diff options
Diffstat (limited to 'src/libnm-std-aux/nm-std-aux.h')
| -rw-r--r-- | src/libnm-std-aux/nm-std-aux.h | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h index d310305e..3b39a019 100644 --- a/src/libnm-std-aux/nm-std-aux.h +++ b/src/libnm-std-aux/nm-std-aux.h @@ -154,6 +154,12 @@ typedef uint64_t _nm_bitwise nm_be64_t; /*****************************************************************************/ +#define _NM_INT_IS_SIGNED(arg) (!(((typeof(arg)) -1) > 0)) + +#define _NM_INT_SAME_SIGNEDNESS(arg1, arg2) (_NM_INT_IS_SIGNED(arg1) == _NM_INT_IS_SIGNED(arg2)) + +/*****************************************************************************/ + #define NM_PASTE_ARGS(identifier1, identifier2) identifier1##identifier2 #define NM_PASTE(identifier1, identifier2) NM_PASTE_ARGS(identifier1, identifier2) @@ -386,37 +392,63 @@ nm_mult_clamped_u(unsigned a, unsigned b) return c; } -/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate - * the argument possibly twice. - * - * Taken from systemd's MIN()/MAX() macros. */ - -#define NM_MIN(a, b) __NM_MIN(NM_UNIQ, a, NM_UNIQ, b) -#define __NM_MIN(aq, a, bq, b) \ - ({ \ - typeof(a) NM_UNIQ_T(A, aq) = (a); \ - typeof(b) NM_UNIQ_T(B, bq) = (b); \ - ((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ +/* In a few places where a constant expression is required, NM_MIN() doesn't work. + * In that case, use NM_MIN_CONST(). */ +#define NM_MIN_CONST(a, b) \ + ((NM_STATIC_ASSERT_EXPR_1(_NM_INT_SAME_SIGNEDNESS((a), (b)) && __builtin_constant_p((a)) \ + && __builtin_constant_p((b))) \ + && ((a) <= (b))) \ + ? (a) \ + : (b)) + +#define _NM_MIN_V(aq, a, bq, b) \ + ({ \ + typeof(a) NM_UNIQ_T(A, aq) = (a); \ + typeof(b) NM_UNIQ_T(B, bq) = (b); \ + \ + ((NM_UNIQ_T(A, aq) <= NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ }) -#define NM_MAX(a, b) __NM_MAX(NM_UNIQ, a, NM_UNIQ, b) -#define __NM_MAX(aq, a, bq, b) \ - ({ \ - typeof(a) NM_UNIQ_T(A, aq) = (a); \ - typeof(b) NM_UNIQ_T(B, bq) = (b); \ - ((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ +#define NM_MIN(a, b) \ + __builtin_choose_expr(__builtin_constant_p((a)) && __builtin_constant_p((b)) \ + && NM_STATIC_ASSERT_EXPR_1(_NM_INT_SAME_SIGNEDNESS((a), (b))), \ + (((a) <= (b)) ? (a) : (b)), \ + _NM_MIN_V(NM_UNIQ, a, NM_UNIQ, b)) + +#define NM_MAX_CONST(a, b) \ + ((NM_STATIC_ASSERT_EXPR_1(_NM_INT_SAME_SIGNEDNESS((a), (b)) && __builtin_constant_p((a)) \ + && __builtin_constant_p((b))) \ + && ((a) >= (b))) \ + ? (a) \ + : (b)) + +#define _NM_MAX_V(aq, a, bq, b) \ + ({ \ + typeof(a) NM_UNIQ_T(A, aq) = (a); \ + typeof(b) NM_UNIQ_T(B, bq) = (b); \ + \ + ((NM_UNIQ_T(A, aq) >= NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ }) +#define NM_MAX(a, b) \ + __builtin_choose_expr(__builtin_constant_p((a)) && __builtin_constant_p((b)) \ + && NM_STATIC_ASSERT_EXPR_1(_NM_INT_SAME_SIGNEDNESS((a), (b))), \ + (((a) >= (b)) ? (a) : (b)), \ + _NM_MAX_V(NM_UNIQ, a, NM_UNIQ, b)) + #define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high) -#define __NM_CLAMP(xq, x, lowq, low, highq, high) \ - ({ \ - typeof(x) NM_UNIQ_T(X, xq) = (x); \ - typeof(low) NM_UNIQ_T(LOW, lowq) = (low); \ - typeof(high) NM_UNIQ_T(HIGH, highq) = (high); \ - \ - ((NM_UNIQ_T(X, xq) > NM_UNIQ_T(HIGH, highq)) ? NM_UNIQ_T(HIGH, highq) \ - : (NM_UNIQ_T(X, xq) < NM_UNIQ_T(LOW, lowq)) ? NM_UNIQ_T(LOW, lowq) \ - : NM_UNIQ_T(X, xq)); \ +#define __NM_CLAMP(xq, x, lowq, low, highq, high) \ + ({ \ + typeof(x) NM_UNIQ_T(X, xq) = (x); \ + typeof(low) NM_UNIQ_T(LOW, lowq) = (low); \ + typeof(high) NM_UNIQ_T(HIGH, highq) = (high); \ + \ + NM_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(NM_UNIQ_T(X, xq), NM_UNIQ_T(LOW, lowq))); \ + NM_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(NM_UNIQ_T(X, xq), NM_UNIQ_T(HIGH, highq))); \ + \ + ((NM_UNIQ_T(X, xq) > NM_UNIQ_T(HIGH, highq)) ? NM_UNIQ_T(HIGH, highq) \ + : (NM_UNIQ_T(X, xq) < NM_UNIQ_T(LOW, lowq)) ? NM_UNIQ_T(LOW, lowq) \ + : NM_UNIQ_T(X, xq)); \ }) #define NM_MAX_WITH_CMP(cmp, a, b) \ @@ -427,13 +459,6 @@ nm_mult_clamped_u(unsigned a, unsigned b) (((cmp(_a, _b)) >= 0) ? _a : _b); \ }) -/* evaluates to (void) if _A or _B are not constant or of different types */ -#define NM_CONST_MAX(_A, _B) \ - (__builtin_choose_expr((__builtin_constant_p(_A) && __builtin_constant_p(_B) \ - && __builtin_types_compatible_p(typeof(_A), typeof(_B))), \ - ((_A) > (_B)) ? (_A) : (_B), \ - ((void) 0))) - /* Determine whether @x is a power of two (@x being an integer type). * Basically, this returns TRUE, if @x has exactly one bit set. * For negative values and zero, this always returns FALSE. */ @@ -1287,13 +1312,15 @@ nm_ptr_to_uintptr(const void *p) /*****************************************************************************/ -#define NM_CMP_DIRECT(a, b) \ - do { \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - \ - if (_a != _b) \ - return (_a < _b) ? -1 : 1; \ +#define NM_CMP_DIRECT(a, b) \ + do { \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + \ + NM_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(_a, _b)); \ + \ + if (_a != _b) \ + return (_a < _b) ? -1 : 1; \ } while (0) #define NM_CMP_DIRECT_UNSAFE(a, b) \ |