libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_macro_utils.h
Go to the documentation of this file.
1/*! \file
2 * \brief Miscellaneous macro utilities and meta generators
3 * \ingroup preprocessor
4 * \sa gimbal_macro_composition.h, gimbal_macro_sequences.h
5 *
6 * \author Falco Girgis
7 * \author 2025 Agustín Bellagamba
8 */
9
10#ifndef GIMBAL_MACRO_UTILS_H
11#define GIMBAL_MACRO_UTILS_H
12
15#include <gimbal/core/gimbal_config.h>
16#include <stdint.h>
17
18#ifdef __cplusplus
19#include <functional>
20extern "C" {
21#endif
22
23#define GBL_MIN(a, b) (((a) < (b))? (a) : (b))
24#define GBL_MAX(a, b) (((a) > (b))? (a) : (b))
25#define GBL_CEIL(numerator, denominator) ((numerator / denominator + (numerator % denominator != 0)))
26#define GBL_CLAMP(n, min, max) (((n) > (max)) ? (max) : (((n) < (min)) ? (min) : (n)))
27
28#define GBL_BIT_MASK_2(bits, offset) (((1u << bits) - 1u) << offset)
29#define GBL_BIT_MASK_1(bits) GBL_BIT_MASK_2(bits, 0)
30#define GBL_BIT_MASK(...) GBL_VA_OVERLOAD_CALL_ARGC(GBL_BIT_MASK, __VA_ARGS__)
31
32#define GBL_BCD_BYTE_PACK(n) (((n / 10) << 4) | (n % 10)) // 0-99
33#define GBL_BCD_BYTE_UNPACK(n) (unsigned)(((n >> 4) * 10) + (n & 0xf))
34
35#define GBL_CONTAINER_OF(ptr, type, member) ((type*)((char*)(ptr) - offsetof(type, member)))
36#define GBL_COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
37
38#define GBL_PTR_OFFSET(...) GBL_VA_OVERLOAD_CALL_ARGC(GBL_PTR_OFFSET, __VA_ARGS__)
39#define GBL_PTR_OFFSET_3(type, ptr, bytes) ((type)(((uintptr_t)ptr) + bytes))
40#define GBL_PTR_OFFSET_2(ptr, bytes) GBL_PTR_OFFSET_3(void*, ptr, bytes)
41
42#define GBL_SWITCH_CASE_STRINGIFY(s) case s: return #s
43
44#define GBL_LABEL_EMPTY(name) name: {;}
45
46#define GBL_SWAP(x,y)
48 unsigned char swap_temp[sizeof(x) == sizeof(y) ?
49 (signed)sizeof(x) : -1];
50 memcpy(swap_temp, &y, sizeof(x));
51 memcpy(&y, &x, sizeof(x));
52 memcpy(&x, swap_temp, sizeof(x));
54
55#define GBL_ASSERT(...)
57
58//! Used to declare an endian-independent group of bitfields.
59#define GBL_BIT_FIELDS(...)
60 GBL_TUPLE_FOREACH(GBL_BIT_FIELDS_ENTRY_, GBL_PHONY, GBL_BIT_FIELDS_ENDIAN_XFORM_ (__VA_ARGS__))
61
62#ifndef __cplusplus
63# define GBL_META_GENERIC_MACRO_GENERATE(traits, X)
64 _Generic((X),
65 GBL_MAP_TUPLES(GBL_META_GENERIC_MACRO_TRAIT_OVERLOADS_DECLARE_CASE_C_,
66 GBL_MAP_TUPLES(GBL_EVAL, GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_OVERLOADS_ traits))
67 default: GBL_EVAL(GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_DEFAULT traits)
68 )
69#else
70# define GBL_META_GENERIC_MACRO_GENERATE(traits, X)
71 [](auto&&... args) {
72 using GenericType = decltype(X);
73 if constexpr(false);
74 GBL_MAP_TUPLES(GBL_META_GENERIC_MACRO_TRAIT_OVERLOADS_DECLARE_CASE_CPP_,
75 GBL_MAP_TUPLES(GBL_EVAL, GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_OVERLOADS_ traits))
76 else if constexpr(requires { GBL_EVAL(GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_DEFAULT_ traits)
77 (std::forward<decltype(args)>(args)...); })
78 return GBL_EVAL(GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_DEFAULT_ traits)(std::forward<decltype(args)>(args)...);
79 }
80#endif
81
82#define GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_DEFAULT(defaultFunc, overloads) defaultFunc
83#define GBL_META_GENERIC_MACRO_NO_DEFAULT GBL_NULL
84
85// ===== Implementation ======
86///\cond
87#define GBL_BIT_FIELDS_ENTRY_(a, b) b;
88
89#if GBL_BIG_ENDIAN
90# define GBL_BIT_FIELDS_ENDIAN_XFORM_(...) (__VA_ARGS__)
91#else
92# define GBL_BIT_FIELDS_ENDIAN_XFORM_(...) (GBL_REVERSE(__VA_ARGS__))
93#endif
94
95#define GBL_META_GENERIC_MACRO_TRAIT_PROPERTY_OVERLOADS_(defaultFunc, overloads) overloads
96#define GBL_META_GENERIC_MACRO_TRAIT_OVERLOADS_PROPERTY_TYPE_(type, function) type
97#define GBL_META_GENERIC_MACRO_TRAIT_OVERLOADS_PROPERTY_FUNCTION_(type, function) function
98
99#define GBL_META_GENERIC_MACRO_TRAIT_OVERLOADS_DECLARE_CASE_C_(type, function)
100 type: function,
101
102#define GBL_META_GENERIC_MACRO_TRAIT_OVERLOADS_DECLARE_CASE_CPP_(type, function)
103 else if constexpr(std::same_as<GenericType, type>) return function(std::forward<decltype(args)>(args)...);
104///\endcond
105#ifdef __cplusplus
106}
107#endif
108
109#define GBL_SCOPE(begin, end) for (int GBL_APPEND_LINE(gblscope_) = ((begin), 0); GBL_APPEND_LINE(gblscope_) < 1; ++GBL_APPEND_LINE(gblscope_), (end))
110#define GBL_SCOPE_EXIT continue
111
112#define GBL_APPEND_LINE(a) GBL_GLUE(GBL_GLUE(a, ), __LINE__)
113
114#endif // GIMBAL_MACRO_UTILS_H
#define GBL_STMT_START
#define GBL_NULL
#define GBL_STMT_END
#define GBL_VA_OVERLOAD_SELECT(BASE, SUFFIXER,...)
#define GBL_GLUE(A, B)
#define GBL_REVERSE(...)
#define GBL_TUPLE_FOREACH(MACRO_, DATA_, TUPLE_)
#define GBL_VA_OVERLOAD_SUFFIXER_ARGC(...)
#define GBL_VA_OVERLOAD_CALL_ARGC(BASE,...)
#define GBL_MAP_TUPLES(f,...)
#define GBL_EVAL(...)
#define GBL_PTR_OFFSET(...)
#define GBL_ASSERT(...)
#define GBL_BIT_MASK_2(bits, offset)
#define GBL_BIT_MASK(...)
#define GBL_APPEND_LINE(a)
#define GBL_PTR_OFFSET_3(type, ptr, bytes)