summary refs log tree commit diff
path: root/shared/nm-utils/nm-macros-internal.h
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2017-11-07 00:14:39 +0100
committerMichael Biebl <biebl@debian.org>2017-11-07 00:14:39 +0100
commit90e8691111889a7b5f3c812f5a41f15a8a058913 (patch)
treef101a879eca27c34a9bfa5f3da52266b22539a36 /shared/nm-utils/nm-macros-internal.h
parentbdb6eeb0670658255c2a4c3c501c0a27fa8cfe55 (diff)
New upstream version 1.9.90 upstream/1.9.90
Diffstat (limited to 'shared/nm-utils/nm-macros-internal.h')
-rw-r--r--shared/nm-utils/nm-macros-internal.h276
1 files changed, 262 insertions, 14 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index 5fe4bc50..d9dab83d 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -26,20 +26,41 @@
 #include <stdlib.h>
 #include <errno.h>
 
-#include "nm-glib.h"
+#define _nm_packed           __attribute__ ((packed))
+#define _nm_unused           __attribute__ ((unused))
+#define _nm_pure             __attribute__ ((pure))
+#define _nm_const            __attribute__ ((const))
+#define _nm_printf(a,b)      __attribute__ ((__format__ (__printf__, a, b)))
+#define _nm_align(s)         __attribute__ ((aligned (s)))
+#define _nm_alignof(type)    __alignof (type)
+#define _nm_alignas(type)    _nm_align (_nm_alignof (type))
+
+/*****************************************************************************/
+
+#ifdef thread_local
+#define _nm_thread_local thread_local
+/*
+ * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
+ * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
+ */
+#elif __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
+#define _nm_thread_local _Thread_local
+#else
+#define _nm_thread_local __thread
+#endif
 
 /*****************************************************************************/
 
-#define _nm_packed __attribute__ ((packed))
-#define _nm_unused __attribute__ ((unused))
-#define _nm_pure   __attribute__ ((pure))
-#define _nm_const  __attribute__ ((const))
-#define _nm_printf(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#include "nm-glib.h"
+
+/*****************************************************************************/
 
 #define nm_offsetofend(t,m) (G_STRUCT_OFFSET (t,m) + sizeof (((t *) NULL)->m))
 
 #define nm_auto(fcn) __attribute__ ((cleanup(fcn)))
 
+static inline int nm_close (int fd);
+
 /**
  * nm_auto_free:
  *
@@ -56,6 +77,14 @@ _nm_auto_unset_gvalue_impl (GValue *v)
 #define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl)
 
 static inline void
+_nm_auto_unref_gtypeclass (gpointer v)
+{
+	if (v && *((gpointer *) v))
+		g_type_class_unref (*((gpointer *) v));
+}
+#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
+
+static inline void
 _nm_auto_free_gstring_impl (GString **str)
 {
 	if (*str)
@@ -69,7 +98,7 @@ _nm_auto_close_impl (int *pfd)
 	if (*pfd >= 0) {
 		int errsv = errno;
 
-		(void) close (*pfd);
+		(void) nm_close (*pfd);
 		errno = errsv;
 	}
 }
@@ -201,6 +230,23 @@ NM_G_ERROR_MSG (GError *error)
 /* macro to return strlen() of a compile time string. */
 #define NM_STRLEN(str)     ( sizeof ("" str) - 1 )
 
