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>2018-10-20 01:30:31 +0200
committerMichael Biebl <biebl@debian.org>2018-10-20 01:30:31 +0200
commit6518e361171f64bcaaa4bf868139362ed95cc2e0 (patch)
treed2d5b53faf80646a40ec2c0c7f2a42b3959612f5 /shared/nm-utils/nm-macros-internal.h
parente126f3e804c35480c4f075777430419d6ece23da (diff)
New upstream version 1.14.2 upstream/1.14.2
Diffstat (limited to 'shared/nm-utils/nm-macros-internal.h')
-rw-r--r--shared/nm-utils/nm-macros-internal.h289
1 files changed, 235 insertions, 54 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index ef3039e6..084219b4 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -16,6 +16,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
+ * (C) Copyright 2012 Colin Walters <walters@verbum.org>.
  * (C) Copyright 2014 Red Hat, Inc.
  */
 
@@ -25,6 +26,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <string.h>
+
+#include <gio/gio.h>
+
+/*****************************************************************************/
 
 #define _nm_packed           __attribute__ ((packed))
 #define _nm_unused           __attribute__ ((unused))
@@ -34,6 +40,8 @@
 #define _nm_align(s)         __attribute__ ((aligned (s)))
 #define _nm_alignof(type)    __alignof (type)
 #define _nm_alignas(type)    _nm_align (_nm_alignof (type))
+#define nm_auto(fcn)         __attribute__ ((cleanup(fcn)))
+
 
 #if __GNUC__ >= 7
 #define _nm_fallthrough      __attribute__ ((fallthrough))
@@ -57,13 +65,146 @@
 
 /*****************************************************************************/
 
+#define NM_AUTO_DEFINE_FCN_VOID(CastType, name, func) \
+static inline void name (void *v) \
+{ \
+	func (*((CastType *) v)); \
+}
+
+#define NM_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \
+static inline void name (void *v) \
+{ \
+	if (*((CastType *) v)) \
+		func (*((CastType *) v)); \
+}
+
+#define NM_AUTO_DEFINE_FCN(Type, name, func) \
+static inline void name (Type *v) \
+{ \
+	func (*v); \
+}
+
+#define NM_AUTO_DEFINE_FCN0(Type, name, func) \
+static inline void name (Type *v) \
+{ \
+	if (*v) \
+		func (*v); \
+}
+
+/*****************************************************************************/
+
+/**
+ * gs_free:
+ *
+ * Call g_free() on a variable location when it goes out of scope.
+ */
+#define gs_free nm_auto(gs_local_free)
+NM_AUTO_DEFINE_FCN_VOID (void *, gs_local_free, g_free)
+
+/**
+ * gs_unref_object:
+ *
+ * Call g_object_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_object_unref(), the variable may be
+ * %NULL.
+ */
+#define gs_unref_object nm_auto(gs_local_obj_unref)
+NM_AUTO_DEFINE_FCN_VOID0 (GObject *, gs_local_obj_unref, g_object_unref)
+
+/**
+ * gs_unref_variant:
+ *
+ * Call g_variant_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_variant_unref(), the variable may be
+ * %NULL.
+ */
+#define gs_unref_variant nm_auto(gs_local_variant_unref)
+NM_AUTO_DEFINE_FCN0 (GVariant *, gs_local_variant_unref, g_variant_unref)
+
+/**
+ * gs_unref_array:
+ *
+ * Call g_array_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_array_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_array nm_auto(gs_local_array_unref)
+NM_AUTO_DEFINE_FCN0 (GArray *, gs_local_array_unref, g_array_unref)
+
+/**
+ * gs_unref_ptrarray:
+ *
+ * Call g_ptr_array_unref() on a variable location when it goes out of
+ * scope.  Note that unlike g_ptr_array_unref(), the variable may be
+ * %NULL.
+
+ */
+#define gs_unref_ptrarray nm_auto(gs_local_ptrarray_unref)
+NM_AUTO_DEFINE_FCN0 (GPtrArray *, gs_local_ptrarray_unref, g_ptr_array_unref)
+
+/**
+ * gs_unref_hashtable:
+ *
+ * Call g_hash_table_unref() on a variable location when it goes out
+ * of scope.  Note that unlike g_hash_table_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_hashtable nm_auto(gs_local_hashtable_unref)
+NM_AUTO_DEFINE_FCN0 (GHashTable *, gs_local_hashtable_unref, g_hash_table_unref)
+
+/**
+ * gs_free_slist:
+ *
+ * Call g_slist_free() on a variable location when it goes out
+ * of scope.
+ */
+#define gs_free_slist nm_auto(gs_local_free_slist)
+NM_AUTO_DEFINE_FCN (GSList *, gs_local_free_slist, g_slist_free)
+
+/**
+ * gs_unref_bytes:
+ *
+ * Call g_bytes_unref() on a variable location when it goes out
+ * of scope.  Note that unlike g_bytes_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_bytes nm_auto(gs_local_bytes_unref)
+NM_AUTO_DEFINE_FCN0 (GBytes *, gs_local_bytes_unref, g_bytes_unref)
+
+/**
+ * gs_strfreev:
+ *
+ * Call g_strfreev() on a variable location when it goes out of scope.
+ */
+#define gs_strfreev nm_auto(gs_local_strfreev)
+NM_AUTO_DEFINE_FCN (char **, gs_local_strfreev, g_strfreev)
+
+/**
+ * gs_free_error:
+ *
+ * Call g_error_free() on a variable location when it goes out of scope.
+ */
+#define gs_free_error nm_auto(gs_local_free_error)
+NM_AUTO_DEFINE_FCN0 (GError *, gs_local_free_error, g_error_free)
+
+/**
+ * gs_unref_keyfile:
+ *
+ * Call g_key_file_unref() on a variable location when it goes out of scope.
+ */
+#define gs_unref_keyfile nm_auto(gs_local_keyfile_unref)
+NM_AUTO_DEFINE_FCN0 (GKeyFile *, gs_local_keyfile_unref, g_key_file_unref)
+
+/*****************************************************************************/
+
 #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);
 
