summary refs log tree commit diff
path: root/shared/nm-utils/nm-macros-internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/nm-utils/nm-macros-internal.h')
-rw-r--r--shared/nm-utils/nm-macros-internal.h160
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__ */