Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
utils.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#ifndef __ASE_UTILS_HH__
3#define __ASE_UTILS_HH__
4
5#include <ase/defs.hh>
6#include <ase/logging.hh>
7#include <experimental/type_traits>
8#include <any>
9
10namespace Ase {
11
12// == Debugging ==
13inline bool debug_enabled () ASE_ALWAYS_INLINE ASE_PURE;
14bool debug_key_enabled (const char *conditional) ASE_PURE;
15bool debug_key_enabled (const std::string &conditional) ASE_PURE;
16std::string debug_key_value (const char *conditional) ASE_PURE;
17template<class ...A> void debug (const char *cond, const char *format, const A &...args) ASE_ALWAYS_INLINE;
18template<class ...A> void fatal_error (const char *format, const A &...args) ASE_NORETURN;
19template<class ...A> void warning (const char *format, const A &...args);
20template<class... A> void printout (const char *format, const A &...args) ASE_PRINTF (1, 0);
21template<class... A> void printerr (const char *format, const A &...args) ASE_PRINTF (1, 0);
22
23// == misc ==
24const char* ase_gettext (const String &untranslated);
25template<class A0, class... Ar> const char* ase_gettext (const char *format, const A0 &a0, const Ar &...restargs) ASE_PRINTF (1, 0);
26
27// == Date & Time ==
28String now_strftime (const String &format);
29
30// == MakeIcon ==
31namespace MakeIcon {
32IconString KwIcon (const String &keywords);
33IconString UcIcon (const String &unicode);
34IconString SvgIcon (const String &svgdata);
35IconString operator""_uc (const char *key, size_t);
36IconString operator""_icon (const char *key, size_t);
37} // MakeIcon
38
39// == Jump Tables ==
41template<typename MkFun, size_t ...INDICES> static auto
42make_indexed_table (const MkFun &mkjump, std::index_sequence<INDICES...>)
43{
44 constexpr size_t N = sizeof... (INDICES);
45 using Fun = decltype (mkjump (std::integral_constant<std::size_t, N - 1>()));
46 const std::array<Fun, N> jumptable = {
48 };
49 return jumptable;
50}
51
54template<std::size_t LAST, typename MkFun> static auto
55make_case_table (const MkFun &mkjump)
56{
57 return make_indexed_table (mkjump, std::make_index_sequence<LAST + 1>());
58}
59
60// == EventFd ==
63{
64 int fds[2];
65 void operator= (const EventFd&) = delete; // no assignments
66 explicit EventFd (const EventFd&) = delete; // no copying
67public:
68 explicit EventFd ();
69 int open ();
70 bool opened ();
71 void wakeup ();
72 int inputfd ();
73 bool pollin ();
74 void flush ();
75 /*Des*/ ~EventFd ();
76};
77
78// == CustomData ==
80template<typename T>
81class CustomDataKey : public VirtualBase {
82 /*Copy*/ CustomDataKey (const CustomDataKey&) = delete;
83 CustomDataKey& operator= (const CustomDataKey&) = delete;
84public:
85 explicit CustomDataKey () = default;
86 virtual T fallback () { return {}; }
87 const std::type_info& type () const noexcept { return typeid (T); }
88 bool has_value (const std::any &any) { return any.has_value() && any.type() == type(); }
89 T extract (const std::any &any) { return has_value (any) ? std::any_cast<T> (any) : fallback(); }
90};
91
98 struct CustomDataEntry : std::any { VirtualBase *key = nullptr; };
100 std::unique_ptr<CustomDataS> custom_data_;
101 static_assert (sizeof (custom_data_) == sizeof (void*));
102 CustomDataEntry& custom_data_entry (VirtualBase *key);
103 std::any& custom_data_get (VirtualBase *key) const;
104 bool custom_data_del (VirtualBase *key);
105protected:
106 /*dtor*/ ~CustomDataContainer ();
107 void custom_data_destroy ();
108public:
110 template<class T> void set_custom_data (CustomDataKey<T> *key, T data)
111 { std::any a (data); custom_data_entry (key).swap (a); }
113 template<class T> T get_custom_data (CustomDataKey<T> *key) const
114 { return key->extract (custom_data_get (key)); }
116 template<class T> bool has_custom_data (CustomDataKey<T> *key) const
117 { return key->has_value (custom_data_get (key)); }
119 template<class T> bool del_custom_data (CustomDataKey<T> *key)
120 { return custom_data_del (key); }
121};
122
123// == Bit Manipulations ==
125constexpr uint16_t uint16_swap_le_be (uint16_t v);
126
128constexpr uint32_t uint32_swap_le_be (uint32_t v);
129
131constexpr uint64_t uint64_swap_le_be (uint64_t v);
132
133// == Implementation Details ==
134extern inline constexpr uint16_t
136{
137 return (v >> 8) | (v << 8);
138}
139
140extern inline constexpr uint32_t
142{
143 return __builtin_bswap32 (v);
144 return ( ((v & 0x000000ffU) << 24) |
145 ((v & 0x0000ff00U) << 8) |
146 ((v & 0x00ff0000U) >> 8) |
147 ((v & 0xff000000U) >> 24) );
148}
149
150extern inline constexpr uint64_t
152{
153 return __builtin_bswap64 (v);
154 return ( ((v & 0x00000000000000ffUL) << 56) |
155 ((v & 0x000000000000ff00UL) << 40) |
156 ((v & 0x0000000000ff0000UL) << 24) |
157 ((v & 0x00000000ff000000UL) << 8) |
158 ((v & 0x000000ff00000000UL) >> 8) |
159 ((v & 0x0000ff0000000000UL) >> 24) |
160 ((v & 0x00ff000000000000UL) >> 40) |
161 ((v & 0xff00000000000000UL) >> 56) );
162}
163
164void debug_message (const char *cond, const std::string &message);
165void diag_flush (uint8 code, const String &txt);
167
169extern bool ase_debugging_enabled;
171extern bool ase_fatal_warnings;
172
174inline bool ASE_ALWAYS_INLINE ASE_PURE
179
181template<class ...Args> inline void ASE_ALWAYS_INLINE
182debug (const char *cond, const char *format, const Args &...args)
183{
184 if (debug_enabled())
185 {
186 if (ASE_UNLIKELY (debug_key_enabled (cond)))
187 debug_message (cond, string_format (format, args...));
188 }
189}
190
195template<class ...Args> void ASE_NORETURN
196fatal_error (const char *format, const Args &...args)
197{
198 assertion_fatal ((diag_prefix ('F') + string_format (format, args...)).c_str(), nullptr, -1, nullptr);
199}
200
202template<class ...Args> void
203warning (const char *format, const Args &...args)
204{
205 assertion_failed ((diag_prefix ('W') + string_format (format, args...)).c_str(), nullptr, -1, nullptr);
206}
207
209template<class... Args> void
210printout (const char *format, const Args &...args)
211{
212 diag_flush ('o', string_format (format, args...));
213}
214
216template<class... Args> void
217printerr (const char *format, const Args &...args)
218{
219 diag_flush ('e', string_format (format, args...));
220}
221
223template<class A0, class... Ar> const char*
224ase_gettext (const char *format, const A0 &a0, const Ar &...restargs)
225{
226 return ase_gettext (string_format (format, a0, restargs...));
227}
228
230namespace Aux {
231
232template<typename T>
233using callable_reserve_int = decltype (std::declval<T&>().reserve (int (0)));
234template<typename T>
235using callable_minus = decltype (std::declval<T>() - std::declval<T>());
236
238template<class Container, class Iteratable> Container
239container_copy (const Iteratable &source)
240{
241 Container c;
242 const auto b = std::begin (source), e = std::end (source);
244 std::experimental::is_detected<callable_minus, decltype (b)>::value) {
245 c.reserve (e - b);
246 }
247 std::copy (b, e, std::back_inserter (c));
248 return c;
249}
250
251// == Binary Lookups ==
252template<typename RandIter, class Cmp, typename Arg, int case_lookup_or_sibling_or_insertion>
253extern inline std::pair<RandIter,bool>
254binary_lookup_fuzzy (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
255{
256 RandIter current = end;
257 size_t n_elements = end - begin, offs = 0;
258 const bool want_lookup = case_lookup_or_sibling_or_insertion == 0;
259 // const bool want_sibling = case_lookup_or_sibling_or_insertion == 1;
260 const bool want_insertion_pos = case_lookup_or_sibling_or_insertion > 1;
261 ssize_t cmp = 0;
262 while (offs < n_elements)
263 {
264 size_t i = (offs + n_elements) >> 1;
265 current = begin + i;
266 cmp = cmp_elements (arg, *current);
267 if (cmp == 0)
268 return want_insertion_pos ? std::make_pair (current, true) : std::make_pair (current, /*ignored*/ false);
269 else if (cmp < 0)
270 n_elements = i;
271 else /* (cmp > 0) */
272 offs = i + 1;
273 }
274 /* check is last mismatch, cmp > 0 indicates greater key */
275 return (want_lookup
276 ? std::make_pair (end, /*ignored*/ false)
277 : (want_insertion_pos && cmp > 0)
278 ? std::make_pair (current + 1, false)
279 : std::make_pair (current, false));
280}
281
287template<typename RandIter, class Cmp, typename Arg>
288extern inline std::pair<RandIter,bool>
289binary_lookup_insertion_pos (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
290{
291 return binary_lookup_fuzzy<RandIter,Cmp,Arg,2> (begin, end, cmp_elements, arg);
292}
293
299template<typename RandIter, class Cmp, typename Arg>
300extern inline RandIter
301binary_lookup_sibling (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
302{
303 return binary_lookup_fuzzy<RandIter,Cmp,Arg,1> (begin, end, cmp_elements, arg).first;
304}
305
311template<typename RandIter, class Cmp, typename Arg>
312extern inline RandIter
313binary_lookup (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
314{
315 /* return end or exact match */
316 return binary_lookup_fuzzy<RandIter,Cmp,Arg,0> (begin, end, cmp_elements, arg).first;
317}
318
320template<typename Value> static inline int
321compare_lesser (const Value &v1, const Value &v2)
322{
323 return -(v1 < v2) | (v2 < v1);
324}
325
327template<typename Value> static inline int
328compare_greater (const Value &v1, const Value &v2)
329{
330 return (v1 < v2) | -(v2 < v1);
331}
332
333// == Vector Utils ==
334
336template<class C> inline size_t
337erase_first (C &container, const std::function<bool (typename C::value_type const &value)> &pred)
338{
339 for (auto iter = container.begin(); iter != container.end(); iter++)
340 if (pred (*iter))
341 {
342 container.erase (iter);
343 return 1;
344 }
345 return 0;
346}
347
349template<class C> inline size_t
350erase_all (C &container, const std::function<bool (typename C::value_type const &value)> &pred)
351{
352 size_t c = 0;
353 for (auto iter = container.begin(); iter != container.end(); )
354 if (pred (*iter))
355 {
356 iter = container.erase (iter);
357 c++;
358 }
359 else
360 iter++;
361 return c;
362}
363
365template<typename C> inline bool
366contains (const C &container, const std::function<bool (typename C::value_type const &value)> &pred)
367{
368 for (auto iter = container.begin(); iter != container.end(); iter++)
369 if (pred (*iter))
370 return true;
371 return false;
372}
373
375template<class T, class Compare> inline typename std::vector<T>::iterator
376insert_sorted (std::vector<T> &vec, const T &value, Compare compare)
377{
378 static_assert (std::is_signed<decltype (std::declval<Compare>() (std::declval<T>(), std::declval<T>()))>::value, "REQUIRE: int Compare (const&, const&);");
379 auto insmatch = binary_lookup_insertion_pos (vec.begin(), vec.end(), compare, value);
380 auto it = insmatch.first;
381 return vec.insert (it, value);
382}
383
384template<class IterableContainer> ssize_t
385index_of (const IterableContainer &c, const std::function<bool(const typename IterableContainer::value_type &e)> &match)
386{
387 ssize_t index = 0;
388 for (auto it = std::begin (c); it != std::end (c); ++index, ++it)
389 if (match (*it))
390 return index;
391 return -1;
392}
393
394} // Aux
395
396} // Ase
397
398#endif // __ASE_UTILS_HH__
T back_inserter(T... args)
T begin(T... args)
T get_custom_data(CustomDataKey< T > *key) const
Retrieve contents of the custom keyed data member, returns DataKey::fallback if nothing was set.
Definition utils.hh:113
bool has_custom_data(CustomDataKey< T > *key) const
Retrieve wether contents of the custom keyed data member exists.
Definition utils.hh:116
bool del_custom_data(CustomDataKey< T > *key)
Delete the current contents of the custom keyed data member, invokes DataKey::destroy.
Definition utils.hh:119
void set_custom_data(CustomDataKey< T > *key, T data)
Assign data to the custom keyed data member, deletes any previously set data.
Definition utils.hh:110
CustomDataKey objects are used to identify and manage custom data members of CustomDataContainer obje...
Definition utils.hh:81
virtual T fallback()
Return default T instance.
Definition utils.hh:86
const std::type_info & type() const noexcept
Return the typeid of T.
Definition utils.hh:87
Wakeup facility for IPC.
Definition utils.hh:63
bool opened()
Indicates whether eventfd has been opened.
Definition utils.cc:246
void flush()
Clear pending wakeups.
Definition utils.cc:280
int inputfd()
Returns the file descriptor for POLLIN.
Definition utils.cc:240
bool pollin()
Checks whether events are pending.
Definition utils.cc:252
int open()
Opens the eventfd and returns -errno.
Definition utils.cc:206
void wakeup()
Wakeup polling end.
Definition utils.cc:263
T copy(T... args)
#define ASE_UNLIKELY(expr)
Compiler hint to optimize for expr evaluating to false.
Definition cxxaux.hh:46
T end(T... args)
T has_value(T... args)
T make_pair(T... args)
std::vector< T >::iterator insert_sorted(std::vector< T > &vec, const T &value, Compare compare)
Insert value into sorted vec using binary_lookup_insertion_pos() with compare.
Definition utils.hh:376
Container container_copy(const Iteratable &source)
Create a Container with copies of the elements of source.
Definition utils.hh:239
RandIter binary_lookup_sibling(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Definition utils.hh:301
size_t erase_all(C &container, const std::function< bool(typename C::value_type const &value)> &pred)
Erase all elements for which pred() is true in vector or list.
Definition utils.hh:350
size_t erase_first(C &container, const std::function< bool(typename C::value_type const &value)> &pred)
Erase first element for which pred() is true in vector or list.
Definition utils.hh:337
RandIter binary_lookup(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Definition utils.hh:313
std::pair< RandIter, bool > binary_lookup_insertion_pos(RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
Definition utils.hh:289
bool contains(const C &container, const std::function< bool(typename C::value_type const &value)> &pred)
Returns true if container element for which pred() is true.
Definition utils.hh:366
The Anklang C++ API namespace.
Definition api.hh:9
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
constexpr uint64_t uint64_swap_le_be(uint64_t v)
Swap 64-Bit integers between __BIG_ENDIAN and __LITTLE_ENDIAN systems.
Definition utils.hh:151
bool debug_key_enabled(const char *conditional)
Check if conditional is enabled by $ASE_DEBUG.
Definition utils.cc:38
bool ase_fatal_warnings
Global boolean to cause the program to abort on warnings.
Definition utils.cc:20
void assertion_failed(const char *msg, const char *file, int line, const char *func) noexcept
Print instructive message, handle "breakpoint", "backtrace" and "fatal-warnings" in $ASE_DEBUG.
Definition cxxaux.cc:122
String diag_prefix(uint8 code)
Create prefix for warnings and errors.
Definition utils.cc:88
uint8_t uint8
An 8-bit unsigned integer.
Definition cxxaux.hh:22
constexpr uint32_t uint32_swap_le_be(uint32_t v)
Swap 32-Bit integers between __BIG_ENDIAN and __LITTLE_ENDIAN systems.
Definition utils.hh:141
void diag_flush(uint8 code, const String &txt)
Handle stdout and stderr printing with flushing.
Definition utils.cc:79
void assertion_fatal(const char *msg, const char *file, int line, const char *func) noexcept
Print a debug message via assertion_failed() and abort the program.
Definition cxxaux.cc:110
constexpr uint16_t uint16_swap_le_be(uint16_t v)
Swap 16-Bit integers between __BIG_ENDIAN and __LITTLE_ENDIAN systems.
Definition utils.hh:135
bool ase_debugging_enabled
Global boolean to reduce debugging penalty where possible.
Definition utils.cc:19
bool debug_enabled() ASE_PURE
Check if any kind of debugging is enabled by $ASE_DEBUG.
Definition utils.hh:175
void debug_message(const char *cond, const std::string &message)
Print a debug message, called from Ase::debug().
Definition utils.cc:61
std::string String
Convenience alias for std::string.
Definition cxxaux.hh:35
::std::string debug_key_value(const char *conditional)
Retrieve the value assigned to debug key conditional in $ASE_DEBUG.
Definition utils.cc:53
typedef uint16_t
Value type used to interface with various property types.
Definition value.hh:54
Common base type to allow casting between polymorphic classes.
Definition cxxaux.hh:214
typedef ssize_t
T type(T... args)
IconString SvgIcon(const String &svgdata)
Create an IconString consisting of an SVG string.
Definition utils.cc:188
IconString UcIcon(const String &unicode)
Create an IconString consisting of a single/double unicode character.
Definition utils.cc:166
IconString KwIcon(const String &keywords)
Create an IconString consisting of keywords.
Definition utils.cc:135