@@ -71,59 +212,49 @@ static inline int nm_close (int fd);
  * nm_auto_free:
  *
  * Call free() on a variable location when it goes out of scope.
+ * This is for pointers that are allocated with malloc() instead of
+ * g_malloc().
+ *
+ * In practice, since glib 2.45, g_malloc()/g_free() always wraps malloc()/free().
+ * See bgo#751592. In that case, it would be safe to free pointers allocated with
+ * malloc() with gs_free or g_free().
+ *
+ * However, let's never mix them. To free malloc'ed memory, always use
+ * free() or nm_auto_free.
  */
+NM_AUTO_DEFINE_FCN_VOID (void *, _nm_auto_free_impl, free)
 #define nm_auto_free nm_auto(_nm_auto_free_impl)
-GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free)
 
-static inline void
-nm_free_secret (char *secret)
-{
-	if (secret) {
-		memset (secret, 0, strlen (secret));
-		g_free (secret);
-	}
-}
+NM_AUTO_DEFINE_FCN0 (GVariantIter *, _nm_auto_free_variant_iter, g_variant_iter_free)
+#define nm_auto_free_variant_iter nm_auto(_nm_auto_free_variant_iter)
 
-static inline void
-_nm_auto_free_secret_impl (char **v)
-{
-	nm_free_secret (*v);
-}
+NM_AUTO_DEFINE_FCN0 (GVariantBuilder *, _nm_auto_unref_variant_builder, g_variant_builder_unref)
+#define nm_auto_unref_variant_builder nm_auto(_nm_auto_unref_variant_builder)
 
