summary refs log tree commit diff
path: root/shared/nm-macros-internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/nm-macros-internal.h')
-rw-r--r--shared/nm-macros-internal.h357
1 files changed, 357 insertions, 0 deletions
diff --git a/shared/nm-macros-internal.h b/shared/nm-macros-internal.h
new file mode 100644
index 00000000..7bddb4bd
--- /dev/null
+++ b/shared/nm-macros-internal.h
@@ -0,0 +1,357 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_MACROS_INTERNAL_H__
+#define __NM_MACROS_INTERNAL_H__
+
+#include "nm-default.h"
+
+/********************************************************/
+
+/* http://stackoverflow.com/a/11172679 */
+#define  _NM_UTILS_MACRO_FIRST(...)                           __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway)
+#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...)             first
+
+#define  _NM_UTILS_MACRO_REST(...)                            __NM_UTILS_MACRO_REST_HELPER(__NM_UTILS_MACRO_REST_NUM(__VA_ARGS__), __VA_ARGS__)
+#define __NM_UTILS_MACRO_REST_HELPER(qty, ...)                __NM_UTILS_MACRO_REST_HELPER2(qty, __VA_ARGS__)
+#define __NM_UTILS_MACRO_REST_HELPER2(qty, ...)               __NM_UTILS_MACRO_REST_HELPER_##qty(__VA_ARGS__)
+#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__, \
+                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
+
+/********************************************************/
+
+/* http://stackoverflow.com/a/2124385/354393 */
+
+#define NM_NARG(...) \
+         _NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N())
+#define _NM_NARG(...) \
+         _NM_NARG_ARG_N(__VA_ARGS__)
+#define _NM_NARG_ARG_N( \
+          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+         _61,_62,_63,N,...) N
+#define _NM_NARG_RSEQ_N() \
+         63,62,61,60,                   \
+         59,58,57,56,55,54,53,52,51,50, \
+         49,48,47,46,45,44,43,42,41,40, \
+         39,38,37,36,35,34,33,32,31,30, \
+         29,28,27,26,25,24,23,22,21,20, \
+         19,18,17,16,15,14,13,12,11,10, \
+         9,8,7,6,5,4,3,2,1,0
+
+/********************************************************/
+
+#if defined (__GNUC__)
+#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(GCC diagnostic ignored warning)
+#elif defined (__clang__)
+#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(clang diagnostic ignored warning)
+#endif
+
+/* you can only suppress a specific warning that the compiler
+ * understands. Otherwise you will get another compiler warning
+ * about invalid pragma option.
+ * It's not that bad however, because gcc and clang often have the
+ * same name for the same warning. */
+
+#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define NM_PRAGMA_WARNING_DISABLE(warning) \
+        _Pragma("GCC diagnostic push") \
+        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
+#elif defined (__clang__)
+#define NM_PRAGMA_WARNING_DISABLE(warning) \
+        _Pragma("clang diagnostic push") \
+        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
+#else
+#define NM_PRAGMA_WARNING_DISABLE(warning)
+#endif
+
+#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define NM_PRAGMA_WARNING_REENABLE \
+    _Pragma("GCC diagnostic pop")
+#elif defined (__clang__)
+#define NM_PRAGMA_WARNING_REENABLE \
+    _Pragma("clang diagnostic pop")
+#else
+#define NM_PRAGMA_WARNING_REENABLE
+#endif
+
+/********************************************************/
+
+/* macro to return strlen() of a compile time string. */
+#define STRLEN(str)     ( sizeof ("" str) - 1 )
+
+#define NM_SET_OUT(out_val, value) \
+	G_STMT_START { \
+		typeof(*(out_val)) *_out_val = (out_val); \
+		\
+		if (_out_val) { \
+			*_out_val = (value); \
+		} \
+	} G_STMT_END
+
+/********************************************************/
+
+#define _NM_IN_SET_EVAL_1(op, x, y1)                              \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_2(op, x, y1, y2)                          \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_3(op, x, y1, y2, y3)                      \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+         op (_x == (y3))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_4(op, x, y1, y2, y3, y4)                  \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+         op (_x == (y3))                                          \
+         op (_x == (y4))                                          \
+        );                                                        \
+    })
+
+#define _NM_IN_SET_EVAL_5(op, x, y1, y2, y3, y4, y5)              \
+    ({                                                            \
+        typeof(x) _x = (x);                                       \
+        (   (_x == (y1))                                          \
+         op (_x == (y2))                                          \
+         op (_x == (y3))                                          \
+         op (_x == (y4))                                          \
+         op (_x == (y5))                                          \
+        );                                                        \
+    })
+
+#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, ...)         _NM_IN_SET_EVAL_N2(op, x, n, __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__)
+
+/* "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_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \
+	(cond) ? (prefix) : "", \
+	(cond) ? (str) : (str_else), \
+	(cond) ? (suffix) : ""
+#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)")
+
+/*****************************************************************************/
+
+#if NM_MORE_ASSERTS
+#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END
+#else
+#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END
+#endif
+
+/*****************************************************************************/
+
+static inline gboolean
+nm_clear_g_source (guint *id)
+{
+	if (id && *id) {
+		g_source_remove (*id);
+		*id = 0;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static inline gboolean
+nm_clear_g_signal_handler (gpointer self, gulong *id)
+{
+	if (id && *id) {
+		g_signal_handler_disconnect (self, *id);
+		*id = 0;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static inline gboolean
+nm_clear_g_variant (GVariant **variant)
+{
+	if (variant && *variant) {
+		g_variant_unref (*variant);
+		*variant = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static inline gboolean
+nm_clear_g_cancellable (GCancellable **cancellable)
+{
+	if (cancellable && *cancellable) {
+		g_cancellable_cancel (*cancellable);
+		g_object_unref (*cancellable);
+		*cancellable = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/*****************************************************************************/
+
+/* 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. */
+#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) ) \
+		 && ((__x & (__x - 1)) == 0); \
+	})
+
+/*****************************************************************************/
+
+/* 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))) )
+
+#define NM_FLAGS_ANY(flags, check)  ( ( ((flags) & (check)) != 0       ) ? TRUE : FALSE )
+#define NM_FLAGS_ALL(flags, check)  ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE )
+
+#define NM_FLAGS_SET(flags, val)  ({ \
+		const typeof(flags) _flags = (flags); \
+		const typeof(flags) _val = (val); \
+		\
+		_flags | _val; \
+	})
+
+#define NM_FLAGS_UNSET(flags, val)  ({ \
+		const typeof(flags) _flags = (flags); \
+		const typeof(flags) _val = (val); \
+		\
+		_flags & (~_val); \
+	})
+
+#define NM_FLAGS_ASSIGN(flags, val, assign)  ({ \
+		const typeof(flags) _flags = (flags); \
+		const typeof(flags) _val = (val); \
+		\
+		(assign) \
+			? _flags | (_val) \
+			: _flags & (~_val); \
+	})
+
+/*****************************************************************************/
+
+#define _NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, ORIG_FUNC, VERSIONED_FUNC, ARGS_TYPED, ARGS) \
+RETURN_TYPE VERSIONED_FUNC ARGS_TYPED; \
+RETURN_TYPE VERSIONED_FUNC ARGS_TYPED \
+{ \
+    return ORIG_FUNC ARGS; \
+} \
+RETURN_TYPE ORIG_FUNC ARGS_TYPED; \
+__asm__(".symver "G_STRINGIFY(VERSIONED_FUNC)", "G_STRINGIFY(ORIG_FUNC)"@"G_STRINGIFY(VERSION))
+
+#define NM_BACKPORT_SYMBOL(VERSION, RETURN_TYPE, FUNC, ARGS_TYPED, ARGS) \
+_NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, FUNC, _##FUNC##_##VERSION, ARGS_TYPED, ARGS)
+
+/*****************************************************************************/
+
+static inline char *
+nm_strstrip (char *str)
+{
+	/* g_strstrip doesn't like NULL. */
+	return str ? g_strstrip (str) : NULL;
+}
+
+/*****************************************************************************/
+
+static inline guint
+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) {
+	*major = (version & 0xFFFF0000u) >> 16;
+	*minor = (version & 0x0000FF00u) >>  8;
+	*micro = (version & 0x000000FFu);
+}
+/*****************************************************************************/
+
+#define nm_sprintf_buf(buf, format, ...) ({ \
+		char * _buf = (buf); \
+		\
+		/* some static assert trying to ensure that the buffer is statically allocated.
+		 * It disallows a buffer size of sizeof(gpointer) to catch that. */ \
+		G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *)); \
+		g_snprintf (_buf, sizeof (buf), \
+		            ""format"", __VA_ARGS__); \
+		_buf; \
+	})
+
+#define nm_sprintf_bufa(n_elements, format, ...) \
+	({ \
+		char *_buf; \
+		\
+		G_STATIC_ASSERT (sizeof (char[MAX ((n_elements), 1)]) == (n_elements)); \
+		_buf = g_alloca (n_elements); \
+		g_snprintf (_buf, n_elements, \
+		            ""format"", __VA_ARGS__); \
+		_buf; \
+	})
+
+/*****************************************************************************/
+
+#endif /* __NM_MACROS_INTERNAL_H__ */