diff options
Diffstat (limited to 'shared/nm-utils/nm-macros-internal.h')
| -rw-r--r-- | shared/nm-utils/nm-macros-internal.h | 160 |
1 files changed, 113 insertions, 47 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index 70476b7e..6ca66d29 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -106,12 +106,14 @@ _nm_auto_protect_errno (int *p_saved_errno) #define __NM_UTILS_MACRO_REST_HELPER_ONE(first) #define __NM_UTILS_MACRO_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__ #define __NM_UTILS_MACRO_REST_NUM(...) \ - __NM_UTILS_MACRO_REST_SELECT_20TH(__VA_ARGS__, \ + __NM_UTILS_MACRO_REST_SELECT_30TH(__VA_ARGS__, \ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ + TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) -#define __NM_UTILS_MACRO_REST_SELECT_20TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, ...) a20 +#define __NM_UTILS_MACRO_REST_SELECT_30TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, ...) a30 /*****************************************************************************/ @@ -178,7 +180,7 @@ _nm_auto_protect_errno (int *p_saved_errno) /** * NM_G_ERROR_MSG: - * @error: (allow none): the #GError instance + * @error: (allow-none): the #GError instance * * All functions must follow the convention that when they * return a failure, they must also set the GError to a valid @@ -233,21 +235,34 @@ NM_G_ERROR_MSG (GError *error) #define _NM_IN_SET_EVAL_16(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_15 (op, _x, __VA_ARGS__) #define _NM_IN_SET_EVAL_N2(op, _x, n, ...) (_NM_IN_SET_EVAL_##n(op, _x, __VA_ARGS__)) -#define _NM_IN_SET_EVAL_N(op, x, n, ...) \ +#define _NM_IN_SET_EVAL_N(op, type, x, n, ...) \ ({ \ - typeof(x) _x = (x); \ + type _x = (x); \ + \ + /* trigger a -Wenum-compare warning */ \ + nm_assert (TRUE || _x == (x)); \ + \ !!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__); \ }) +#define _NM_IN_SET(op, type, x, ...) _NM_IN_SET_EVAL_N(op, type, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) + /* Beware that this does short-circuit evaluation (use "||" instead of "|") * which has a possibly unexpected non-function-like behavior. * Use NM_IN_SET_SE if you need all arguments to be evaluted. */ -#define NM_IN_SET(x, ...) _NM_IN_SET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) +#define NM_IN_SET(x, ...) _NM_IN_SET(||, typeof (x), x, __VA_ARGS__) /* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do * short-circuit evaluation, which can make a difference if the arguments have * side-effects. */ -#define NM_IN_SET_SE(x, ...) _NM_IN_SET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) +#define NM_IN_SET_SE(x, ...) _NM_IN_SET(|, typeof (x), x, __VA_ARGS__) + +/* the *_TYPED forms allow to explicitly select the type of "x". This is useful + * if "x" doesn't support typeof (bitfields) or you want to gracefully convert + * a type using automatic type conversion rules (but not forcing the conversion + * with a cast). */ +#define NM_IN_SET_TYPED(type, x, ...) _NM_IN_SET(||, type, x, __VA_ARGS__) +#define NM_IN_SET_SE_TYPED(type, x, ...) _NM_IN_SET(|, type, x, __VA_ARGS__) /*****************************************************************************/ @@ -278,8 +293,8 @@ _NM_IN_STRSET_streq (const char *x, const char *s) #define _NM_IN_STRSET_EVAL_N(op, x, n, ...) \ ({ \ const char *_x = (x); \ - ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, (const char *) NULL, n, __VA_ARGS__)) \ - || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \ + ( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, ((const char *) NULL), n, __VA_ARGS__)) \ + || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \ ); \ }) @@ -341,6 +356,40 @@ _NM_IN_STRSET_streq (const char *x, const char *s) /*****************************************************************************/ +/* NM_CACHED_QUARK() returns the GQuark for @string, but caches + * it in a static variable to speed up future lookups. + * + * @string must be a string literal. + */ +#define NM_CACHED_QUARK(string) \ + ({ \ + static GQuark _nm_cached_quark = 0; \ + \ + (G_LIKELY (_nm_cached_quark != 0) \ + ? _nm_cached_quark \ + : (_nm_cached_quark = g_quark_from_static_string (""string""))); \ + }) + +/* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK + * with two differences: + * - @string must be a quited string-literal + * - @fcn must be the full function name, while G_DEFINE_QUARK() appends + * "_quark" to the function name. + * Both properties of G_DEFINE_QUARK() are non favorable, because you can no + * longer grep for string/fcn -- unless you are aware that you are searching + * for G_DEFINE_QUARK() and omit quotes / append _quark(). With NM_CACHED_QUARK_FCN(), + * ctags/cscope can locate the use of @fcn (though it doesn't recognize that + * NM_CACHED_QUARK_FCN() defines it). + */ +#define NM_CACHED_QUARK_FCN(string, fcn) \ +GQuark \ +fcn (void) \ +{ \ + return NM_CACHED_QUARK (string); \ +} + +/*****************************************************************************/ + #define nm_streq(s1, s2) (strcmp (s1, s2) == 0) #define nm_streq0(s1, s2) (g_strcmp0 (s1, s2) == 0) @@ -435,6 +484,9 @@ _notify (obj_type *obj, _PropertyEnums prop) \ /*****************************************************************************/ +/* these are implemented as a macro, because they accept self + * as both (type*) and (const type*), and return a const + * private pointer accordingly. */ #define __NM_GET_PRIVATE(self, type, is_check, result_cmd) \ ({ \ /* preserve the const-ness of self. Unfortunately, that @@ -442,7 +494,7 @@ _notify (obj_type *obj, _PropertyEnums prop) \ typeof (self) _self = (self); \ \ /* Get compiler error if variable is of wrong type */ \ - _nm_unused const type *_self2 = (_self); \ + _nm_unused const type *const _self2 = (_self); \ \ nm_assert (is_check (_self)); \ ( result_cmd ); \ @@ -451,6 +503,21 @@ _notify (obj_type *obj, _PropertyEnums prop) \ #define _NM_GET_PRIVATE(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check, &_self->_priv) #define _NM_GET_PRIVATE_PTR(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check, _self->_priv) +#define __NM_GET_PRIVATE_VOID(self, type, is_check, result_cmd) \ + ({ \ + /* (self) can be any non-const pointer. It will be cast to "type *". + * We don't explicitly cast but assign first to (void *) which + * will fail if @self is pointing to const. */ \ + void *const _self1 = (self); \ + type *const _self = _self1; \ + \ + nm_assert (is_check (_self)); \ + ( result_cmd ); \ + }) + +#define _NM_GET_PRIVATE_VOID(self, type, is_check) __NM_GET_PRIVATE_VOID(self, type, is_check, &_self->_priv) +#define _NM_GET_PRIVATE_PTR_VOID(self, type, is_check) __NM_GET_PRIVATE_VOID(self, type, is_check, _self->_priv) + /*****************************************************************************/ static inline gpointer @@ -543,16 +610,16 @@ nm_clear_g_cancellable (GCancellable **cancellable) /* Determine whether @x is a power of two (@x being an integer type). * For the special cases @x equals zero or one, it also returns true. - * For negative @x, always returns FALSE. That only applies, if the data - * type of @x is signed. */ + * In case @x being a signed type, for negative @x always return FALSE. */ #define nm_utils_is_power_of_two(x) ({ \ typeof(x) __x = (x); \ \ /* Check if the value is negative. In that case, return FALSE. * The first expression is a compile time constant, depending on whether * the type is signed. The second expression is a clumsy way for (__x >= 0), - * which causes a compiler warning for unsigned types. */ \ - ( ( ((typeof(__x)) -1) > ((typeof(__x)) 0) ) || (__x > 0) || (__x == 0) ) \ + * which otherwise causes a compiler warning for unsigned types. */ \ + ( (((typeof(__x)) -1) > ((typeof(__x)) 0)) \ + || (__x > 0 || __x == 0) ) \ && ((__x & (__x - 1)) == 0); \ }) @@ -561,7 +628,7 @@ nm_clear_g_cancellable (GCancellable **cancellable) /* check if @flags has exactly one flag (@check) set. You should call this * only with @check being a compile time constant and a power of two. */ #define NM_FLAGS_HAS(flags, check) \ - ( (G_STATIC_ASSERT_EXPR ( ((check) != 0) && ((check) & ((check)-1)) == 0 )), (NM_FLAGS_ANY ((flags), (check))) ) + ( G_STATIC_ASSERT_EXPR ((check) > 0 && ((check) & ((check) - 1)) == 0), NM_FLAGS_ANY ((flags), (check)) ) #define NM_FLAGS_ANY(flags, check) ( ( ((flags) & (check)) != 0 ) ? TRUE : FALSE ) #define NM_FLAGS_ALL(flags, check) ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE ) @@ -714,13 +781,15 @@ nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_d /*****************************************************************************/ static inline guint -nm_encode_version (guint major, guint minor, guint micro) { +nm_encode_version (guint major, guint minor, guint micro) +{ /* analog to the preprocessor macro NM_ENCODE_VERSION(). */ return (major << 16) | (minor << 8) | micro; } static inline void -nm_decode_version (guint version, guint *major, guint *minor, guint *micro) { +nm_decode_version (guint version, guint *major, guint *minor, guint *micro) +{ *major = (version & 0xFFFF0000u) >> 16; *minor = (version & 0x0000FF00u) >> 8; *micro = (version & 0x000000FFu); @@ -743,35 +812,33 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro) { /*****************************************************************************/ /* if @str is NULL, return "(null)". Otherwise, allocate a buffer using - * alloca() of size @bufsize and fill it with @str. @str will be quoted with - * single quote, and in case @str is too long, the final quote will be '^'. */ -#define nm_strquote_a(bufsize, str) \ + * alloca() of and fill it with @str. @str will be quoted with double quote. + * If @str is longer then @trunc_at, the string is truncated and the closing + * quote is instead '^' to indicate truncation. + * + * Thus, the maximum stack allocated buffer will be @trunc_at+3. */ +#define nm_strquote_a(trunc_at, str) \ ({ \ - G_STATIC_ASSERT ((bufsize) >= 6); \ - const gsize _BUFSIZE = (bufsize); \ - const char *const _s = (str); \ - char *_r; \ - gsize _l; \ - gboolean _truncated; \ - \ - nm_assert (_BUFSIZE >= 6); \ + const char *const _str = (str); \ \ - if (_s) { \ - _l = strlen (_s) + 3; \ - if ((_truncated = (_BUFSIZE < _l))) \ - _l = _BUFSIZE; \ - \ - _r = g_alloca (_l); \ - _r[0] = '\''; \ - memcpy (&_r[1], _s, _l - 3); \ - _r[_l - 2] = _truncated ? '^' : '\''; \ - _r[_l - 1] = '\0'; \ - } else \ - _r = "(null)"; \ - _r; \ + (_str \ + ? ({ \ + const gsize _trunc_at = (trunc_at); \ + const gsize _strlen_trunc = NM_MIN (strlen (_str), _trunc_at); \ + char *_buf; \ + \ + _buf = g_alloca (_strlen_trunc + 3); \ + _buf[0] = '"'; \ + memcpy (&_buf[1], _str, _strlen_trunc); \ + _buf[_strlen_trunc + 1] = _str[_strlen_trunc] ? '^' : '"'; \ + _buf[_strlen_trunc + 2] = '\0'; \ + _buf; \ + }) \ + : "(null)"); \ }) -#define nm_sprintf_buf(buf, format, ...) ({ \ +#define nm_sprintf_buf(buf, format, ...) \ + ({ \ char * _buf = (buf); \ int _buf_len; \ \ @@ -788,12 +855,12 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro) { ({ \ char *_buf; \ int _buf_len; \ + typeof (n_elements) _n_elements = (n_elements); \ \ - G_STATIC_ASSERT (sizeof (char[MAX ((n_elements), 1)]) == (n_elements)); \ - _buf = g_alloca (n_elements); \ - _buf_len = g_snprintf (_buf, (n_elements), \ + _buf = g_alloca (_n_elements); \ + _buf_len = g_snprintf (_buf, _n_elements, \ ""format"", ##__VA_ARGS__); \ - nm_assert (_buf_len < (n_elements)); \ + nm_assert (_buf_len < _n_elements); \ _buf; \ }) @@ -870,7 +937,6 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro) { #define _G_BOOLEAN_EXPR(expr) __NM_G_BOOLEAN_EXPR_IMPL (NM_UNIQ, expr) #endif - /*****************************************************************************/ #endif /* __NM_MACROS_INTERNAL_H__ */ |