+/* returns the length of a NULL terminated array of pointers,
+ * like g_strv_length() does. The difference is:
+ *  - it operats on arrays of pointers (of any kind, requiring no cast).
+ *  - it accepts NULL to return zero. */
+#define NM_PTRARRAY_LEN(array) \
+	({ \
+		typeof (*(array)) *const _array = (array); \
+		gsize _n = 0; \
+		\
+		if (_array) { \
+			_nm_unused typeof (*(_array[0])) *_array_check = _array[0]; \
+			while (_array[_n]) \
+				_n++; \
+		} \
+		_n; \
+	})
+
 /* Note: @value is only evaluated when *out_val is present.
  * Thus,
  *    NM_SET_OUT (out_str, g_strdup ("hallo"));
@@ -217,6 +263,47 @@ NM_G_ERROR_MSG (GError *error)
 
 /*****************************************************************************/
 
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__))
+#define _NM_CC_SUPPORT_GENERIC 1
+#else
+#define _NM_CC_SUPPORT_GENERIC 0
+#endif
+
+#if _NM_CC_SUPPORT_GENERIC
+#define _NM_CONSTCAST(type, obj) \
+	(_Generic ((obj), \
+	           void *           : ((type *) (obj)), \
+	           void *const      : ((type *) (obj)), \
+	           const void *     : ((const type *) (obj)), \
+	           const void *const: ((const type *) (obj)), \
+	           const type *     : (obj), \
+	           const type *const: (obj), \
+	           type *           : (obj), \
+	           type *const      : (obj)))
+#else
+/* _NM_CONSTCAST() is there to preserve constness of a pointer.
+ * It uses C11's _Generic(). If that is not supported, we fall back
+ * to casting away constness. So, with _Generic, we get some additional
+ * static type checking by preserving constness, without, we cast it
+ * to a non-const pointer. */
+#define _NM_CONSTCAST(type, obj) \
+	((type *) (obj))
+#endif
+
+#if _NM_CC_SUPPORT_GENERIC
+/* returns @value, if the type of @value matches @type.
+ * This requires support for C11 _Generic(). If no support is
+ * present, this returns @value directly.
+ *
+ * It's useful to check the let the compiler ensure that @value is
+ * of a certain type. */
+#define _NM_ENSURE_TYPE(type, value) (_Generic ((value), type: (value)))
+#else
+#define _NM_ENSURE_TYPE(type, value) (value)
+#endif
+
+/*****************************************************************************/
+
 #define _NM_IN_SET_EVAL_1( op, _x, y)           (_x == (y))
 #define _NM_IN_SET_EVAL_2( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_1  (op, _x, __VA_ARGS__)
 #define _NM_IN_SET_EVAL_3( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_2  (op, _x, __VA_ARGS__)
@@ -395,6 +482,16 @@ fcn (void) \
 
 /*****************************************************************************/
 
+static inline GString *
+nm_gstring_prepare (GString **l)
+{
+	if (*l)
+		g_string_set_size (*l, 0);
+	else
+		*l = g_string_sized_new (30);
+	return *l;
+}
+
 static inline const char *
 nm_str_not_empty (const char *str)
 {
@@ -487,7 +584,7 @@ _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) \
+#define __NM_GET_PRIVATE(self, type, is_check, addrop) \
 	({ \
 		/* preserve the const-ness of self. Unfortunately, that
 		 * way, @self cannot be a void pointer */ \
@@ -497,11 +594,11 @@ _notify (obj_type *obj, _PropertyEnums prop) \
 		_nm_unused const type *const _self2 = (_self); \
 		\
 		nm_assert (is_check (_self)); \
-		( result_cmd ); \
+		( addrop ( _NM_CONSTCAST (type, _self)->_priv) ); \
 	})
 