-/**
- * nm_auto_free_secret:
- *
- * Call g_free() on a variable location when it goes out of scope.
- * Also, previously, calls memset(loc, 0, strlen(loc)) to clear out
- * the secret.
- */
-#define nm_auto_free_secret nm_auto(_nm_auto_free_secret_impl)
+NM_AUTO_DEFINE_FCN (GList *, _nm_auto_free_list, g_list_free)
+#define nm_auto_free_list nm_auto(_nm_auto_free_list)
 
-static inline void
-_nm_auto_unset_gvalue_impl (GValue *v)
-{
-	g_value_unset (v);
-}
-#define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl)
+NM_AUTO_DEFINE_FCN0 (GChecksum *, _nm_auto_checksum_free, g_checksum_free)
+#define nm_auto_free_checksum nm_auto(_nm_auto_checksum_free)
 
-static inline void
-_nm_auto_unref_gtypeclass (gpointer v)
-{
-	if (v && *((gpointer *) v))
-		g_type_class_unref (*((gpointer *) v));
-}
+#define nm_auto_unset_gvalue nm_auto(g_value_unset)
+
+NM_AUTO_DEFINE_FCN_VOID0 (void *, _nm_auto_unref_gtypeclass, g_type_class_unref)
 #define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
 
+NM_AUTO_DEFINE_FCN0 (GByteArray *, _nm_auto_unref_bytearray, g_byte_array_unref)
+#define nm_auto_unref_bytearray nm_auto(_nm_auto_unref_bytearray)
+
 static inline void
-_nm_auto_free_gstring_impl (GString **str)
+_nm_auto_free_gstring (GString **str)
 {
 	if (*str)
 		g_string_free (*str, TRUE);
 }
-#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring_impl)
+#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring)
 
 static inline void
-_nm_auto_close_impl (int *pfd)
+_nm_auto_close (int *pfd)
 {
 	if (*pfd >= 0) {
 		int errsv = errno;
@@ -132,10 +263,10 @@ _nm_auto_close_impl (int *pfd)
 		errno = errsv;
 	}
 }
-#define nm_auto_close nm_auto(_nm_auto_close_impl)
+#define nm_auto_close nm_auto(_nm_auto_close)
 
 static inline void
-_nm_auto_fclose_impl (FILE **pfd)
+_nm_auto_fclose (FILE **pfd)
 {
 	if (*pfd) {
 		int errsv = errno;
@@ -144,7 +275,7 @@ _nm_auto_fclose_impl (FILE **pfd)
 		errno = errsv;
 	}
 }
-#define nm_auto_fclose nm_auto(_nm_auto_fclose_impl)
+#define nm_auto_fclose nm_auto(_nm_auto_fclose)
 
 static inline void
 _nm_auto_protect_errno (int *p_saved_errno)
@@ -153,13 +284,25 @@ _nm_auto_protect_errno (int *p_saved_errno)
 }
 #define NM_AUTO_PROTECT_ERRNO(errsv_saved) nm_auto(_nm_auto_protect_errno) _nm_unused const int errsv_saved = (errno)
 
+NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_unref_gsource, g_source_unref);
+#define nm_auto_unref_gsource nm_auto(_nm_auto_unref_gsource)
+
 static inline void
-_nm_auto_unref_gsource (GSource **ptr)
+_nm_auto_freev (gpointer ptr)
 {
-	if (*ptr)
-		g_source_unref (g_steal_pointer (ptr));
+	gpointer **p = ptr;
+	gpointer *_ptr;
+
+	if (*p) {
+		for (_ptr = *p; *_ptr; _ptr++)
+			g_free (*_ptr);
+		g_free (*p);
+	}
 }
-#define nm_auto_unref_gsource nm_auto(_nm_auto_unref_gsource)
+/* g_free a NULL terminated array of pointers, with also freeing each
+ * pointer with g_free(). It essentially does the same as
+ * gs_strfreev / g_strfreev(), but not restricted to strv arrays. */
+#define nm_auto_freev nm_auto(_nm_auto_freev)
 
 /*****************************************************************************/
 
