diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2019-01-30 23:18:06 +0100 |
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2019-04-18 12:44:29 +0200 |
| commit | 0d019561bd855b6097b75d8d95a4dc69e410aae1 (patch) | |
| tree | d704db707170f1fbc7bccb170b72d97834b74c90 /lib/compiler.h | |
| parent | 440d5faa3a328e226435785afe7793251746175f (diff) | |
lib: move/redo some macros
Signed-off-by: David Lamparter <equinox@diac24.net>
Diffstat (limited to 'lib/compiler.h')
| -rw-r--r-- | lib/compiler.h | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/compiler.h b/lib/compiler.h index cb4f7531ec..02bdbd6afd 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -69,6 +69,10 @@ extern "C" { #define _FALLTHROUGH #endif +/* for helper functions defined inside macros */ +#define macro_inline static inline __attribute__((unused)) +#define macro_pure static inline __attribute__((unused, pure)) + /* * for warnings on macros, put in the macro content like this: * #define MACRO BLA CPP_WARN("MACRO has been deprecated") @@ -92,6 +96,80 @@ extern "C" { #define CPP_NOTICE(text) #endif +/* MAX / MIN are not commonly defined, but useful */ +/* note: glibc sys/param.h has #define MIN(a,b) (((a)<(b))?(a):(b)) */ +#ifdef MAX +#undef MAX +#endif +#define MAX(a, b) \ + ({ \ + typeof(a) _max_a = (a); \ + typeof(b) _max_b = (b); \ + _max_a > _max_b ? _max_a : _max_b; \ + }) +#ifdef MIN +#undef MIN +#endif +#define MIN(a, b) \ + ({ \ + typeof(a) _min_a = (a); \ + typeof(b) _min_b = (b); \ + _min_a < _min_b ? _min_a : _min_b; \ + }) + +#ifndef offsetof +#ifdef __compiler_offsetof +#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER) +#else +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif +#endif + +/* this variant of container_of() retains 'const' on pointers without needing + * to be told to do so. The following will all work without warning: + * + * struct member *p; + * const struct member *cp; + * + * const struct cont *x = container_of(cp, struct cont, member); + * const struct cont *x = container_of(cp, const struct cont, member); + * const struct cont *x = container_of(p, struct cont, member); + * const struct cont *x = container_of(p, const struct cont, member); + * struct cont *x = container_of(p, struct cont, member); + * + * but the following will generate warnings about stripping const: + * + * struct cont *x = container_of(cp, struct cont, member); + * struct cont *x = container_of(cp, const struct cont, member); + * struct cont *x = container_of(p, const struct cont, member); + */ +#ifdef container_of +#undef container_of +#endif +#define container_of(ptr, type, member) \ + (__builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(&((type *)0)->member), \ + typeof(ptr)) \ + || __builtin_types_compatible_p(void *, typeof(ptr)), \ + ({ \ + typeof(((type *)0)->member) *__mptr = (void *)(ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); \ + }), \ + ({ \ + typeof(((const type *)0)->member) *__mptr = (ptr); \ + (const type *)((const char *)__mptr - \ + offsetof(type, member)); \ + }) \ + )) + +#define container_of_null(ptr, type, member) \ + ({ \ + typeof(ptr) _tmp = (ptr); \ + _tmp ? container_of(_tmp, type, member) : NULL; \ + }) + +#define array_size(ar) (sizeof(ar) / sizeof(ar[0])) + #ifdef __cplusplus } #endif |