-#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(self, type, is_check)     __NM_GET_PRIVATE(self, type, is_check, &)
+#define _NM_GET_PRIVATE_PTR(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check,  )
 
 #define __NM_GET_PRIVATE_VOID(self, type, is_check, result_cmd) \
 	({ \
@@ -540,6 +637,36 @@ nm_g_object_unref (gpointer obj)
 		g_object_unref (obj);
 }
 
+/* Assigns GObject @obj to destination @pdst, and takes an additional ref.
+ * The previous value of @pdst is unrefed.
+ *
+ * It makes sure to first increase the ref-count of @obj, and handles %NULL
+ * @obj correctly.
+ * */
+#define nm_g_object_ref_set(pp, obj) \
+	({ \
+		typeof (*(pp)) *const _pp = (pp); \
+		typeof (**_pp) *const _obj = (obj); \
+		typeof (**_pp) *_p; \
+		gboolean _changed = FALSE; \
+		\
+		if (   _pp \
+		    && ((_p = *_pp) != _obj)) { \
+			if (_obj) { \
+				nm_assert (G_IS_OBJECT (_obj)); \
+				 g_object_ref (_obj); \
+			} \
+			if (_p) { \
+				nm_assert (G_IS_OBJECT (_p)); \
+				*_pp = NULL; \
+				g_object_unref (_p); \
+			} \
+			*_pp = _obj; \
+			_changed = TRUE; \
+		} \
+		_changed; \
+	})
+
 /* basically, replaces
  *   g_clear_pointer (&location, g_free)
  * with
@@ -552,13 +679,32 @@ nm_g_object_unref (gpointer obj)
 #define nm_clear_g_free(pp) \
 	({  \
 		typeof (*(pp)) *_pp = (pp); \
-		typeof (**_pp) *_p = *_pp; \
+		typeof (**_pp) *_p; \
+		gboolean _changed = FALSE; \
 		\
-		if (_p) { \
+		if (  _pp \
+		    && (_p = *_pp)) { \
 			*_pp = NULL; \
 			g_free (_p); \
+			_changed = TRUE; \
+		} \
+		_changed; \
+	})
+
+#define nm_clear_g_object(pp) \
+	({ \
+		typeof (*(pp)) *_pp = (pp); \
+		typeof (**_pp) *_p; \
+		gboolean _changed = FALSE; \
+		\
+		if (   _pp \
+		    && (_p = *_pp)) { \
+			nm_assert (G_IS_OBJECT (_p)); \
+			*_pp = NULL; \
+			g_object_unref (_p); \
+			_changed = TRUE; \
 		} \
-		!!_p; \
+		_changed; \
 	})
 
 static inline gboolean
@@ -620,6 +766,50 @@ nm_clear_g_cancellable (GCancellable **cancellable)
 
 /*****************************************************************************/
 
+#define NM_UTILS_LOOKUP_DEFAULT(v)            return (v)
+#define NM_UTILS_LOOKUP_DEFAULT_WARN(v)       g_return_val_if_reached (v)
+#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v)  { nm_assert_not_reached (); return (v); }
+#define NM_UTILS_LOOKUP_ITEM(v, n)            (void) 0; case v: return (n); (void) 0
+#define NM_UTILS_LOOKUP_STR_ITEM(v, n)        NM_UTILS_LOOKUP_ITEM(v, ""n"")
+#define NM_UTILS_LOOKUP_ITEM_IGNORE(v)        (void) 0; case v: break; (void) 0
+#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER()   (void) 0; default: break; (void) 0
+
+#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
+scope result_type \
+fcn_name (lookup_type val) \
+{ \
+	switch (val) { \
+		(void) 0, \
+		__VA_ARGS__ \
+		(void) 0; \
+	}; \
+	{ unknown_val; } \
+}
+
+#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
+	_NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
+#define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \
+	_NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
+
+/* Call the string-lookup-table function @fcn_name. If the function returns
+ * %NULL, the numeric index is converted to string using a alloca() buffer.
+ * Beware: this macro uses alloca(). */
+#define NM_UTILS_LOOKUP_STR(fcn_name, idx) \
+	({ \
+		typeof (idx) _idx = (idx); \
+		const char *_s; \
+		\
+		_s = fcn_name (_idx); \
+		if (!_s) { \
+			_s = g_alloca (30); \
+			\
+			g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \
+		} \
+		_s; \
+	})
+
+/*****************************************************************************/
+
 /* 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)  \
@@ -686,6 +876,33 @@ nm_strstrip (char *str)
 	return str ? g_strstrip (str) : NULL;
 }
 
+static inline const char *
+nm_strstrip_avoid_copy (const char *str, char **str_free)
+{
+	gsize l;
+	char *s;
+
+	nm_assert (str_free && !*str_free);
+
+	if (!str)
+		return NULL;
+
+	str = nm_str_skip_leading_spaces (str);
+	l = strlen (str);
+	if (   l == 0
+	    || !g_ascii_isspace (str[l - 1]))
+		return str;
+	while (   l > 0
+	       && g_ascii_isspace (str[l - 1]))
+		l--;
+
+	s = g_new (char, l + 1);
+	memcpy (s, str, l);
+	s[l] = '\0';
+	*str_free = s;
+	return s;
+}
+
 /* g_ptr_array_sort()'s compare function takes pointers to the
  * value. Thus, you cannot use strcmp directly. You can use
  * nm_strcmp_p().
@@ -934,4 +1151,35 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
 
 /*****************************************************************************/
 
+static inline int
+nm_steal_fd (int *p_fd)
+{
+	int fd;
+
+	if (   p_fd
+	    && ((fd = *p_fd) >= 0)) {
+		*p_fd = -1;
+		return fd;
+	}
+	return -1;
+}
+
+/**
+ * nm_close:
+ *
+ * Like close() but throws an assertion if the input fd is
+ * invalid.  Closing an invalid fd is a programming error, so
+ * it's better to catch it early.
+ */
+static inline int
+nm_close (int fd)
+{
+	if (fd >= 0) {
+		if (close (fd) == 0)
+			return 0;
+		nm_assert (errno != EBADF);
+	}
+	return -1;
+}
+
 #endif /* __NM_MACROS_INTERNAL_H__ */