@@ -184,13 +327,16 @@ _nm_auto_unref_gsource (GSource **ptr)
 
 /*****************************************************************************/
 
-/* http://stackoverflow.com/a/2124385/354393 */
+/* http://stackoverflow.com/a/2124385/354393
+ * https://stackoverflow.com/questions/11317474/macro-to-count-number-of-arguments
+ */
 
 #define NM_NARG(...) \
-         _NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N())
+         _NM_NARG(, ##__VA_ARGS__, _NM_NARG_RSEQ_N())
 #define _NM_NARG(...) \
          _NM_NARG_ARG_N(__VA_ARGS__)
 #define _NM_NARG_ARG_N( \
+          _0, \
           _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, \
@@ -261,7 +407,7 @@ _nm_auto_unref_gsource (GSource **ptr)
 static inline const char *
 NM_G_ERROR_MSG (GError *error)
 {
-	return error ? (error->message ? : "(null)") : "(no-error)"; \
+	return error ? (error->message ?: "(null)") : "(no-error)"; \
 }
 
 /*****************************************************************************/
@@ -754,7 +900,7 @@ nm_str_realloc (char *str)
 
 #define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \
 typedef enum { \
-	_PROPERTY_ENUMS_0, \
+	PROP_0, \
 	__VA_ARGS__ \
 	_PROPERTY_ENUMS_LAST, \
 } _PropertyEnums; \
@@ -763,12 +909,39 @@ static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, }
 #define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
 NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \
 static inline void \
-_notify (obj_type *obj, _PropertyEnums prop) \
+_nm_gobject_notify_together_impl (obj_type *obj, guint n, const _PropertyEnums *props) \
 { \
+	const gboolean freeze_thaw = (n > 1); \
+	\
 	nm_assert (G_IS_OBJECT (obj)); \
-	nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \
-	g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \
-}
+	nm_assert (n > 0); \
+	\
+	if (freeze_thaw) \
+		g_object_freeze_notify ((GObject *) obj); \
+	while (n-- > 0) { \
+		const _PropertyEnums prop = *props++; \
+		\
+		if (prop != PROP_0) { \
+			nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \
+			nm_assert (obj_properties[prop]); \
+			g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \
+		} \
+	} \
+	if (freeze_thaw) \
+		g_object_thaw_notify ((GObject *) obj); \
+} \
+\
+static inline void \
+_notify (obj_type *obj, _PropertyEnums prop) \
+{ \
+	_nm_gobject_notify_together_impl (obj, 1, &prop); \
+} \
+
+/* invokes _notify() for all arguments (of type _PropertyEnums). Note, that if
+ * there are more than one prop arguments, this will involve a freeze/thaw
+ * of GObject property notifications. */
+#define nm_gobject_notify_together(obj, ...) \
+	_nm_gobject_notify_together_impl (obj, NM_NARG (__VA_ARGS__), (const _PropertyEnums[]) { __VA_ARGS__ })
 
 /*****************************************************************************/
 
@@ -943,6 +1116,14 @@ nm_clear_g_cancellable (GCancellable **cancellable)
 		 && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \
 	})
 
+#define NM_DIV_ROUND_UP(x, y) \
+	({ \
+		const typeof(x) _x = (x); \
+		const typeof(y) _y = (y); \
+		\
+		(_x / _y + !!(_x % _y)); \
+	})
+
 /*****************************************************************************/
 
 #define NM_UTILS_LOOKUP_DEFAULT(v)            return (v)
@@ -1261,7 +1442,7 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
  * Using _Bool has advantages over gboolean:
  *
  * - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean
- *   is a typedef for gint). Especially when having boolean fields in a struct, we can
+ *   is a typedef for int). Especially when having boolean fields in a struct, we can
  *   thereby easily save some space.
  *
  * - _Bool type guarantees that two "true" expressions compare equal. E.g. the follwing