summary refs log tree commit diff
path: root/shared/nm-glib-aux/nm-shared-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/nm-glib-aux/nm-shared-utils.h')
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h3019
1 files changed, 1596 insertions, 1423 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index b17c8d1a..83e1c284 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: LGPL-2.1+
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /*
  * Copyright (C) 2016 Red Hat, Inc.
  */
@@ -8,35 +8,51 @@
 
 #include <netinet/in.h>
 
+static inline gboolean
+nm_is_ascii(char ch)
+{
+    return ((uint8_t) ch) < 128;
+}
+
 /*****************************************************************************/
 
-pid_t nm_utils_gettid (void);
+pid_t nm_utils_gettid(void);
 
-gboolean _nm_assert_on_main_thread (void);
+gboolean _nm_assert_on_main_thread(void);
 
 #if NM_MORE_ASSERTS > 5
-#define NM_ASSERT_ON_MAIN_THREAD() G_STMT_START { nm_assert (_nm_assert_on_main_thread ()); } G_STMT_END
+    #define NM_ASSERT_ON_MAIN_THREAD()              \
+        G_STMT_START                                \
+        {                                           \
+            nm_assert(_nm_assert_on_main_thread()); \
+        }                                           \
+        G_STMT_END
 #else
-#define NM_ASSERT_ON_MAIN_THREAD() G_STMT_START {                                         ; } G_STMT_END
+    #define NM_ASSERT_ON_MAIN_THREAD() \
+        G_STMT_START                   \
+        {                              \
+            ;                          \
+        }                              \
+        G_STMT_END
 #endif
 
 /*****************************************************************************/
 
 static inline gboolean
-_NM_INT_NOT_NEGATIVE (gssize val)
-{
-	/* whether an enum (without negative values) is a signed int, depends on compiler options
-	 * and compiler implementation.
-	 *
-	 * When using such an enum for accessing an array, one naturally wants to check
-	 * that the enum is not negative. However, the compiler doesn't like a plain
-	 * comparison "enum_val >= 0", because (if the enum is unsigned), it will warn
-	 * that the expression is always true *duh*. Not even a cast to a signed
-	 * type helps to avoid the compiler warning in any case.
-	 *
-	 * The sole purpose of this function is to avoid a compiler warning, when checking
-	 * that an enum is not negative. */
-	return val >= 0;
+_NM_INT_NOT_NEGATIVE(gssize val)
+{
+    /* whether an enum (without negative values) is a signed int, depends on compiler options
+     * and compiler implementation.
+     *
+     * When using such an enum for accessing an array, one naturally wants to check
+     * that the enum is not negative. However, the compiler doesn't like a plain
+     * comparison "enum_val >= 0", because (if the enum is unsigned), it will warn
+     * that the expression is always true *duh*. Not even a cast to a signed
+     * type helps to avoid the compiler warning in any case.
+     *
+     * The sole purpose of this function is to avoid a compiler warning, when checking
+     * that an enum is not negative. */
+    return val >= 0;
 }
 
 /* check whether the integer value is smaller than G_MAXINT32. This macro exists
@@ -47,133 +63,127 @@ _NM_INT_NOT_NEGATIVE (gssize val)
  * exists to catch cases where that is not true.
  *
  * Together with the G_STATIC_ASSERT(), we make sure that this is always satisfied. */
-G_STATIC_ASSERT (sizeof (int) == sizeof (gint32));
+G_STATIC_ASSERT(sizeof(int) == sizeof(gint32));
 #if _NM_CC_SUPPORT_GENERIC
-#define _NM_INT_LE_MAXINT32(value) \
-	({ \
-		_nm_unused typeof (value) _value = (value); \
-		\
-		_Generic((value), \
-		         int: TRUE \
-		); \
-	})
+    #define _NM_INT_LE_MAXINT32(value)                 \
+        ({                                             \
+            _nm_unused typeof(value) _value = (value); \
+                                                       \
+            _Generic((value), int : TRUE);             \
+        })
 #else
-#define _NM_INT_LE_MAXINT32(value) ({ \
-		_nm_unused typeof (value) _value = (value); \
-		_nm_unused const int *_p_value = &_value; \
-		\
-		TRUE; \
-	})
+    #define _NM_INT_LE_MAXINT32(value)                 \
+        ({                                             \
+            _nm_unused typeof(value) _value = (value); \
+            _nm_unused const int *_p_value  = &_value; \
+                                                       \
+            TRUE;                                      \
+        })
 #endif
 
 /*****************************************************************************/
 
-static inline char
-nm_utils_addr_family_to_char (int addr_family)
-{
-	switch (addr_family) {
-	case AF_UNSPEC: return 'X';
-	case AF_INET:   return '4';
-	case AF_INET6:  return '6';
-	}
-	g_return_val_if_reached ('?');
-}
+typedef struct {
+    guint8 ether_addr_octet[6 /*ETH_ALEN*/];
+} NMEtherAddr;
+
+#define NM_ETHER_ADDR_FORMAT_STR "%02X:%02X:%02X:%02X:%02X:%02X"
+#define NM_ETHER_ADDR_FORMAT_VAL(x)                                            \
+    (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], \
+        (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
+#define NM_ETHER_ADDR_INIT(...)            \
+    {                                      \
+        .ether_addr_octet = {__VA_ARGS__}, \
+    }
 
-static inline gsize
-nm_utils_addr_family_to_size (int addr_family)
+static inline int
+nm_ether_addr_cmp(const NMEtherAddr *a, const NMEtherAddr *b)
 {
-	switch (addr_family) {
-	case AF_INET:  return sizeof (in_addr_t);
-	case AF_INET6: return sizeof (struct in6_addr);
-	}
-	g_return_val_if_reached (0);
+    NM_CMP_SELF(a, b);
+    NM_CMP_DIRECT_MEMCMP(a, b, sizeof(NMEtherAddr));
+    return 0;
 }
 
-static inline int
-nm_utils_addr_family_from_size (gsize len)
+static inline gboolean
+nm_ether_addr_equal(const NMEtherAddr *a, const NMEtherAddr *b)
 {
-	switch (len) {
-	case sizeof (in_addr_t):       return AF_INET;
-	case sizeof (struct in6_addr): return AF_INET6;
-	}
-	return AF_UNSPEC;
+    return nm_ether_addr_cmp(a, b) == 0;
 }
 
-#define nm_assert_addr_family(addr_family) \
-	nm_assert (NM_IN_SET ((addr_family), AF_INET, AF_INET6))
-
 /*****************************************************************************/
 
 typedef struct {
-	union {
-		guint8 addr_ptr[1];
-		in_addr_t addr4;
-		struct in_addr addr4_struct;
-		struct in6_addr addr6;
-
-		/* NMIPAddr is really a union for IP addresses.
-		 * However, as ethernet addresses fit in here nicely, use
-		 * it also for an ethernet MAC address. */
-		guint8 addr_eth[6 /*ETH_ALEN*/];
-
-		guint8 array[sizeof (struct in6_addr)];
-	};
+    union {
+        guint8          addr_ptr[1];
+        in_addr_t       addr4;
+        struct in_addr  addr4_struct;
+        struct in6_addr addr6;
+
+        /* NMIPAddr is really a union for IP addresses.
+         * However, as ethernet addresses fit in here nicely, use
+         * it also for an ethernet MAC address. */
+        guint8      ether_addr_octet[6 /*ETH_ALEN*/];
+        NMEtherAddr ether_addr;
+
+        guint8 array[sizeof(struct in6_addr)];
+    };
 } NMIPAddr;
 
-#define NM_IP_ADDR_INIT { .array = { 0 } }
+#define NM_IP_ADDR_INIT \
+    {                   \
+        .array = { 0 }  \
+    }
 
 extern const NMIPAddr nm_ip_addr_zero;
 
+#define nm_ether_addr_zero (nm_ip_addr_zero.ether_addr)
+
 static inline int
-nm_ip_addr_cmp (int addr_family, gconstpointer a, gconstpointer b)
+nm_ip_addr_cmp(int addr_family, gconstpointer a, gconstpointer b)
 {
-	nm_assert_addr_family (addr_family);
-	nm_assert (a);
-	nm_assert (b);
+    nm_assert_addr_family(addr_family);
+    nm_assert(a);
+    nm_assert(b);
 
-	return memcmp (a, b, nm_utils_addr_family_to_size (addr_family));
+    return memcmp(a, b, nm_utils_addr_family_to_size(addr_family));
 }
 
 static inline gboolean
-nm_ip_addr_equal (int addr_family, gconstpointer a, gconstpointer b)
+nm_ip_addr_equal(int addr_family, gconstpointer a, gconstpointer b)
 {
-	return nm_ip_addr_cmp (addr_family, a, b) == 0;
+    return nm_ip_addr_cmp(addr_family, a, b) == 0;
 }
 
 static inline gboolean
-nm_ip_addr_is_null (int addr_family, gconstpointer addr)
+nm_ip_addr_is_null(int addr_family, gconstpointer addr)
 {
-	nm_assert (addr);
-	if (addr_family == AF_INET6)
-		return IN6_IS_ADDR_UNSPECIFIED ((const struct in6_addr *) addr);
-	nm_assert (addr_family == AF_INET);
-	return ((const struct in_addr *) addr)->s_addr == 0;
+    nm_assert(addr);
+    if (addr_family == AF_INET6)
+        return IN6_IS_ADDR_UNSPECIFIED((const struct in6_addr *) addr);
+    nm_assert(addr_family == AF_INET);
+    return ((const struct in_addr *) addr)->s_addr == 0;
 }
 
 static inline void
-nm_ip_addr_set (int addr_family, gpointer dst, gconstpointer src)
+nm_ip_addr_set(int addr_family, gpointer dst, gconstpointer src)
 {
-	nm_assert_addr_family (addr_family);
-	nm_assert (dst);
-	nm_assert (src);
+    nm_assert_addr_family(addr_family);
+    nm_assert(dst);
+    nm_assert(src);
 
-	memcpy (dst,
-	        src,
-	        (addr_family != AF_INET6)
-	          ? sizeof (in_addr_t)
-	          : sizeof (struct in6_addr));
+    memcpy(dst, src, (addr_family != AF_INET6) ? sizeof(in_addr_t) : sizeof(struct in6_addr));
 }
 
-gboolean nm_ip_addr_set_from_untrusted (int addr_family,
-                                        gpointer dst,
-                                        gconstpointer src,
-                                        gsize src_len,
-                                        int *out_addr_family);
+gboolean nm_ip_addr_set_from_untrusted(int           addr_family,
+                                       gpointer      dst,
+                                       gconstpointer src,
+                                       gsize         src_len,
+                                       int *         out_addr_family);
 
 static inline gboolean
-nm_ip4_addr_is_localhost (in_addr_t addr4)
+nm_ip4_addr_is_localhost(in_addr_t addr4)
 {
-	return (addr4 & htonl (0xFF000000u)) == htonl (0x7F000000u);
+    return (addr4 & htonl(0xFF000000u)) == htonl(0x7F000000u);
 }
 
 /*****************************************************************************/
@@ -181,17 +191,17 @@ nm_ip4_addr_is_localhost (in_addr_t addr4)
 struct ether_addr;
 
 static inline int
-nm_utils_ether_addr_cmp (const struct ether_addr *a1, const struct ether_addr *a2)
+nm_utils_ether_addr_cmp(const struct ether_addr *a1, const struct ether_addr *a2)
 {
-	nm_assert (a1);
-	nm_assert (a2);
-	return memcmp (a1, a2, 6 /*ETH_ALEN*/);
+    nm_assert(a1);
+    nm_assert(a2);
+    return memcmp(a1, a2, 6 /*ETH_ALEN*/);
 }
 
 static inline gboolean
-nm_utils_ether_addr_equal (const struct ether_addr *a1, const struct ether_addr *a2)
+nm_utils_ether_addr_equal(const struct ether_addr *a1, const struct ether_addr *a2)
 {
-	return nm_utils_ether_addr_cmp (a1, a2) == 0;
+    return nm_utils_ether_addr_cmp(a1, a2) == 0;
 }
 
 /*****************************************************************************/
@@ -199,743 +209,652 @@ nm_utils_ether_addr_equal (const struct ether_addr *a1, const struct ether_addr
 #define NM_UTILS_INET_ADDRSTRLEN INET6_ADDRSTRLEN
 
 static inline const char *
-nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst)
+nm_utils_inet_ntop(int addr_family, gconstpointer addr, char *dst)
 {
-	const char *s;
+    const char *s;
 
-	const char *inet_ntop (int af,
-	                       const void *src,
-	                       char *dst,
-	                       socklen_t size);
+    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
 
-	nm_assert_addr_family (addr_family);
-	nm_assert (addr);
-	nm_assert (dst);
+    nm_assert_addr_family(addr_family);
+    nm_assert(addr);
+    nm_assert(dst);
 
-	s = inet_ntop (addr_family,
-	               addr,
-	               dst,
-	               addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN);
-	nm_assert (s);
-	return s;
+    s = inet_ntop(addr_family,
+                  addr,
+                  dst,
+                  addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN);
+    nm_assert(s);
+    return s;
 }
 
 static inline const char *
-_nm_utils_inet4_ntop (in_addr_t addr, char dst[static INET_ADDRSTRLEN])
+_nm_utils_inet4_ntop(in_addr_t addr, char dst[static INET_ADDRSTRLEN])
 {
-	return nm_utils_inet_ntop (AF_INET, &addr, dst);
+    return nm_utils_inet_ntop(AF_INET, &addr, dst);
 }
 
 static inline const char *
-_nm_utils_inet6_ntop (const struct in6_addr *addr, char dst[static INET6_ADDRSTRLEN])
+_nm_utils_inet6_ntop(const struct in6_addr *addr, char dst[static INET6_ADDRSTRLEN])
 {
-	return nm_utils_inet_ntop (AF_INET6, addr, dst);
+    return nm_utils_inet_ntop(AF_INET6, addr, dst);
 }
 
 static inline char *
-nm_utils_inet_ntop_dup (int addr_family, gconstpointer addr)
+nm_utils_inet_ntop_dup(int addr_family, gconstpointer addr)
 {
-	char buf[NM_UTILS_INET_ADDRSTRLEN];
+    char buf[NM_UTILS_INET_ADDRSTRLEN];
 
-	return g_strdup (nm_utils_inet_ntop (addr_family, addr, buf));
+    return g_strdup(nm_utils_inet_ntop(addr_family, addr, buf));
 }
 
 static inline char *
-nm_utils_inet4_ntop_dup (in_addr_t addr)
+nm_utils_inet4_ntop_dup(in_addr_t addr)
 {
-	return nm_utils_inet_ntop_dup (AF_INET, &addr);
+    return nm_utils_inet_ntop_dup(AF_INET, &addr);
 }
 
 static inline char *
-nm_utils_inet6_ntop_dup (const struct in6_addr *addr)
+nm_utils_inet6_ntop_dup(const struct in6_addr *addr)
 {
-	return nm_utils_inet_ntop_dup (AF_INET6, addr);
+    return nm_utils_inet_ntop_dup(AF_INET6, addr);
 }
 
 /*****************************************************************************/
 
-gboolean nm_utils_ipaddr_is_valid (int addr_family,
-                                   const char *str_addr);
+gboolean nm_utils_ipaddr_is_valid(int addr_family, const char *str_addr);
 
-gboolean nm_utils_ipaddr_is_normalized (int addr_family,
-                                        const char *str_addr);
+gboolean nm_utils_ipaddr_is_normalized(int addr_family, const char *str_addr);
 
 /*****************************************************************************/
 
-#define NM_CMP_RETURN(c) \
-    G_STMT_START { \
-        const int _cc = (c); \
-        if (_cc) \
-            return _cc < 0 ? -1 : 1; \
-    } G_STMT_END
-
-#define NM_CMP_RETURN_DIRECT(c) \
-    G_STMT_START { \
-        const int _cc = (c); \
-        if (_cc) \
-            return _cc; \
-    } G_STMT_END
-
-#define NM_CMP_SELF(a, b) \
-    G_STMT_START { \
-        typeof (a) _a = (a); \
-        typeof (b) _b = (b); \
-        \
-        if (_a == _b) \
-            return 0; \
-        if (!_a) \
-            return -1; \
-        if (!_b) \
-            return 1; \
-    } G_STMT_END
-
-#define NM_CMP_DIRECT(a, b) \
-    G_STMT_START { \
-        typeof (a) _a = (a); \
-        typeof (b) _b = (b); \
-        \
-        if (_a != _b) \
-            return (_a < _b) ? -1 : 1; \
-    } G_STMT_END
-
-/* In the general case, direct pointer comparison is undefined behavior in C.
- * Avoid that by casting pointers to void* and then to uintptr_t. This comparison
- * is not really meaningful, except that it provides some kind of stable sort order
- * between pointers (that can otherwise not be compared). */
-#define NM_CMP_DIRECT_PTR(a, b) \
-	NM_CMP_DIRECT ((uintptr_t) ((void *) (a)), \
-	               (uintptr_t) ((void *) (b)))
-
-#define NM_CMP_DIRECT_MEMCMP(a, b, size) \
-    NM_CMP_RETURN (memcmp ((a), (b), (size)))
-
-#define NM_CMP_DIRECT_STRCMP(a, b) \
-    NM_CMP_RETURN_DIRECT (strcmp ((a), (b)))
-
-#define NM_CMP_DIRECT_STRCMP0(a, b) \
-    NM_CMP_RETURN_DIRECT (nm_strcmp0 ((a), (b)))
-
-#define NM_CMP_DIRECT_IN6ADDR(a, b) \
-    G_STMT_START { \
-        const struct in6_addr *const _a = (a); \
-        const struct in6_addr *const _b = (b); \
-        NM_CMP_RETURN (memcmp (_a, _b, sizeof (struct in6_addr))); \
-    } G_STMT_END
-
-#define NM_CMP_FIELD(a, b, field) \
-    NM_CMP_DIRECT (((a)->field), ((b)->field))
-
-#define NM_CMP_FIELD_UNSAFE(a, b, field) \
-    G_STMT_START { \
-        /* it's unsafe, because it evaluates the arguments more then once.
-         * This is necessary for bitfields, for which typeof() doesn't work. */ \
-        if (((a)->field) != ((b)->field)) \
-            return ((a)->field < ((b)->field)) ? -1 : 1; \
-    } G_STMT_END
-
-#define NM_CMP_FIELD_BOOL(a, b, field) \
-    NM_CMP_DIRECT (!!((a)->field), !!((b)->field))
-
-#define NM_CMP_FIELD_STR(a, b, field) \
-    NM_CMP_RETURN (strcmp (((a)->field), ((b)->field)))
-
-#define NM_CMP_FIELD_STR_INTERNED(a, b, field) \
-    G_STMT_START { \
-        const char *_a = ((a)->field); \
-        const char *_b = ((b)->field); \
-        \
-        if (_a != _b) { \
-            NM_CMP_RETURN_DIRECT (nm_strcmp0 (_a, _b)); \
-        } \
-    } G_STMT_END
-
-#define NM_CMP_FIELD_STR0(a, b, field) \
-    NM_CMP_RETURN_DIRECT (nm_strcmp0 (((a)->field), ((b)->field)))
-
-#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
-    NM_CMP_RETURN (memcmp (&((a)->field), &((b)->field), \
-                           NM_MIN (len, sizeof ((a)->field))))
-
-#define NM_CMP_FIELD_MEMCMP(a, b, field) \
-    NM_CMP_RETURN (memcmp (&((a)->field), \
-                           &((b)->field), \
-                           sizeof ((a)->field)))
-
-#define NM_CMP_FIELD_IN6ADDR(a, b, field) \
-    G_STMT_START { \
-        const struct in6_addr *const _a = &((a)->field); \
-        const struct in6_addr *const _b = &((b)->field); \
-        NM_CMP_RETURN (memcmp (_a, _b, sizeof (struct in6_addr))); \
-    } G_STMT_END
-
-/*****************************************************************************/
-
-gboolean nm_utils_memeqzero (gconstpointer data, gsize length);
+gboolean nm_utils_memeqzero(gconstpointer data, gsize length);
 
 /*****************************************************************************/
 
 extern const void *const _NM_PTRARRAY_EMPTY[1];
 
-#define NM_PTRARRAY_EMPTY(type) ((type const*) _NM_PTRARRAY_EMPTY)
+#define NM_PTRARRAY_EMPTY(type) ((type const *) _NM_PTRARRAY_EMPTY)
 
 static inline void
-_nm_utils_strbuf_init (char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len)
+_nm_utils_strbuf_init(char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len)
 {
-	NM_SET_OUT (p_buf_len, len);
-	NM_SET_OUT (p_buf_ptr, buf);
-	buf[0] = '\0';
+    NM_SET_OUT(p_buf_len, len);
+    NM_SET_OUT(p_buf_ptr, buf);
+    buf[0] = '\0';
 }
 
-#define nm_utils_strbuf_init(buf, p_buf_ptr, p_buf_len) \
-	G_STMT_START { \
-		G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) > sizeof (char *)); \
-		_nm_utils_strbuf_init ((buf), sizeof (buf), (p_buf_ptr), (p_buf_len)); \
-	} G_STMT_END
-void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) _nm_printf (3, 4);
-void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
-void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
-void nm_utils_strbuf_append_bin (char **buf, gsize *len, gconstpointer str, gsize str_len);
-void nm_utils_strbuf_seek_end (char **buf, gsize *len);
+#define nm_utils_strbuf_init(buf, p_buf_ptr, p_buf_len)                                    \
+    G_STMT_START                                                                           \
+    {                                                                                      \
+        G_STATIC_ASSERT(G_N_ELEMENTS(buf) == sizeof(buf) && sizeof(buf) > sizeof(char *)); \
+        _nm_utils_strbuf_init((buf), sizeof(buf), (p_buf_ptr), (p_buf_len));               \
+    }                                                                                      \
+    G_STMT_END
+void nm_utils_strbuf_append(char **buf, gsize *len, const char *format, ...) _nm_printf(3, 4);
+void nm_utils_strbuf_append_c(char **buf, gsize *len, char c);
+void nm_utils_strbuf_append_str(char **buf, gsize *len, const char *str);
+void nm_utils_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_len);
+void nm_utils_strbuf_seek_end(char **buf, gsize *len);
 
-const char *nm_strquote (char *buf, gsize buf_len, const char *str);
+const char *nm_strquote(char *buf, gsize buf_len, const char *str);
 
 static inline gboolean
-nm_utils_is_separator (const char c)
+nm_utils_is_separator(const char c)
 {
-	return NM_IN_SET (c, ' ', '\t');
+    return NM_IN_SET(c, ' ', '\t');
 }
 
 /*****************************************************************************/
 
-GBytes *nm_gbytes_get_empty (void);
+GBytes *nm_gbytes_get_empty(void);
 
 static inline gboolean
-nm_gbytes_equal0 (GBytes *a, GBytes *b)
+nm_gbytes_equal0(GBytes *a, GBytes *b)
 {
-	return a == b || (a && b && g_bytes_equal (a, b));
+    return a == b || (a && b && g_bytes_equal(a, b));
 }
 
-gboolean nm_utils_gbytes_equal_mem (GBytes *bytes,
-                                    gconstpointer mem_data,
-                                    gsize mem_len);
+gboolean nm_utils_gbytes_equal_mem(GBytes *bytes, gconstpointer mem_data, gsize mem_len);
 
-GVariant *nm_utils_gbytes_to_variant_ay (GBytes *bytes);
+GVariant *nm_utils_gbytes_to_variant_ay(GBytes *bytes);
 
-GVariant *nm_utils_strdict_to_variant_ass (GHashTable *strdict);
+GVariant *nm_utils_strdict_to_variant_ass(GHashTable *strdict);
+GVariant *nm_utils_strdict_to_variant_asv(GHashTable *strdict);
 
 /*****************************************************************************/
 
-GVariant *nm_utils_gvariant_vardict_filter (GVariant *src,
-                                            gboolean (*filter_fcn) (const char *key,
-                                                                    GVariant *val,
-                                                                    char **out_key,
-                                                                    GVariant **out_val,
-                                                                    gpointer user_data),
-                                            gpointer user_data);
+GVariant *nm_utils_gvariant_vardict_filter(GVariant *src,
+                                           gboolean (*filter_fcn)(const char *key,
+                                                                  GVariant *  val,
+                                                                  char **     out_key,
+                                                                  GVariant ** out_val,
+                                                                  gpointer    user_data),
+                                           gpointer user_data);
 
-GVariant *
-nm_utils_gvariant_vardict_filter_drop_one (GVariant *src,
-                                           const char *key);
+GVariant *nm_utils_gvariant_vardict_filter_drop_one(GVariant *src, const char *key);
 
 /*****************************************************************************/
 
 static inline int
-nm_utils_hexchar_to_int (char ch)
+nm_utils_hexchar_to_int(char ch)
 {
-	G_STATIC_ASSERT_EXPR ('0' < 'A');
-	G_STATIC_ASSERT_EXPR ('A' < 'a');
+    G_STATIC_ASSERT_EXPR('0' < 'A');
+    G_STATIC_ASSERT_EXPR('A' < 'a');
 
-	if (ch >= '0') {
-		if (ch <= '9')
-			return ch - '0';
-		if (ch >= 'A') {
-			if (ch <= 'F')
-				return ((int) ch) + (10 - (int) 'A');
-			if (ch >= 'a' && ch <= 'f')
-				return ((int) ch) + (10 - (int) 'a');
-		}
-	}
-	return -1;
+    if (ch >= '0') {
+        if (ch <= '9')
+            return ch - '0';
+        if (ch >= 'A') {
+            if (ch <= 'F')
+                return ((int) ch) + (10 - (int) 'A');
+            if (ch >= 'a' && ch <= 'f')
+                return ((int) ch) + (10 - (int) 'a');
+        }
+    }
+    return -1;
 }
 
 /*****************************************************************************/
 
-const char *nm_utils_dbus_path_get_last_component (const char *dbus_path);
+const char *nm_utils_dbus_path_get_last_component(const char *dbus_path);
 
-int nm_utils_dbus_path_cmp (const char *dbus_path_a, const char *dbus_path_b);
+int nm_utils_dbus_path_cmp(const char *dbus_path_a, const char *dbus_path_b);
 
 /*****************************************************************************/
 
 typedef enum {
-	NM_UTILS_STRSPLIT_SET_FLAGS_NONE           = 0,
-
-	/* by default, strsplit will coalesce consecutive delimiters and remove
-	 * them from the result. If this flag is present, empty values are preserved
-	 * and returned.
-	 *
-	 * When combined with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, if a value gets
-	 * empty after strstrip(), it also gets removed. */
-	NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY = (1u << 0),
-
-	/* %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING means that delimiters prefixed
-	 * by a backslash are not treated as a separator. Such delimiters and their escape
-	 * character are copied to the current word without unescaping them. In general,
-	 * nm_utils_strsplit_set_full() does not remove any backslash escape characters
-	 * and does no unescaping. It only considers them for skipping to split at
-	 * an escaped delimiter.
-	 *
-	 * If this is combined with (or implied by %NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED), then
-	 * the backslash escapes are removed from the result.
-	 */
-	NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING = (1u << 1),
-
-	/* If flag is set, does the same as g_strstrip() on the returned tokens.
-	 * This will remove leading and trailing ascii whitespaces (g_ascii_isspace()
-	 * and NM_ASCII_SPACES).
-	 *
-	 * - when combined with !%NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY,
-	 *   empty tokens will be removed (and %NULL will be returned if that
-	 *   results in an empty string array).
-	 * - when combined with %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING,
-	 *   trailing whitespace escaped by backslash are not stripped. */
-	NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP       = (1u << 2),
-
-	/* This implies %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING.
-	 *
-	 * This will do a final run over all tokens and remove all backslash
-	 * escape characters that
-	 *   - precede a delimiter.
-	 *   - precede a backslash.
-	 *   - preceed a whitespace (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
-	 *
-	 *  Note that with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, it is only
-	 *  necessary to escape the very last whitespace (if the delimiters
-	 *  are not whitespace themself). So, technically, it would be sufficient
-	 *  to only unescape a backslash before the last whitespace and the user
-	 *  still could express everything. However, such a rule would be complicated
-	 *  to understand, so when using backslash escaping with nm_utils_strsplit_set_full(),
-	 *  then all characters (including backslash) are treated verbatim, except:
-	 *
-	 *    - "\\$DELIMITER" (escaped delimiter)
-	 *    - "\\\\" (escaped backslash)
-	 *    - "\\$SPACE" (escaped space) (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
-	 *
-	 * Note that all other escapes like "\\n" or "\\001" are left alone.
-	 * That makes the escaping/unescaping rules simple. Also, for the most part
-	 * a text is just taken as-is, with little additional rules. Only backslashes
-	 * need extra care, and then only if they proceed one of the relevant characters.
-	 */
-	NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED        = (1u << 3),
+    NM_UTILS_STRSPLIT_SET_FLAGS_NONE = 0,
+
+    /* by default, strsplit will coalesce consecutive delimiters and remove
+     * them from the result. If this flag is present, empty values are preserved
+     * and returned.
+     *
+     * When combined with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, if a value gets
+     * empty after strstrip(), it also gets removed. */
+    NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY = (1u << 0),
+
+    /* %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING means that delimiters prefixed
+     * by a backslash are not treated as a separator. Such delimiters and their escape
+     * character are copied to the current word without unescaping them. In general,
+     * nm_utils_strsplit_set_full() does not remove any backslash escape characters
+     * and does no unescaping. It only considers them for skipping to split at
+     * an escaped delimiter.
+     *
+     * If this is combined with (or implied by %NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED), then
+     * the backslash escapes are removed from the result.
+     */
+    NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING = (1u << 1),
+
+    /* If flag is set, does the same as g_strstrip() on the returned tokens.
+     * This will remove leading and trailing ascii whitespaces (g_ascii_isspace()
+     * and NM_ASCII_SPACES).
+     *
+     * - when combined with !%NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY,
+     *   empty tokens will be removed (and %NULL will be returned if that
+     *   results in an empty string array).
+     * - when combined with %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING,
+     *   trailing whitespace escaped by backslash are not stripped. */
+    NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP = (1u << 2),
+
+    /* This implies %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING.
+     *
+     * This will do a final run over all tokens and remove all backslash
+     * escape characters that
+     *   - precede a delimiter.
+     *   - precede a backslash.
+     *   - preceed a whitespace (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
+     *
+     *  Note that with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, it is only
+     *  necessary to escape the very last whitespace (if the delimiters
+     *  are not whitespace themself). So, technically, it would be sufficient
+     *  to only unescape a backslash before the last whitespace and the user
+     *  still could express everything. However, such a rule would be complicated
+     *  to understand, so when using backslash escaping with nm_utils_strsplit_set_full(),
+     *  then all characters (including backslash) are treated verbatim, except:
+     *
+     *    - "\\$DELIMITER" (escaped delimiter)
+     *    - "\\\\" (escaped backslash)
+     *    - "\\$SPACE" (escaped space) (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
+     *
+     * Note that all other escapes like "\\n" or "\\001" are left alone.
+     * That makes the escaping/unescaping rules simple. Also, for the most part
+     * a text is just taken as-is, with little additional rules. Only backslashes
+     * need extra care, and then only if they proceed one of the relevant characters.
+     */
+    NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED = (1u << 3),
 
 } NMUtilsStrsplitSetFlags;
 
-const char **nm_utils_strsplit_set_full (const char *str,
-                                         const char *delimiter,
-                                         NMUtilsStrsplitSetFlags flags);
+const char **
+nm_utils_strsplit_set_full(const char *str, const char *delimiter, NMUtilsStrsplitSetFlags flags);
 
 static inline const char **
-nm_utils_strsplit_set_with_empty (const char *str,
-                                  const char *delimiters)
+nm_utils_strsplit_set_with_empty(const char *str, const char *delimiters)
 {
-	/* this returns the same result as g_strsplit_set(str, delimiters, -1), except
-	 * it does not deep-clone the strv array.
-	 * Also, for @str == "", this returns %NULL while g_strsplit_set() would return
-	 * an empty strv array. */
-	return nm_utils_strsplit_set_full (str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY);
+    /* this returns the same result as g_strsplit_set(str, delimiters, -1), except
+     * it does not deep-clone the strv array.
+     * Also, for @str == "", this returns %NULL while g_strsplit_set() would return
+     * an empty strv array. */
+    return nm_utils_strsplit_set_full(str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY);
 }
 
 static inline const char **
-nm_utils_strsplit_set (const char *str,
-                       const char *delimiters)
+nm_utils_strsplit_set(const char *str, const char *delimiters)
 {
-	return nm_utils_strsplit_set_full (str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_NONE);
+    return nm_utils_strsplit_set_full(str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_NONE);
 }
 
-gssize nm_utils_strv_find_first (char **list, gssize len, const char *needle);
+gssize nm_utils_strv_find_first(char **list, gssize len, const char *needle);
 
-char **_nm_utils_strv_cleanup (char **strv,
-                               gboolean strip_whitespace,
-                               gboolean skip_empty,
-                               gboolean skip_repeated);
+char **_nm_utils_strv_cleanup(char **  strv,
+                              gboolean strip_whitespace,
+                              gboolean skip_empty,
+                              gboolean skip_repeated);
+
+/*****************************************************************************/
+
+static inline gpointer
+nm_copy_func_g_strdup(gconstpointer arg, gpointer user_data)
+{
+    return g_strdup(arg);
+}
 
 /*****************************************************************************/
 
 static inline const char **
-nm_utils_escaped_tokens_split (const char *str,
-                               const char *delimiters)
+nm_utils_escaped_tokens_split(const char *str, const char *delimiters)
 {
-	return nm_utils_strsplit_set_full (str,
-	                                   delimiters,
-	                                     NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED
-	                                   | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
+    return nm_utils_strsplit_set_full(str,
+                                      delimiters,
+                                      NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED
+                                          | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
 }
 
 typedef enum {
-	NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_NONE                       = 0,
-	NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_SPACES              = (1ull << 0),
-	NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE       = (1ull << 1),
-	NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE      = (1ull << 2),
-
-	/* Backslash characters will be escaped as "\\\\" if they precede another
-	 * character that makes it necessary. Such characters are:
-	 *
-	 *  1) before another '\\' backslash.
-	 *  2) before any delimiter in @delimiters.
-	 *  3) before any delimiter in @delimiters_as_needed.
-	 *  4) before a white space, if ESCAPE_LEADING_SPACE or ESCAPE_TRAILING_SPACE is set.
-	 *  5) before the end of the word
-	 *
-	 * Rule 4) is an extension. It's not immediately clear why with ESCAPE_LEADING_SPACE
-	 * and ESCAPE_TRAILING_SPACE we want *all* backslashes before a white space escaped.
-	 * The reason is, that we obviously want to use ESCAPE_LEADING_SPACE and ESCAPE_TRAILING_SPACE
-	 * in cases, where we later parse the backslash escaped strings back, but allowing to strip
-	 * unescaped white spaces. That means, we want that " a " gets escaped as "\\ a\\ ".
-	 * On the other hand, we also want that " a\\ b " gets escaped as "\\ a\\\\ b\\ ",
-	 * and not "\\ a\\ b\\ ". Because otherwise, the parser would need to treat "\\ "
-	 * differently depending on whether the sequence is at the beginning, end or middle
-	 * of the word.
-	 *
-	 * Rule 5) is also not immediately obvious. When used with ESCAPE_TRAILING_SPACE,
-	 * we clearly want to allow that an escaped word can have arbitrary
-	 * whitespace suffixes. That's why this mode exists. So we must escape "a\\" as
-	 * "a\\\\", so that appending " " does not change the meaning.
-	 * Also without ESCAPE_TRAILING_SPACE, we want in general that we can concatenate
-	 * two escaped words without changing their meaning. If the words would be "a\\"
-	 * and "," (with ',' being a delimiter), then the result must be "a\\\\" and "\\,"
-	 * so that the concatenated word ("a\\\\\\,") is still the same. If we would escape
-	 * them instead as "a\\" + "\\,", then the concatenated word would be "a\\\\," and
-	 * different.
-	 * */
-	NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED = (1ull << 3),
-
-	NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS    = (1ull << 4),
+    NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_NONE                  = 0,
+    NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_SPACES         = (1ull << 0),
+    NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE  = (1ull << 1),
+    NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE = (1ull << 2),
+
+    /* Backslash characters will be escaped as "\\\\" if they precede another
+     * character that makes it necessary. Such characters are:
+     *
+     *  1) before another '\\' backslash.
+     *  2) before any delimiter in @delimiters.
+     *  3) before any delimiter in @delimiters_as_needed.
+     *  4) before a white space, if ESCAPE_LEADING_SPACE or ESCAPE_TRAILING_SPACE is set.
+     *  5) before the end of the word
+     *
+     * Rule 4) is an extension. It's not immediately clear why with ESCAPE_LEADING_SPACE
+     * and ESCAPE_TRAILING_SPACE we want *all* backslashes before a white space escaped.
+     * The reason is, that we obviously want to use ESCAPE_LEADING_SPACE and ESCAPE_TRAILING_SPACE
+     * in cases, where we later parse the backslash escaped strings back, but allowing to strip
+     * unescaped white spaces. That means, we want that " a " gets escaped as "\\ a\\ ".
+     * On the other hand, we also want that " a\\ b " gets escaped as "\\ a\\\\ b\\ ",
+     * and not "\\ a\\ b\\ ". Because otherwise, the parser would need to treat "\\ "
+     * differently depending on whether the sequence is at the beginning, end or middle
+     * of the word.
+     *
+     * Rule 5) is also not immediately obvious. When used with ESCAPE_TRAILING_SPACE,
+     * we clearly want to allow that an escaped word can have arbitrary
+     * whitespace suffixes. That's why this mode exists. So we must escape "a\\" as
+     * "a\\\\", so that appending " " does not change the meaning.
+     * Also without ESCAPE_TRAILING_SPACE, we want in general that we can concatenate
+     * two escaped words without changing their meaning. If the words would be "a\\"
+     * and "," (with ',' being a delimiter), then the result must be "a\\\\" and "\\,"
+     * so that the concatenated word ("a\\\\\\,") is still the same. If we would escape
+     * them instead as "a\\" + "\\,", then the concatenated word would be "a\\\\," and
+     * different.
+     * */
+    NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED = (1ull << 3),
+
+    NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS = (1ull << 4),
 } NMUtilsEscapedTokensEscapeFlags;
 
-const char *nm_utils_escaped_tokens_escape_full (const char *str,
-                                                 const char *delimiters,
-                                                 const char *delimiters_as_needed,
-                                                 NMUtilsEscapedTokensEscapeFlags flags,
-                                                 char **out_to_free);
+const char *nm_utils_escaped_tokens_escape_full(const char *str,
+                                                const char *delimiters,
+                                                const char *delimiters_as_needed,
+                                                NMUtilsEscapedTokensEscapeFlags flags,
+                                                char **                         out_to_free);
 
 static inline const char *
-nm_utils_escaped_tokens_escape (const char *str,
-                                const char *delimiters,
-                                char **out_to_free)
+nm_utils_escaped_tokens_escape(const char *str, const char *delimiters, char **out_to_free)
 {
-	return nm_utils_escaped_tokens_escape_full (str,
-	                                            delimiters,
-	                                            NULL,
-	                                              NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS
-	                                            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
-	                                            out_to_free);
+    return nm_utils_escaped_tokens_escape_full(
+        str,
+        delimiters,
+        NULL,
+        NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS
+            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
+        out_to_free);
 }
 
-static inline GString *
-nm_utils_escaped_tokens_escape_gstr_assert (const char *str,
-                                            const char *delimiters,
-                                            GString *gstring)
+/**
+ * nm_utils_escaped_tokens_escape_unnecessary:
+ * @str: the string to check for "escape"
+ * @delimiters: the delimiters
+ *
+ * This asserts that calling nm_utils_escaped_tokens_escape()
+ * on @str has no effect and returns @str directly. This is only
+ * for asserting that @str is safe to not require any escaping.
+ *
+ * Returns: @str
+ */
+static inline const char *
+nm_utils_escaped_tokens_escape_unnecessary(const char *str, const char *delimiters)
 {
 #if NM_MORE_ASSERTS > 0
 
-	/* Just appends @str to @gstring, but also assert that
-	 * no escaping is necessary.
-	 *
-	 * Use nm_utils_escaped_tokens_escape_gstr_assert() instead
-	 * of nm_utils_escaped_tokens_escape_gstr(), if you *know* that
-	 * @str contains no delimiters, no backslashes, and no trailing
-	 * whitespace that requires escaping. */
-
-	nm_assert (str);
-	nm_assert (gstring);
-	nm_assert (delimiters);
-
-	{
-		gs_free char *str_to_free = NULL;
-		const char *str0;
-
-		str0 = nm_utils_escaped_tokens_escape (str, delimiters, &str_to_free);
-		nm_assert (str0 == str);
-		nm_assert (!str_to_free);
-	}
+    nm_assert(str);
+    nm_assert(delimiters);
+
+    {
+        gs_free char *str_to_free = NULL;
+        const char *  str0;
+
+        str0 = nm_utils_escaped_tokens_escape(str, delimiters, &str_to_free);
+        nm_assert(str0 == str);
+        nm_assert(!str_to_free);
+    }
 #endif
 
-	g_string_append (gstring, str);
-	return gstring;
+    return str;
+}
+
+static inline void
+nm_utils_escaped_tokens_escape_gstr_assert(const char *str,
+                                           const char *delimiters,
+                                           GString *   gstring)
+{
+    g_string_append(gstring, nm_utils_escaped_tokens_escape_unnecessary(str, delimiters));
 }
 
 static inline GString *
-nm_utils_escaped_tokens_escape_gstr (const char *str,
-                                     const char *delimiters,
-                                     GString *gstring)
+nm_utils_escaped_tokens_escape_gstr(const char *str, const char *delimiters, GString *gstring)
 {
-	gs_free char *str_to_free = NULL;
+    gs_free char *str_to_free = NULL;
 
-	nm_assert (str);
-	nm_assert (gstring);
+    nm_assert(str);
+    nm_assert(gstring);
 
-	g_string_append (gstring,
-	                 nm_utils_escaped_tokens_escape (str, delimiters, &str_to_free));
-	return gstring;
+    g_string_append(gstring, nm_utils_escaped_tokens_escape(str, delimiters, &str_to_free));
+    return gstring;
 }
 
 /*****************************************************************************/
 
-char **nm_utils_strsplit_quoted (const char *str);
+char **nm_utils_strsplit_quoted(const char *str);
 
 /*****************************************************************************/
 
 static inline const char **
-nm_utils_escaped_tokens_options_split_list (const char *str)
+nm_utils_escaped_tokens_options_split_list(const char *str)
 {
-	return nm_utils_strsplit_set_full (str,
-	                                   ",",
-	                                     NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP
-	                                   | NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING);
+    return nm_utils_strsplit_set_full(str,
+                                      ",",
+                                      NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP
+                                          | NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING);
 }
 
-void nm_utils_escaped_tokens_options_split (char *str,
-                                            const char **out_key,
-                                            const char **out_val);
+void nm_utils_escaped_tokens_options_split(char *str, const char **out_key, const char **out_val);
 
 static inline const char *
-nm_utils_escaped_tokens_options_escape_key (const char *key,
-                                            char **out_to_free)
+nm_utils_escaped_tokens_options_escape_key(const char *key, char **out_to_free)
 {
-	return nm_utils_escaped_tokens_escape_full (key,
-	                                            ",=",
-	                                            NULL,
-	                                              NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED
-	                                            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
-	                                            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
-	                                            out_to_free);
+    return nm_utils_escaped_tokens_escape_full(
+        key,
+        ",=",
+        NULL,
+        NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED
+            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
+            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
+        out_to_free);
 }
 
 static inline const char *
-nm_utils_escaped_tokens_options_escape_val (const char *val,
-                                            char **out_to_free)
+nm_utils_escaped_tokens_options_escape_val(const char *val, char **out_to_free)
 {
-	return nm_utils_escaped_tokens_escape_full (val,
-	                                            ",",
-	                                            "=",
-	                                              NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED
-	                                            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
-	                                            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
-	                                            out_to_free);
+    return nm_utils_escaped_tokens_escape_full(
+        val,
+        ",",
+        "=",
+        NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED
+            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
+            | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
+        out_to_free);
 }
 
 /*****************************************************************************/
 
-#define NM_UTILS_CHECKSUM_LENGTH_MD5          16
-#define NM_UTILS_CHECKSUM_LENGTH_SHA1         20
-#define NM_UTILS_CHECKSUM_LENGTH_SHA256       32
-
-#define nm_utils_checksum_get_digest(sum, arr) \
-	G_STMT_START { \
-		GChecksum *const _sum = (sum); \
-		gsize _len; \
-		\
-		G_STATIC_ASSERT_EXPR (   sizeof (arr) == NM_UTILS_CHECKSUM_LENGTH_MD5 \
-		                      || sizeof (arr) == NM_UTILS_CHECKSUM_LENGTH_SHA1 \
-		                      || sizeof (arr) == NM_UTILS_CHECKSUM_LENGTH_SHA256); \
-		G_STATIC_ASSERT_EXPR (sizeof (arr) == G_N_ELEMENTS (arr)); \
-		\
-		nm_assert (_sum); \
-		\
-		_len = G_N_ELEMENTS (arr); \
-		\
-		g_checksum_get_digest (_sum, (arr), &_len); \
-		nm_assert (_len == G_N_ELEMENTS (arr)); \
-	} G_STMT_END
-
-#define nm_utils_checksum_get_digest_len(sum, buf, len) \
-	G_STMT_START { \
-		GChecksum *const _sum = (sum); \
-		const gsize _len0 = (len); \
-		gsize _len; \
-		\
-		nm_assert (NM_IN_SET (_len0, NM_UTILS_CHECKSUM_LENGTH_MD5, \
-		                             NM_UTILS_CHECKSUM_LENGTH_SHA1, \
-		                             NM_UTILS_CHECKSUM_LENGTH_SHA256)); \
-		nm_assert (_sum); \
-		\
-		_len = _len0; \
-		g_checksum_get_digest (_sum, (buf), &_len); \
-		nm_assert (_len == _len0); \
-	} G_STMT_END
+#define NM_UTILS_CHECKSUM_LENGTH_MD5    16
+#define NM_UTILS_CHECKSUM_LENGTH_SHA1   20
+#define NM_UTILS_CHECKSUM_LENGTH_SHA256 32
+
+#define nm_utils_checksum_get_digest(sum, arr)                                   \
+    G_STMT_START                                                                 \
+    {                                                                            \
+        GChecksum *const _sum = (sum);                                           \
+        gsize            _len;                                                   \
+                                                                                 \
+        G_STATIC_ASSERT_EXPR(sizeof(arr) == NM_UTILS_CHECKSUM_LENGTH_MD5         \
+                             || sizeof(arr) == NM_UTILS_CHECKSUM_LENGTH_SHA1     \
+                             || sizeof(arr) == NM_UTILS_CHECKSUM_LENGTH_SHA256); \
+        G_STATIC_ASSERT_EXPR(sizeof(arr) == G_N_ELEMENTS(arr));                  \
+                                                                                 \
+        nm_assert(_sum);                                                         \
+                                                                                 \
+        _len = G_N_ELEMENTS(arr);                                                \
+                                                                                 \
+        g_checksum_get_digest(_sum, (arr), &_len);                               \
+        nm_assert(_len == G_N_ELEMENTS(arr));                                    \
+    }                                                                            \
+    G_STMT_END
+
+#define nm_utils_checksum_get_digest_len(sum, buf, len)        \
+    G_STMT_START                                               \
+    {                                                          \
+        GChecksum *const _sum  = (sum);                        \
+        const gsize      _len0 = (len);                        \
+        gsize            _len;                                 \
+                                                               \
+        nm_assert(NM_IN_SET(_len0,                             \
+                            NM_UTILS_CHECKSUM_LENGTH_MD5,      \
+                            NM_UTILS_CHECKSUM_LENGTH_SHA1,     \
+                            NM_UTILS_CHECKSUM_LENGTH_SHA256)); \
+        nm_assert(_sum);                                       \
+                                                               \
+        _len = _len0;                                          \
+        g_checksum_get_digest(_sum, (buf), &_len);             \
+        nm_assert(_len == _len0);                              \
+    }                                                          \
+    G_STMT_END
 
 /*****************************************************************************/
 
-guint32 _nm_utils_ip4_prefix_to_netmask (guint32 prefix);
-guint32 _nm_utils_ip4_get_default_prefix (guint32 ip);
+guint32 _nm_utils_ip4_prefix_to_netmask(guint32 prefix);
+guint32 _nm_utils_ip4_get_default_prefix(guint32 ip);
 
-gconstpointer          nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen);
-in_addr_t              nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
-const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
-int nm_utils_ip6_address_same_prefix_cmp (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
+gconstpointer
+nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint8 plen);
+in_addr_t              nm_utils_ip4_address_clear_host_address(in_addr_t addr, guint8 plen);
+const struct in6_addr *nm_utils_ip6_address_clear_host_address(struct in6_addr *      dst,
+                                                               const struct in6_addr *src,
+                                                               guint8                 plen);
+int                    nm_utils_ip6_address_same_prefix_cmp(const struct in6_addr *addr_a,
+                                                            const struct in6_addr *addr_b,
+                                                            guint8                 plen);
 
-gboolean nm_utils_ip_is_site_local (int addr_family,
-                                    const void *address);
+gboolean nm_utils_ip_is_site_local(int addr_family, const void *address);
 
 /*****************************************************************************/
 
-gboolean nm_utils_parse_inaddr_bin_full (int addr_family,
-                                         gboolean accept_legacy,
-                                         const char *text,
-                                         int *out_addr_family,
-                                         gpointer out_addr);
+gboolean nm_utils_parse_inaddr_bin_full(int         addr_family,
+                                        gboolean    accept_legacy,
+                                        const char *text,
+                                        int *       out_addr_family,
+                                        gpointer    out_addr);
 static inline gboolean
-nm_utils_parse_inaddr_bin (int addr_family,
-                           const char *text,
-                           int *out_addr_family,
-                           gpointer out_addr)
+nm_utils_parse_inaddr_bin(int         addr_family,
+                          const char *text,
+                          int *       out_addr_family,
+                          gpointer    out_addr)
 {
-	return nm_utils_parse_inaddr_bin_full (addr_family, FALSE, text, out_addr_family, out_addr);
+    return nm_utils_parse_inaddr_bin_full(addr_family, FALSE, text, out_addr_family, out_addr);
 }
 
-gboolean nm_utils_parse_inaddr (int addr_family,
-                                const char *text,
-                                char **out_addr);
+gboolean nm_utils_parse_inaddr(int addr_family, const char *text, char **out_addr);
 
-gboolean nm_utils_parse_inaddr_prefix_bin (int addr_family,
-                                           const char *text,
-                                           int *out_addr_family,
-                                           gpointer out_addr,
-                                           int *out_prefix);
+gboolean nm_utils_parse_inaddr_prefix_bin(int         addr_family,
+                                          const char *text,
+                                          int *       out_addr_family,
+                                          gpointer    out_addr,
+                                          int *       out_prefix);
 
-gboolean nm_utils_parse_inaddr_prefix (int addr_family,
-                                       const char *text,
-                                       char **out_addr,
-                                       int *out_prefix);
+gboolean
+nm_utils_parse_inaddr_prefix(int addr_family, const char *text, char **out_addr, int *out_prefix);
 
-gboolean nm_utils_parse_next_line (const char **inout_ptr,
-                                   gsize *inout_len,
-                                   const char **out_line,
-                                   gsize *out_line_len);
+gboolean nm_utils_parse_next_line(const char **inout_ptr,
+                                  gsize *      inout_len,
+                                  const char **out_line,
+                                  gsize *      out_line_len);
 
-gint64 nm_g_ascii_strtoll (const char *nptr,
-                           char **endptr,
-                           guint base);
+gint64 nm_g_ascii_strtoll(const char *nptr, char **endptr, guint base);
 
-guint64 nm_g_ascii_strtoull (const char *nptr,
-                             char **endptr,
-                             guint base);
+guint64 nm_g_ascii_strtoull(const char *nptr, char **endptr, guint base);
 
-double nm_g_ascii_strtod (const char *nptr,
-                          char **endptr);
+double nm_g_ascii_strtod(const char *nptr, char **endptr);
 
-gint64  _nm_utils_ascii_str_to_int64  (const char *str, guint base, gint64  min, gint64  max, gint64  fallback);
-guint64 _nm_utils_ascii_str_to_uint64 (const char *str, guint base, guint64 min, guint64 max, guint64 fallback);
+gint64
+_nm_utils_ascii_str_to_int64(const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
+guint64 _nm_utils_ascii_str_to_uint64(const char *str,
+                                      guint       base,
+                                      guint64     min,
+                                      guint64     max,
+                                      guint64     fallback);
 
-int _nm_utils_ascii_str_to_bool (const char *str,
-                                  int default_value);
+int _nm_utils_ascii_str_to_bool(const char *str, int default_value);
 
 /*****************************************************************************/
 
 extern char _nm_utils_to_string_buffer[2096];
 
-void     nm_utils_to_string_buffer_init (char **buf, gsize *len);
-gboolean nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len);
+void     nm_utils_to_string_buffer_init(char **buf, gsize *len);
+gboolean nm_utils_to_string_buffer_init_null(gconstpointer obj, char **buf, gsize *len);
 
 /*****************************************************************************/
 
 typedef struct {
-	unsigned flag;
-	const char *name;
+    unsigned    flag;
+    const char *name;
 } NMUtilsFlags2StrDesc;
 
-#define NM_UTILS_FLAGS2STR(f, n) { .flag = f, .name = ""n, }
-
-#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
-const char * \
-fcn_name (flags_type flags, char *buf, gsize len) \
-{ \
-	static const NMUtilsFlags2StrDesc descs[] = { \
-		__VA_ARGS__ \
-	}; \
-	G_STATIC_ASSERT (sizeof (flags_type) <= sizeof (unsigned)); \
-	return nm_utils_flags2str (descs, G_N_ELEMENTS (descs), flags, buf, len); \
-};
-
-const char *nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
-                                gsize n_descs,
-                                unsigned flags,
-                                char *buf,
-                                gsize len);
+#define NM_UTILS_FLAGS2STR(f, n) \
+    {                            \
+        .flag = f, .name = "" n, \
+    }
+
+#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...)                    \
+    const char *fcn_name(flags_type flags, char *buf, gsize len)                \
+    {                                                                           \
+        static const NMUtilsFlags2StrDesc descs[] = {__VA_ARGS__};              \
+        G_STATIC_ASSERT(sizeof(flags_type) <= sizeof(unsigned));                \
+        return nm_utils_flags2str(descs, G_N_ELEMENTS(descs), flags, buf, len); \
+    };
+
+const char *nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs,
+                               gsize                       n_descs,
+                               unsigned                    flags,
+                               char *                      buf,
+                               gsize                       len);
 
 /*****************************************************************************/
 
-#define NM_UTILS_ENUM2STR(v, n)     (void) 0; case v: s = ""n""; break; (void) 0
-#define NM_UTILS_ENUM2STR_IGNORE(v) (void) 0; case v: break; (void) 0
+#define NM_UTILS_ENUM2STR(v, n) \
+    (void) 0;                   \
+case v:                         \
+    s = "" n "";                \
+    break;                      \
+    (void) 0
+#define NM_UTILS_ENUM2STR_IGNORE(v) \
+    (void) 0;                       \
+case v:                             \
+    break;                          \
+    (void) 0
 
 #define NM_UTILS_ENUM2STR_DEFINE_FULL(fcn_name, lookup_type, int_fmt, ...) \
-const char * \
-fcn_name (lookup_type val, char *buf, gsize len) \
-{ \
-	nm_utils_to_string_buffer_init (&buf, &len); \
-	if (len) { \
-		const char *s = NULL; \
-		switch (val) { \
-			(void) 0, \
-			__VA_ARGS__ \
-			(void) 0; \
-		}; \
-		if (s) \
-			g_strlcpy (buf, s, len); \
-		else \
-			g_snprintf (buf, len, "(%"int_fmt")", val); \
-	} \
-	return buf; \
-}
+    const char *fcn_name(lookup_type val, char *buf, gsize len)            \
+    {                                                                      \
+        nm_utils_to_string_buffer_init(&buf, &len);                        \
+        if (len) {                                                         \
+            const char *s = NULL;                                          \
+            switch (val) {                                                 \
+                (void) 0, __VA_ARGS__(void) 0;                             \
+            };                                                             \
+            if (s)                                                         \
+                g_strlcpy(buf, s, len);                                    \
+            else                                                           \
+                g_snprintf(buf, len, "(%" int_fmt ")", val);               \
+        }                                                                  \
+        return buf;                                                        \
+    }
 
 #define NM_UTILS_ENUM2STR_DEFINE(fcn_name, lookup_type, ...) \
-	NM_UTILS_ENUM2STR_DEFINE_FULL (fcn_name, lookup_type, "d", __VA_ARGS__)
+    NM_UTILS_ENUM2STR_DEFINE_FULL(fcn_name, lookup_type, "d", __VA_ARGS__)
 
 /*****************************************************************************/
 
-#define _nm_g_slice_free_fcn_define(mem_size) \
-static inline void \
-_nm_g_slice_free_fcn_##mem_size (gpointer mem_block) \
-{ \
-	g_slice_free1 (mem_size, mem_block); \
-}
-
-_nm_g_slice_free_fcn_define (1)
-_nm_g_slice_free_fcn_define (2)
-_nm_g_slice_free_fcn_define (4)
-_nm_g_slice_free_fcn_define (8)
-_nm_g_slice_free_fcn_define (10)
-_nm_g_slice_free_fcn_define (12)
-_nm_g_slice_free_fcn_define (16)
-_nm_g_slice_free_fcn_define (32)
-
-#define nm_g_slice_free_fcn1(mem_size) \
-	({ \
-		void (*_fcn) (gpointer); \
-		\
-		/* If mem_size is a compile time constant, the compiler
-		 * will be able to optimize this. Hence, you don't want
-		 * to call this with a non-constant size argument. */ \
-		G_STATIC_ASSERT_EXPR (   ((mem_size) ==  1) \
-		                      || ((mem_size) ==  2) \
-		                      || ((mem_size) ==  4) \
-		                      || ((mem_size) ==  8) \
-		                      || ((mem_size) == 10) \
-		                      || ((mem_size) == 12) \
-		                      || ((mem_size) == 16) \
-		                      || ((mem_size) == 32)); \
-		switch ((mem_size)) { \
-		case  1: _fcn = _nm_g_slice_free_fcn_1;  break; \
-		case  2: _fcn = _nm_g_slice_free_fcn_2;  break; \
-		case  4: _fcn = _nm_g_slice_free_fcn_4;  break; \
-		case  8: _fcn = _nm_g_slice_free_fcn_8;  break; \
-		case 10: _fcn = _nm_g_slice_free_fcn_10; break; \
-		case 12: _fcn = _nm_g_slice_free_fcn_12; break; \
-		case 16: _fcn = _nm_g_slice_free_fcn_16; break; \
-		case 32: _fcn = _nm_g_slice_free_fcn_32; break; \
-		default: g_assert_not_reached (); _fcn = NULL; break; \
-		} \
-		_fcn; \
-	})
+#define _nm_g_slice_free_fcn_define(mem_size)                              \
+    static inline void _nm_g_slice_free_fcn_##mem_size(gpointer mem_block) \
+    {                                                                      \
+        g_slice_free1(mem_size, mem_block);                                \
+    }
+
+_nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_fcn_define(4)
+    _nm_g_slice_free_fcn_define(8) _nm_g_slice_free_fcn_define(10) _nm_g_slice_free_fcn_define(12)
+        _nm_g_slice_free_fcn_define(16) _nm_g_slice_free_fcn_define(32)
+
+#define nm_g_slice_free_fcn1(mem_size)                                                        \
+    ({                                                                                        \
+        void (*_fcn)(gpointer);                                                               \
+                                                                                              \
+        /* If mem_size is a compile time constant, the compiler
+         * will be able to optimize this. Hence, you don't want
+         * to call this with a non-constant size argument. */                               \
+        G_STATIC_ASSERT_EXPR(((mem_size) == 1) || ((mem_size) == 2) || ((mem_size) == 4)      \
+                             || ((mem_size) == 8) || ((mem_size) == 10) || ((mem_size) == 12) \
+                             || ((mem_size) == 16) || ((mem_size) == 32));                    \
+        switch ((mem_size)) {                                                                 \
+        case 1:                                                                               \
+            _fcn = _nm_g_slice_free_fcn_1;                                                    \
+            break;                                                                            \
+        case 2:                                                                               \
+            _fcn = _nm_g_slice_free_fcn_2;                                                    \
+            break;                                                                            \
+        case 4:                                                                               \
+            _fcn = _nm_g_slice_free_fcn_4;                                                    \
+            break;                                                                            \
+        case 8:                                                                               \
+            _fcn = _nm_g_slice_free_fcn_8;                                                    \
+            break;                                                                            \
+        case 10:                                                                              \
+            _fcn = _nm_g_slice_free_fcn_10;                                                   \
+            break;                                                                            \
+        case 12:                                                                              \
+            _fcn = _nm_g_slice_free_fcn_12;                                                   \
+            break;                                                                            \
+        case 16:                                                                              \
+            _fcn = _nm_g_slice_free_fcn_16;                                                   \
+            break;                                                                            \
+        case 32:                                                                              \
+            _fcn = _nm_g_slice_free_fcn_32;                                                   \
+            break;                                                                            \
+        default:                                                                              \
+            g_assert_not_reached();                                                           \
+            _fcn = NULL;                                                                      \
+            break;                                                                            \
+        }                                                                                     \
+        _fcn;                                                                                 \
+    })
 
 /**
  * nm_g_slice_free_fcn:
@@ -947,9 +866,9 @@ _nm_g_slice_free_fcn_define (32)
  *
  * Only certain types are implemented. You'll get a compile time
  * error for the wrong types. */
-#define nm_g_slice_free_fcn(type) (nm_g_slice_free_fcn1 (sizeof (type)))
+#define nm_g_slice_free_fcn(type) (nm_g_slice_free_fcn1(sizeof(type)))
 
-#define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn (gint64))
+#define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn(gint64))
 
 /*****************************************************************************/
 
@@ -959,44 +878,43 @@ _nm_g_slice_free_fcn_define (32)
  *   be inlined. This macro calls the getter only if there is an error (lazy).
  * - accept a list of allowed codes, instead of only one.
  */
-#define nm_g_error_matches(error, err_domain, ...) \
-	({ \
-		const GError *const _error = (error); \
-		\
-		   _error \
-		&& _error->domain == (err_domain) \
-		&& NM_IN_SET (_error->code, __VA_ARGS__); \
-	})
-
-static inline void
-nm_g_set_error_take (GError **error, GError *error_take)
-{
-	if (!error_take)
-		g_return_if_reached ();
-	if (!error) {
-		g_error_free (error_take);
-		return;
-	}
-	if (*error) {
-		g_error_free (error_take);
-		g_return_if_reached ();
-	}
-	*error = error_take;
-}
-
-#define nm_g_set_error_take_lazy(error, error_take_lazy) \
-	G_STMT_START { \
-		GError **_error = (error); \
-		\
-		if (_error) \
-			nm_g_set_error_take (_error, (error_take_lazy)); \
-	} G_STMT_END
+#define nm_g_error_matches(error, err_domain, ...)                                        \
+    ({                                                                                    \
+        const GError *const _error = (error);                                             \
+                                                                                          \
+        _error && _error->domain == (err_domain) && NM_IN_SET(_error->code, __VA_ARGS__); \
+    })
+
+            static inline void nm_g_set_error_take(GError **error, GError *error_take)
+{
+    if (!error_take)
+        g_return_if_reached();
+    if (!error) {
+        g_error_free(error_take);
+        return;
+    }
+    if (*error) {
+        g_error_free(error_take);
+        g_return_if_reached();
+    }
+    *error = error_take;
+}
+
+#define nm_g_set_error_take_lazy(error, error_take_lazy)    \
+    G_STMT_START                                            \
+    {                                                       \
+        GError **_error = (error);                          \
+                                                            \
+        if (_error)                                         \
+            nm_g_set_error_take(_error, (error_take_lazy)); \
+    }                                                       \
+    G_STMT_END
 
 /**
  * NMUtilsError:
  * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
  * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
- *   pending aynchronous operations, the operation is cancelled with this
+ *   pending asynchronous operations, the operation is cancelled with this
  *   error reason. Depending on the usage, this might indicate a bug because
  *   usually the target object should stay alive as long as there are pending
  *   operations.
@@ -1017,606 +935,705 @@ nm_g_set_error_take (GError **error, GError *error_take)
  * @NM_UTILS_ERROR_INVALID_ARGUMENT: invalid argument.
  */
 typedef enum {
-	NM_UTILS_ERROR_UNKNOWN = 0,                 /*< nick=Unknown >*/
-	NM_UTILS_ERROR_CANCELLED_DISPOSING,         /*< nick=CancelledDisposing >*/
-	NM_UTILS_ERROR_INVALID_ARGUMENT,            /*< nick=InvalidArgument >*/
-
-	/* the following codes have a special meaning and are exactly used for
-	 * nm_device_check_connection_compatible() and nm_device_check_connection_available().
-	 *
-	 * Actually, their meaning is not very important (so, don't think too
-	 * hard about the name of these error codes). What is important, is their
-	 * relative order (i.e. the integer value of the codes). When manager
-	 * searches for a suitable device, it will check all devices whether
-	 * a profile can be activated. If they all fail, it will pick the error
-	 * message from the device that returned the *highest* error code,
-	 * in the hope that this message makes the most sense for the caller.
-	 * */
-	NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
-	NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
-	NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-
-	NM_UTILS_ERROR_SETTING_MISSING,
+    NM_UTILS_ERROR_UNKNOWN = 0,         /*< nick=Unknown >*/
+    NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
+    NM_UTILS_ERROR_INVALID_ARGUMENT,    /*< nick=InvalidArgument >*/
+
+    /* the following codes have a special meaning and are exactly used for
+     * nm_device_check_connection_compatible() and nm_device_check_connection_available().
+     *
+     * Actually, their meaning is not very important (so, don't think too
+     * hard about the name of these error codes). What is important, is their
+     * relative order (i.e. the integer value of the codes). When manager
+     * searches for a suitable device, it will check all devices whether
+     * a profile can be activated. If they all fail, it will pick the error
+     * message from the device that returned the *highest* error code,
+     * in the hope that this message makes the most sense for the caller.
+     * */
+    NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
+    NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
+    NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
+
+    NM_UTILS_ERROR_SETTING_MISSING,
 
 } NMUtilsError;
 
-#define NM_UTILS_ERROR (nm_utils_error_quark ())
-GQuark nm_utils_error_quark (void);
+#define NM_UTILS_ERROR (nm_utils_error_quark())
+GQuark nm_utils_error_quark(void);
 
-void nm_utils_error_set_cancelled (GError **error,
-                                   gboolean is_disposing,
-                                   const char *instance_name);
+void nm_utils_error_set_cancelled(GError **error, gboolean is_disposing, const char *instance_name);
 
 static inline GError *
-nm_utils_error_new_cancelled (gboolean is_disposing,
-                              const char *instance_name)
+nm_utils_error_new_cancelled(gboolean is_disposing, const char *instance_name)
 {
-	GError *error = NULL;
+    GError *error = NULL;
 
-	nm_utils_error_set_cancelled (&error, is_disposing, instance_name);
-	return error;
+    nm_utils_error_set_cancelled(&error, is_disposing, instance_name);
+    return error;
 }
 
-gboolean nm_utils_error_is_cancelled_or_disposing (GError *error);
+gboolean nm_utils_error_is_cancelled_or_disposing(GError *error);
 
 static inline gboolean
-nm_utils_error_is_cancelled (GError *error)
+nm_utils_error_is_cancelled(GError *error)
 {
-	return    error
-	       && error->code == G_IO_ERROR_CANCELLED
-	       && error->domain == G_IO_ERROR;
+    return error && error->code == G_IO_ERROR_CANCELLED && error->domain == G_IO_ERROR;
 }
 
-gboolean nm_utils_error_is_notfound (GError *error);
+gboolean nm_utils_error_is_notfound(GError *error);
 
 static inline void
-nm_utils_error_set_literal (GError **error, int error_code, const char *literal)
-{
-	g_set_error_literal (error, NM_UTILS_ERROR, error_code, literal);
-}
-
-#define nm_utils_error_set(error, error_code, ...) \
-	G_STMT_START { \
-		if (NM_NARG (__VA_ARGS__) == 1) { \
-			g_set_error_literal ((error), NM_UTILS_ERROR, (error_code), _NM_UTILS_MACRO_FIRST (__VA_ARGS__)); \
-		} else { \
-			g_set_error ((error), NM_UTILS_ERROR, (error_code), __VA_ARGS__); \
-		} \
-	} G_STMT_END
-
-#define nm_utils_error_set_errno(error, errsv, fmt, ...) \
-	G_STMT_START { \
-		char _bstrerr[NM_STRERROR_BUFSIZE]; \
-		\
-		g_set_error ((error), \
-		             NM_UTILS_ERROR, \
-		             NM_UTILS_ERROR_UNKNOWN, \
-		             fmt, \
-		             ##__VA_ARGS__, \
-		             nm_strerror_native_r (({ \
-		                                      const int _errsv = (errsv); \
-		                                      \
-		                                      (  _errsv >= 0 \
-		                                       ? _errsv \
-		                                       : (  G_UNLIKELY (_errsv == G_MININT) \
-		                                          ? G_MAXINT \
-		                                          : -errsv)); \
-		                                   }), \
-		                                   _bstrerr, \
-		                                   sizeof (_bstrerr))); \
-	} G_STMT_END
-
-#define nm_utils_error_new(error_code, ...) \
-	(   (NM_NARG (__VA_ARGS__) == 1) \
-	 ? g_error_new_literal (NM_UTILS_ERROR, (error_code), _NM_UTILS_MACRO_FIRST (__VA_ARGS__)) \
-	 : g_error_new         (NM_UTILS_ERROR, (error_code), __VA_ARGS__))
+nm_utils_error_set_literal(GError **error, int error_code, const char *literal)
+{
+    g_set_error_literal(error, NM_UTILS_ERROR, error_code, literal);
+}
+
+#define nm_utils_error_set(error, error_code, ...)                           \
+    G_STMT_START                                                             \
+    {                                                                        \
+        if (NM_NARG(__VA_ARGS__) == 1) {                                     \
+            g_set_error_literal((error),                                     \
+                                NM_UTILS_ERROR,                              \
+                                (error_code),                                \
+                                _NM_UTILS_MACRO_FIRST(__VA_ARGS__));         \
+        } else {                                                             \
+            g_set_error((error), NM_UTILS_ERROR, (error_code), __VA_ARGS__); \
+        }                                                                    \
+    }                                                                        \
+    G_STMT_END
+
+#define nm_utils_error_set_errno(error, errsv, fmt, ...)                                          \
+    G_STMT_START                                                                                  \
+    {                                                                                             \
+        char _bstrerr[NM_STRERROR_BUFSIZE];                                                       \
+                                                                                                  \
+        g_set_error((error),                                                                      \
+                    NM_UTILS_ERROR,                                                               \
+                    NM_UTILS_ERROR_UNKNOWN,                                                       \
+                    fmt,                                                                          \
+                    ##__VA_ARGS__,                                                                \
+                    nm_strerror_native_r(                                                         \
+                        ({                                                                        \
+                            const int _errsv = (errsv);                                           \
+                                                                                                  \
+                            (_errsv >= 0 ? _errsv                                                 \
+                                         : (G_UNLIKELY(_errsv == G_MININT) ? G_MAXINT : -errsv)); \
+                        }),                                                                       \
+                        _bstrerr,                                                                 \
+                        sizeof(_bstrerr)));                                                       \
+    }                                                                                             \
+    G_STMT_END
+
+#define nm_utils_error_new(error_code, ...)                                                      \
+    ((NM_NARG(__VA_ARGS__) == 1)                                                                 \
+         ? g_error_new_literal(NM_UTILS_ERROR, (error_code), _NM_UTILS_MACRO_FIRST(__VA_ARGS__)) \
+         : g_error_new(NM_UTILS_ERROR, (error_code), __VA_ARGS__))
 
 /*****************************************************************************/
 
-gboolean nm_g_object_set_property (GObject *object,
-                                   const char *property_name,
-                                   const GValue *value,
-                                   GError **error);
-
-gboolean nm_g_object_set_property_string (GObject *object,
-                                          const char *property_name,
-                                          const char *value,
-                                          GError **error);
-
-gboolean nm_g_object_set_property_string_static (GObject *object,
-                                                 const char *property_name,
-                                                 const char *value,
-                                                 GError **error);
+gboolean nm_g_object_set_property(GObject *     object,
+                                  const char *  property_name,
+                                  const GValue *value,
+                                  GError **     error);
 
-gboolean nm_g_object_set_property_string_take (GObject *object,
-                                               const char *property_name,
-                                               char *value,
-                                               GError **error);
+gboolean nm_g_object_set_property_string(GObject *   object,
+                                         const char *property_name,
+                                         const char *value,
+                                         GError **   error);
 
-gboolean nm_g_object_set_property_boolean (GObject *object,
-                                           const char *property_name,
-                                           gboolean value,
-                                           GError **error);
+gboolean nm_g_object_set_property_string_static(GObject *   object,
+                                                const char *property_name,
+                                                const char *value,
+                                                GError **   error);
 
-gboolean nm_g_object_set_property_char (GObject *object,
-                                        const char *property_name,
-                                        gint8 value,
-                                        GError **error);
+gboolean nm_g_object_set_property_string_take(GObject *   object,
+                                              const char *property_name,
+                                              char *      value,
+                                              GError **   error);
 
-gboolean nm_g_object_set_property_uchar (GObject *object,
-                                         const char *property_name,
-                                         guint8 value,
-                                         GError **error);
+gboolean nm_g_object_set_property_boolean(GObject *   object,
+                                          const char *property_name,
+                                          gboolean    value,
+                                          GError **   error);
 
-gboolean nm_g_object_set_property_int (GObject *object,
+gboolean nm_g_object_set_property_char(GObject *   object,
                                        const char *property_name,
-                                       int value,
-                                       GError **error);
+                                       gint8       value,
+                                       GError **   error);
 
-gboolean nm_g_object_set_property_int64 (GObject *object,
-                                         const char *property_name,
-                                         gint64 value,
-                                         GError **error);
+gboolean nm_g_object_set_property_uchar(GObject *   object,
+                                        const char *property_name,
+                                        guint8      value,
+                                        GError **   error);
+
+gboolean
+nm_g_object_set_property_int(GObject *object, const char *property_name, int value, GError **error);
 
-gboolean nm_g_object_set_property_uint (GObject *object,
+gboolean nm_g_object_set_property_int64(GObject *   object,
                                         const char *property_name,
-                                        guint value,
-                                        GError **error);
+                                        gint64      value,
+                                        GError **   error);
 
-gboolean nm_g_object_set_property_uint64 (GObject *object,
-                                          const char *property_name,
-                                          guint64 value,
-                                          GError **error);
+gboolean nm_g_object_set_property_uint(GObject *   object,
+                                       const char *property_name,
+                                       guint       value,
+                                       GError **   error);
 
-gboolean nm_g_object_set_property_flags (GObject *object,
+gboolean nm_g_object_set_property_uint64(GObject *   object,
                                          const char *property_name,
-                                         GType gtype,
-                                         guint value,
-                                         GError **error);
+                                         guint64     value,
+                                         GError **   error);
 
-gboolean nm_g_object_set_property_enum (GObject *object,
+gboolean nm_g_object_set_property_flags(GObject *   object,
                                         const char *property_name,
-                                        GType gtype,
-                                        int value,
-                                        GError **error);
+                                        GType       gtype,
+                                        guint       value,
+                                        GError **   error);
 
-GParamSpec *nm_g_object_class_find_property_from_gtype (GType gtype,
-                                                        const char *property_name);
-
-/*****************************************************************************/
+gboolean nm_g_object_set_property_enum(GObject *   object,
+                                       const char *property_name,
+                                       GType       gtype,
+                                       int         value,
+                                       GError **   error);
 
-#define _NM_G_PARAM_SPEC_CAST(param_spec, _value_type, _c_type) \
-	({ \
-		const GParamSpec *const _param_spec = (param_spec); \
-		\
-		nm_assert (   !_param_spec \
-		           || _param_spec->value_type == (_value_type)); \
-		((const _c_type *) _param_spec); \
-	})
+GParamSpec *nm_g_object_class_find_property_from_gtype(GType gtype, const char *property_name);
 
-#define NM_G_PARAM_SPEC_CAST_BOOLEAN(param_spec) _NM_G_PARAM_SPEC_CAST (param_spec, G_TYPE_BOOLEAN, GParamSpecBoolean)
-#define NM_G_PARAM_SPEC_CAST_UINT(param_spec)    _NM_G_PARAM_SPEC_CAST (param_spec, G_TYPE_UINT,    GParamSpecUInt)
-#define NM_G_PARAM_SPEC_CAST_UINT64(param_spec)  _NM_G_PARAM_SPEC_CAST (param_spec, G_TYPE_UINT64,  GParamSpecUInt64)
+/*****************************************************************************/
 
-#define NM_G_PARAM_SPEC_GET_DEFAULT_BOOLEAN(param_spec) (NM_G_PARAM_SPEC_CAST_BOOLEAN (NM_ENSURE_NOT_NULL (param_spec))->default_value)
-#define NM_G_PARAM_SPEC_GET_DEFAULT_UINT(param_spec)    (NM_G_PARAM_SPEC_CAST_UINT    (NM_ENSURE_NOT_NULL (param_spec))->default_value)
-#define NM_G_PARAM_SPEC_GET_DEFAULT_UINT64(param_spec)  (NM_G_PARAM_SPEC_CAST_UINT64  (NM_ENSURE_NOT_NULL (param_spec))->default_value)
+#define _NM_G_PARAM_SPEC_CAST(param_spec, _value_type, _c_type)              \
+    ({                                                                       \
+        const GParamSpec *const _param_spec = (param_spec);                  \
+                                                                             \
+        nm_assert(!_param_spec || _param_spec->value_type == (_value_type)); \
+        ((const _c_type *) _param_spec);                                     \
+    })
+
+#define NM_G_PARAM_SPEC_CAST_BOOLEAN(param_spec) \
+    _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_BOOLEAN, GParamSpecBoolean)
+#define NM_G_PARAM_SPEC_CAST_UINT(param_spec) \
+    _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_UINT, GParamSpecUInt)
+#define NM_G_PARAM_SPEC_CAST_UINT64(param_spec) \
+    _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_UINT64, GParamSpecUInt64)
+
+#define NM_G_PARAM_SPEC_GET_DEFAULT_BOOLEAN(param_spec) \
+    (NM_G_PARAM_SPEC_CAST_BOOLEAN(NM_ENSURE_NOT_NULL(param_spec))->default_value)
+#define NM_G_PARAM_SPEC_GET_DEFAULT_UINT(param_spec) \
+    (NM_G_PARAM_SPEC_CAST_UINT(NM_ENSURE_NOT_NULL(param_spec))->default_value)
+#define NM_G_PARAM_SPEC_GET_DEFAULT_UINT64(param_spec) \
+    (NM_G_PARAM_SPEC_CAST_UINT64(NM_ENSURE_NOT_NULL(param_spec))->default_value)
 
 /*****************************************************************************/
 
-GType nm_g_type_find_implementing_class_for_property (GType gtype,
-                                                      const char *pname);
+GType nm_g_type_find_implementing_class_for_property(GType gtype, const char *pname);
 
 /*****************************************************************************/
 
 typedef enum {
-	NM_UTILS_STR_UTF8_SAFE_FLAG_NONE                = 0,
-
-	/* This flag only has an effect during escaping. */
-	NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL         = 0x0001,
-
-	/* This flag only has an effect during escaping. */
-	NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII    = 0x0002,
-
-	/* This flag only has an effect during escaping to ensure we
-	 * don't leak secrets in memory. Note that during unescape we
-	 * know the maximum result size from the beginning, and no
-	 * reallocation happens. Thus, unescape always avoids leaking
-	 * secrets already. */
-	NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET              = 0x0004,
-
-	/* This flag only has an effect during unescaping. It means
-	 * that non-escaped whitespaces (g_ascii_isspace()) will be
-	 * stripped from the front and end of the string. Note that
-	 * this flag is only useful for gracefully accepting user input
-	 * with spaces. With this flag, escape and unescape may no longer
-	 * yield the original input. */
-	NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES    = 0x0008,
+    NM_UTILS_STR_UTF8_SAFE_FLAG_NONE = 0,
+
+    /* This flag only has an effect during escaping. */
+    NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL = 0x0001,
+
+    /* This flag only has an effect during escaping. */
+    NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII = 0x0002,
+
+    /* This flag only has an effect during escaping to ensure we
+     * don't leak secrets in memory. Note that during unescape we
+     * know the maximum result size from the beginning, and no
+     * reallocation happens. Thus, unescape always avoids leaking
+     * secrets already. */
+    NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET = 0x0004,
+
+    /* This flag only has an effect during unescaping. It means
+     * that non-escaped whitespaces (g_ascii_isspace()) will be
+     * stripped from the front and end of the string. Note that
+     * this flag is only useful for gracefully accepting user input
+     * with spaces. With this flag, escape and unescape may no longer
+     * yield the original input. */
+    NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES = 0x0008,
 } NMUtilsStrUtf8SafeFlags;
 
-const char *nm_utils_buf_utf8safe_escape (gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-char *nm_utils_buf_utf8safe_escape_cp (gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags);
-const char *nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-gconstpointer nm_utils_buf_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, gsize *out_len, gpointer *to_free);
+const char *nm_utils_buf_utf8safe_escape(gconstpointer           buf,
+                                         gssize                  buflen,
+                                         NMUtilsStrUtf8SafeFlags flags,
+                                         char **                 to_free);
+char *
+nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags);
+const char *
+nm_utils_buf_utf8safe_escape_bytes(GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free);
+gconstpointer nm_utils_buf_utf8safe_unescape(const char *            str,
+                                             NMUtilsStrUtf8SafeFlags flags,
+                                             gsize *                 out_len,
+                                             gpointer *              to_free);
 
-const char *nm_utils_str_utf8safe_escape   (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-const char *nm_utils_str_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
+const char *
+nm_utils_str_utf8safe_escape(const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
+const char *
+nm_utils_str_utf8safe_unescape(const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
 
-char *nm_utils_str_utf8safe_escape_cp   (const char *str, NMUtilsStrUtf8SafeFlags flags);
-char *nm_utils_str_utf8safe_unescape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
+char *nm_utils_str_utf8safe_escape_cp(const char *str, NMUtilsStrUtf8SafeFlags flags);
+char *nm_utils_str_utf8safe_unescape_cp(const char *str, NMUtilsStrUtf8SafeFlags flags);
 
-char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);
+char *nm_utils_str_utf8safe_escape_take(char *str, NMUtilsStrUtf8SafeFlags flags);
+
+GVariant *nm_g_variant_singleton_u_0(void);
 
 static inline void
-nm_g_variant_unref_floating (GVariant *var)
-{
-	/* often a function wants to keep a reference to an input variant.
-	 * It uses g_variant_ref_sink() to either increase the ref-count,
-	 * or take ownership of a possibly floating reference.
-	 *
-	 * If the function doesn't actually want to do anything with the
-	 * input variant, it still must make sure that a passed in floating
-	 * reference is consumed. Hence, this helper which:
-	 *
-	 *   - does nothing if @var is not floating
-	 *   - unrefs (consumes) @var if it is floating. */
-	if (g_variant_is_floating (var))
-		g_variant_unref (var);
-}
-
-#define nm_g_variant_lookup(dictionary, ...) \
-	({ \
-		GVariant *const _dictionary = (dictionary); \
-		\
-		(   _dictionary \
-		 && g_variant_lookup (_dictionary, __VA_ARGS__)); \
-	})
+nm_g_variant_unref_floating(GVariant *var)
+{
+    /* often a function wants to keep a reference to an input variant.
+     * It uses g_variant_ref_sink() to either increase the ref-count,
+     * or take ownership of a possibly floating reference.
+     *
+     * If the function doesn't actually want to do anything with the
+     * input variant, it still must make sure that a passed in floating
+     * reference is consumed. Hence, this helper which:
+     *
+     *   - does nothing if @var is not floating
+     *   - unrefs (consumes) @var if it is floating. */
+    if (g_variant_is_floating(var))
+        g_variant_unref(var);
+}
+
+#define nm_g_variant_lookup(dictionary, ...)                         \
+    ({                                                               \
+        GVariant *const _dictionary = (dictionary);                  \
+                                                                     \
+        (_dictionary && g_variant_lookup(_dictionary, __VA_ARGS__)); \
+    })
 
 static inline GVariant *
-nm_g_variant_lookup_value (GVariant *dictionary,
-                           const char *key,
-                           const GVariantType *expected_type)
+nm_g_variant_lookup_value(GVariant *dictionary, const char *key, const GVariantType *expected_type)
 {
-	return   dictionary
-	       ? g_variant_lookup_value (dictionary, key, expected_type)
-	       : NULL;
+    return dictionary ? g_variant_lookup_value(dictionary, key, expected_type) : NULL;
 }
 
 static inline gboolean
-nm_g_variant_is_of_type (GVariant *value,
-                         const GVariantType *type)
+nm_g_variant_is_of_type(GVariant *value, const GVariantType *type)
 {
-	return    value
-	       && g_variant_is_of_type (value, type);
+    return value && g_variant_is_of_type(value, type);
 }
 
 static inline void
-nm_g_variant_builder_add_sv (GVariantBuilder *builder, const char *key, GVariant *val)
+nm_g_variant_builder_add_sv(GVariantBuilder *builder, const char *key, GVariant *val)
 {
-	g_variant_builder_add (builder, "{sv}", key, val);
+    g_variant_builder_add(builder, "{sv}", key, val);
 }
 
 static inline void
-nm_g_variant_builder_add_sv_bytearray (GVariantBuilder *builder, const char *key, const guint8 *arr, gsize len)
+nm_g_variant_builder_add_sv_bytearray(GVariantBuilder *builder,
+                                      const char *     key,
+                                      const guint8 *   arr,
+                                      gsize            len)
 {
-	g_variant_builder_add (builder, "{sv}", key, g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, arr, len, 1));
+    g_variant_builder_add(builder,
+                          "{sv}",
+                          key,
+                          g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, arr, len, 1));
 }
 
 static inline void
-nm_g_variant_builder_add_sv_uint32 (GVariantBuilder *builder, const char *key, guint32 val)
+nm_g_variant_builder_add_sv_uint32(GVariantBuilder *builder, const char *key, guint32 val)
 {
-	nm_g_variant_builder_add_sv (builder, key, g_variant_new_uint32 (val));
+    nm_g_variant_builder_add_sv(builder, key, g_variant_new_uint32(val));
 }
 
 static inline void
-nm_g_variant_builder_add_sv_str (GVariantBuilder *builder, const char *key, const char *str)
+nm_g_variant_builder_add_sv_str(GVariantBuilder *builder, const char *key, const char *str)
 {
-	nm_g_variant_builder_add_sv (builder, key, g_variant_new_string (str));
+    nm_g_variant_builder_add_sv(builder, key, g_variant_new_string(str));
 }
 
 static inline void
-nm_g_source_destroy_and_unref (GSource *source)
+nm_g_source_destroy_and_unref(GSource *source)
 {
-	g_source_destroy (source);
-	g_source_unref (source);
+    g_source_destroy(source);
+    g_source_unref(source);
 }
 
-#define nm_clear_g_source_inst(ptr) (nm_clear_pointer ((ptr), nm_g_source_destroy_and_unref))
+#define nm_clear_g_source_inst(ptr) (nm_clear_pointer((ptr), nm_g_source_destroy_and_unref))
 
-NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_destroy_and_unref_gsource, nm_g_source_destroy_and_unref);
+NM_AUTO_DEFINE_FCN0(GSource *, _nm_auto_destroy_and_unref_gsource, nm_g_source_destroy_and_unref);
 #define nm_auto_destroy_and_unref_gsource nm_auto(_nm_auto_destroy_and_unref_gsource)
 
-NM_AUTO_DEFINE_FCN0 (GMainContext *, _nm_auto_pop_gmaincontext, g_main_context_pop_thread_default)
-#define nm_auto_pop_gmaincontext nm_auto (_nm_auto_pop_gmaincontext)
+NM_AUTO_DEFINE_FCN0(GMainContext *, _nm_auto_pop_gmaincontext, g_main_context_pop_thread_default);
+#define nm_auto_pop_gmaincontext nm_auto(_nm_auto_pop_gmaincontext)
 
 static inline gboolean
-nm_source_func_unref_gobject (gpointer user_data)
-{
-	nm_assert (G_IS_OBJECT (user_data));
-	g_object_unref (user_data);
-	return G_SOURCE_REMOVE;
-}
-
-GSource *nm_g_idle_source_new (int priority,
-                               GSourceFunc func,
-                               gpointer user_data,
-                               GDestroyNotify destroy_notify);
-
-GSource *nm_g_timeout_source_new (guint timeout_msec,
-                                  int priority,
-                                  GSourceFunc func,
-                                  gpointer user_data,
-                                  GDestroyNotify destroy_notify);
-GSource *nm_g_unix_fd_source_new (int fd,
-                                  GIOCondition io_condition,
-                                  int priority,
-                                  gboolean (*source_func) (int fd,
-                                                           GIOCondition condition,
-                                                           gpointer user_data),
-                                  gpointer user_data,
-                                  GDestroyNotify destroy_notify);
-GSource *nm_g_unix_signal_source_new (int signum,
-                                      int priority,
-                                      GSourceFunc handler,
-                                      gpointer user_data,
-                                      GDestroyNotify notify);
+nm_source_func_unref_gobject(gpointer user_data)
+{
+    nm_assert(G_IS_OBJECT(user_data));
+    g_object_unref(user_data);
+    return G_SOURCE_REMOVE;
+}
+
+GSource *nm_g_idle_source_new(int            priority,
+                              GSourceFunc    func,
+                              gpointer       user_data,
+                              GDestroyNotify destroy_notify);
+
+GSource *nm_g_timeout_source_new(guint          timeout_msec,
+                                 int            priority,
+                                 GSourceFunc    func,
+                                 gpointer       user_data,
+                                 GDestroyNotify destroy_notify);
+
+GSource *nm_g_timeout_source_new_seconds(guint          timeout_sec,
+                                         int            priority,
+                                         GSourceFunc    func,
+                                         gpointer       user_data,
+                                         GDestroyNotify destroy_notify);
+
+GSource *
+         nm_g_unix_fd_source_new(int          fd,
+                                 GIOCondition io_condition,
+                                 int          priority,
+                                 gboolean (*source_func)(int fd, GIOCondition condition, gpointer user_data),
+                                 gpointer       user_data,
+                                 GDestroyNotify destroy_notify);
+GSource *nm_g_unix_signal_source_new(int            signum,
+                                     int            priority,
+                                     GSourceFunc    handler,
+                                     gpointer       user_data,
+                                     GDestroyNotify notify);
 
 static inline GSource *
-nm_g_source_attach (GSource *source,
-                    GMainContext *context)
+nm_g_source_attach(GSource *source, GMainContext *context)
 {
-	g_source_attach (source, context);
-	return source;
+    g_source_attach(source, context);
+    return source;
 }
 
-NM_AUTO_DEFINE_FCN0 (GMainContext *, _nm_auto_unref_gmaincontext, g_main_context_unref)
-#define nm_auto_unref_gmaincontext nm_auto (_nm_auto_unref_gmaincontext)
+NM_AUTO_DEFINE_FCN0(GMainContext *, _nm_auto_unref_gmaincontext, g_main_context_unref);
+#define nm_auto_unref_gmaincontext nm_auto(_nm_auto_unref_gmaincontext)
 
 static inline GMainContext *
-nm_g_main_context_push_thread_default (GMainContext *context)
+nm_g_main_context_push_thread_default(GMainContext *context)
 {
-	/* This function is to work together with nm_auto_pop_gmaincontext. */
-	if (G_UNLIKELY (!context))
-		context = g_main_context_default ();
-	g_main_context_push_thread_default (context);
-	return context;
+    /* This function is to work together with nm_auto_pop_gmaincontext. */
+    if (G_UNLIKELY(!context))
+        context = g_main_context_default();
+    g_main_context_push_thread_default(context);
+    return context;
 }
 
 static inline gboolean
-nm_g_main_context_is_thread_default (GMainContext *context)
+nm_g_main_context_is_thread_default(GMainContext *context)
 {
-	GMainContext *cur_context;
+    GMainContext *cur_context;
 
-	cur_context = g_main_context_get_thread_default ();
-	if (cur_context == context)
-		return TRUE;
+    cur_context = g_main_context_get_thread_default();
+    if (cur_context == context)
+        return TRUE;
 
-	if (G_UNLIKELY (!cur_context))
-		cur_context = g_main_context_default ();
-	else if (G_UNLIKELY (!context))
-		context = g_main_context_default ();
-	else
-		return FALSE;
+    if (G_UNLIKELY(!cur_context))
+        cur_context = g_main_context_default();
+    else if (G_UNLIKELY(!context))
+        context = g_main_context_default();
+    else
+        return FALSE;
 
-	return (cur_context == context);
+    return (cur_context == context);
 }
 
 static inline GMainContext *
-nm_g_main_context_push_thread_default_if_necessary (GMainContext *context)
+nm_g_main_context_push_thread_default_if_necessary(GMainContext *context)
 {
-	GMainContext *cur_context;
+    GMainContext *cur_context;
 
-	cur_context = g_main_context_get_thread_default ();
-	if (cur_context == context)
-		return NULL;
+    cur_context = g_main_context_get_thread_default();
+    if (cur_context == context)
+        return NULL;
 
-	if (G_UNLIKELY (!cur_context)) {
-		cur_context = g_main_context_default ();
-		if (cur_context == context)
-			return NULL;
-	} else if (G_UNLIKELY (!context)) {
-		context = g_main_context_default ();
-		if (cur_context == context)
-			return NULL;
-	}
+    if (G_UNLIKELY(!cur_context)) {
+        cur_context = g_main_context_default();
+        if (cur_context == context)
+            return NULL;
+    } else if (G_UNLIKELY(!context)) {
+        context = g_main_context_default();
+        if (cur_context == context)
+            return NULL;
+    }
 
-	g_main_context_push_thread_default (context);
-	return context;
+    g_main_context_push_thread_default(context);
+    return context;
 }
 
 /*****************************************************************************/
 
 static inline int
-nm_utf8_collate0 (const char *a, const char *b)
+nm_utf8_collate0(const char *a, const char *b)
 {
-	if (!a)
-		return !b ? 0 : -1;
-	if (!b)
-		return 1;
-	return g_utf8_collate (a, b);
+    if (!a)
+        return !b ? 0 : -1;
+    if (!b)
+        return 1;
+    return g_utf8_collate(a, b);
 }
 
-int nm_strcmp_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_strcmp0_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data);
-int nm_cmp_int2ptr_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data);
+int nm_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
+int nm_strcmp_p_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
+int nm_strcmp0_p_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
+int nm_strcmp_ascii_case_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
+int nm_cmp_uint32_p_with_data(gconstpointer p_a, gconstpointer p_b, gpointer user_data);
+int nm_cmp_int2ptr_p_with_data(gconstpointer p_a, gconstpointer p_b, gpointer user_data);
 
 /*****************************************************************************/
 
 typedef struct {
-	const char *name;
+    const char *name;
 } NMUtilsNamedEntry;
 
 typedef struct {
-	union {
-		NMUtilsNamedEntry named_entry;
-		const char *name;
-	};
-	union {
-		const char *value_str;
-		gconstpointer value_ptr;
-	};
+    union {
+        NMUtilsNamedEntry named_entry;
+        const char *      name;
+    };
+    union {
+        const char *value_str;
+        gpointer    value_ptr;
+    };
 } NMUtilsNamedValue;
 
-#define NM_UTILS_NAMED_VALUE_INIT(n, v)     { .name = (n), .value_ptr = (v) }
-
-NMUtilsNamedValue *nm_utils_named_values_from_str_dict_with_sort (GHashTable *hash,
-                                                                  guint *out_len,
-                                                                  GCompareDataFunc compare_func,
-                                                                  gpointer user_data);
-
-static inline NMUtilsNamedValue *
-nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len)
-{
-	G_STATIC_ASSERT (G_STRUCT_OFFSET (NMUtilsNamedValue, name) == 0);
-
-	return nm_utils_named_values_from_str_dict_with_sort (hash, out_len, nm_strcmp_p_with_data, NULL);
-}
-
-gssize nm_utils_named_value_list_find (const NMUtilsNamedValue *arr,
-                                       gsize len,
-                                       const char *name,
-                                       gboolean sorted);
-
-gboolean nm_utils_named_value_list_is_sorted (const NMUtilsNamedValue *arr,
-                                              gsize len,
-                                              gboolean accept_duplicates,
-                                              GCompareDataFunc compare_func,
-                                              gpointer user_data);
-
-void nm_utils_named_value_list_sort (NMUtilsNamedValue *arr,
-                                     gsize len,
-                                     GCompareDataFunc compare_func,
-                                     gpointer user_data);
+#define NM_UTILS_NAMED_VALUE_INIT(n, v) \
+    {                                   \
+        .name = (n), .value_ptr = (v)   \
+    }
+
+NMUtilsNamedValue *
+nm_utils_named_values_from_strdict_full(GHashTable *        hash,
+                                        guint *             out_len,
+                                        GCompareDataFunc    compare_func,
+                                        gpointer            user_data,
+                                        NMUtilsNamedValue * provided_buffer,
+                                        guint               provided_buffer_len,
+                                        NMUtilsNamedValue **out_allocated_buffer);
+
+#define nm_utils_named_values_from_strdict(hash, out_len, array, out_allocated_buffer) \
+    nm_utils_named_values_from_strdict_full((hash),                                    \
+                                            (out_len),                                 \
+                                            nm_strcmp_p_with_data,                     \
+                                            NULL,                                      \
+                                            (array),                                   \
+                                            G_N_ELEMENTS(array),                       \
+                                            (out_allocated_buffer))
+
+gssize nm_utils_named_value_list_find(const NMUtilsNamedValue *arr,
+                                      gsize                    len,
+                                      const char *             name,
+                                      gboolean                 sorted);
+
+gboolean nm_utils_named_value_list_is_sorted(const NMUtilsNamedValue *arr,
+                                             gsize                    len,
+                                             gboolean                 accept_duplicates,
+                                             GCompareDataFunc         compare_func,
+                                             gpointer                 user_data);
+
+void nm_utils_named_value_list_sort(NMUtilsNamedValue *arr,
+                                    gsize              len,
+                                    GCompareDataFunc   compare_func,
+                                    gpointer           user_data);
 
 /*****************************************************************************/
 
-gpointer *nm_utils_hash_keys_to_array (GHashTable *hash,
-                                       GCompareDataFunc compare_func,
-                                       gpointer user_data,
-                                       guint *out_len);
+gpointer *nm_utils_hash_keys_to_array(GHashTable *     hash,
+                                      GCompareDataFunc compare_func,
+                                      gpointer         user_data,
+                                      guint *          out_len);
 
-gpointer *nm_utils_hash_values_to_array (GHashTable *hash,
-                                         GCompareDataFunc compare_func,
-                                         gpointer user_data,
-                                         guint *out_len);
+gpointer *nm_utils_hash_values_to_array(GHashTable *     hash,
+                                        GCompareDataFunc compare_func,
+                                        gpointer         user_data,
+                                        guint *          out_len);
 
 static inline const char **
-nm_utils_strdict_get_keys (const GHashTable *hash,
-                           gboolean sorted,
-                           guint *out_length)
+nm_utils_strdict_get_keys(const GHashTable *hash, gboolean sorted, guint *out_length)
 {
-	return (const char **) nm_utils_hash_keys_to_array ((GHashTable *) hash,
-	                                                    sorted ? nm_strcmp_p_with_data : NULL,
-	                                                    NULL,
-	                                                    out_length);
+    return (const char **) nm_utils_hash_keys_to_array((GHashTable *) hash,
+                                                       sorted ? nm_strcmp_p_with_data : NULL,
+                                                       NULL,
+                                                       out_length);
 }
 
-gboolean nm_utils_hashtable_same_keys (const GHashTable *a,
-                                       const GHashTable *b);
+gboolean nm_utils_hashtable_equal(const GHashTable *a,
+                                  const GHashTable *b,
+                                  GCompareDataFunc  cmp_values,
+                                  gpointer          user_data);
 
-char **nm_utils_strv_make_deep_copied (const char **strv);
+static inline gboolean
+nm_utils_hashtable_same_keys(const GHashTable *a, const GHashTable *b)
+{
+    return nm_utils_hashtable_equal(a, b, NULL, NULL);
+}
+
+int nm_utils_hashtable_cmp(const GHashTable *a,
+                           const GHashTable *b,
+                           gboolean          do_fast_precheck,
+                           GCompareDataFunc  cmp_keys,
+                           GCompareDataFunc  cmp_values,
+                           gpointer          user_data);
+
+char **nm_utils_strv_make_deep_copied(const char **strv);
 
-char **nm_utils_strv_make_deep_copied_n (const char **strv, gsize len);
+char **nm_utils_strv_make_deep_copied_n(const char **strv, gsize len);
 
 static inline char **
-nm_utils_strv_make_deep_copied_nonnull (const char **strv)
+nm_utils_strv_make_deep_copied_nonnull(const char **strv)
 {
-	return nm_utils_strv_make_deep_copied (strv) ?: g_new0 (char *, 1);
+    return nm_utils_strv_make_deep_copied(strv) ?: g_new0(char *, 1);
 }
 
-char **nm_utils_strv_dup (gpointer strv,
-                          gssize len,
-                          gboolean deep_copied);
+char **_nm_utils_strv_dup(const char *const *strv, gssize len, gboolean deep_copied);
+
+#define nm_utils_strv_dup(strv, len, deep_copied) \
+    _nm_utils_strv_dup(NM_CAST_STRV_CC(strv), (len), (deep_copied))
+
+const char **_nm_utils_strv_dup_packed(const char *const *strv, gssize len);
+
+#define nm_utils_strv_dup_packed(strv, len) _nm_utils_strv_dup_packed(NM_CAST_STRV_CC(strv), (len))
 
 /*****************************************************************************/
 
-GSList *nm_utils_g_slist_find_str (const GSList *list,
-                                   const char *needle);
+GSList *nm_utils_g_slist_find_str(const GSList *list, const char *needle);
 
-int nm_utils_g_slist_strlist_cmp (const GSList *a, const GSList *b);
+int nm_utils_g_slist_strlist_cmp(const GSList *a, const GSList *b);
 
-char *nm_utils_g_slist_strlist_join (const GSList *a, const char *separator);
+char *nm_utils_g_slist_strlist_join(const GSList *a, const char *separator);
 
 /*****************************************************************************/
 
 static inline guint
-nm_g_array_len (const GArray *arr)
+nm_g_array_len(const GArray *arr)
 {
-	return arr ? arr->len : 0u;
+    return arr ? arr->len : 0u;
 }
 
+#define nm_g_array_append_new(arr, type)   \
+    ({                                     \
+        GArray *const _arr = (arr);        \
+        guint         _len;                \
+                                           \
+        nm_assert(_arr);                   \
+        _len = _arr->len;                  \
+        nm_assert(_len < G_MAXUINT);       \
+        g_array_set_size(_arr, _len + 1u); \
+        &g_array_index(arr, type, _len);   \
+    })
+
 /*****************************************************************************/
 
 static inline guint
-nm_g_ptr_array_len (const GPtrArray *arr)
+nm_g_ptr_array_len(const GPtrArray *arr)
 {
-	return arr ? arr->len : 0u;
+    return arr ? arr->len : 0u;
 }
 
+static inline gpointer *
+nm_g_ptr_array_pdata(const GPtrArray *arr)
+{
+    return arr ? arr->pdata : NULL;
+}
+
+GPtrArray *_nm_g_ptr_array_copy(GPtrArray *    array,
+                                GCopyFunc      func,
+                                gpointer       user_data,
+                                GDestroyNotify element_free_func);
+
+/**
+ * nm_g_ptr_array_copy:
+ * @array: the #GPtrArray to clone.
+ * @func: the copy function.
+ * @user_data: the user data for the copy function
+ * @element_free_func: the free function of the elements. @array MUST have
+ *   the same element_free_func. This argument is only used on older
+ *   glib, that doesn't support g_ptr_array_copy().
+ *
+ * This is a replacement for g_ptr_array_copy(), which is not available
+ * before glib 2.62. Since GPtrArray does not allow to access the internal
+ * element_free_func, we cannot add a compatibility implementation of g_ptr_array_copy()
+ * and the user must provide a suitable destroy function.
+ *
+ * Note that the @element_free_func MUST correspond to free function set in @array.
+ */
+#if GLIB_CHECK_VERSION(2, 62, 0)
+    #define nm_g_ptr_array_copy(array, func, user_data, element_free_func)            \
+        ({                                                                            \
+            _nm_unused GDestroyNotify const _element_free_func = (element_free_func); \
+                                                                                      \
+            G_GNUC_BEGIN_IGNORE_DEPRECATIONS;                                         \
+            g_ptr_array_copy((array), (func), (user_data));                           \
+            G_GNUC_END_IGNORE_DEPRECATIONS;                                           \
+        })
+#else
+    #define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \
+        _nm_g_ptr_array_copy((array), (func), (user_data), (element_free_func))
+#endif
+
 /*****************************************************************************/
 
 static inline guint
-nm_g_hash_table_size (GHashTable *hash)
+nm_g_hash_table_size(GHashTable *hash)
 {
-	return hash ? g_hash_table_size (hash) : 0u;
+    return hash ? g_hash_table_size(hash) : 0u;
 }
 
 static inline gpointer
-nm_g_hash_table_lookup (GHashTable *hash, gconstpointer key)
+nm_g_hash_table_lookup(GHashTable *hash, gconstpointer key)
 {
-	return hash ? g_hash_table_lookup (hash, key) : NULL;
+    return hash ? g_hash_table_lookup(hash, key) : NULL;
 }
 
 static inline gboolean
-nm_g_hash_table_remove (GHashTable *hash, gconstpointer key)
+nm_g_hash_table_contains(GHashTable *hash, gconstpointer key)
 {
-	return hash ? g_hash_table_remove (hash, key) : FALSE;
+    return hash ? g_hash_table_contains(hash, key) : FALSE;
+}
+
+static inline gboolean
+nm_g_hash_table_remove(GHashTable *hash, gconstpointer key)
+{
+    return hash ? g_hash_table_remove(hash, key) : FALSE;
 }
 
 /*****************************************************************************/
 
-gssize nm_utils_ptrarray_find_binary_search (gconstpointer *list,
-                                             gsize len,
-                                             gconstpointer needle,
-                                             GCompareDataFunc cmpfcn,
-                                             gpointer user_data,
-                                             gssize *out_idx_first,
-                                             gssize *out_idx_last);
-
-gssize nm_utils_array_find_binary_search (gconstpointer list,
-                                          gsize elem_size,
-                                          gsize len,
-                                          gconstpointer needle,
-                                          GCompareDataFunc cmpfcn,
-                                          gpointer user_data);
+gssize nm_utils_ptrarray_find_binary_search(gconstpointer *  list,
+                                            gsize            len,
+                                            gconstpointer    needle,
+                                            GCompareDataFunc cmpfcn,
+                                            gpointer         user_data,
+                                            gssize *         out_idx_first,
+                                            gssize *         out_idx_last);
+
+gssize nm_utils_array_find_binary_search(gconstpointer    list,
+                                         gsize            elem_size,
+                                         gsize            len,
+                                         gconstpointer    needle,
+                                         GCompareDataFunc cmpfcn,
+                                         gpointer         user_data);
 
 /*****************************************************************************/
 
-typedef gboolean (*NMUtilsHashTableEqualFunc) (gconstpointer a,
-                                               gconstpointer b);
+typedef gboolean (*NMUtilsHashTableEqualFunc)(gconstpointer a, gconstpointer b);
 
-gboolean nm_utils_hash_table_equal (const GHashTable *a,
-                                    const GHashTable *b,
-                                    gboolean treat_null_as_empty,
-                                    NMUtilsHashTableEqualFunc equal_func);
+gboolean nm_utils_hash_table_equal(const GHashTable *        a,
+                                   const GHashTable *        b,
+                                   gboolean                  treat_null_as_empty,
+                                   NMUtilsHashTableEqualFunc equal_func);
 
 /*****************************************************************************/
 
-void _nm_utils_strv_sort (const char **strv, gssize len);
-#define nm_utils_strv_sort(strv, len) _nm_utils_strv_sort (NM_CAST_STRV_MC (strv), len)
+void _nm_utils_strv_sort(const char **strv, gssize len);
+#define nm_utils_strv_sort(strv, len) _nm_utils_strv_sort(NM_CAST_STRV_MC(strv), len)
 
-int _nm_utils_strv_cmp_n (const char *const*strv1,
-                          gssize len1,
-                          const char *const*strv2,
-                          gssize len2);
+int
+_nm_utils_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *strv2, gssize len2);
 
 static inline gboolean
-_nm_utils_strv_equal (char **strv1, char **strv2)
+_nm_utils_strv_equal(char **strv1, char **strv2)
 {
-	return _nm_utils_strv_cmp_n ((const char *const*) strv1, -1,
-	                             (const char *const*) strv2, -1) == 0;
+    return _nm_utils_strv_cmp_n((const char *const *) strv1, -1, (const char *const *) strv2, -1)
+           == 0;
 }
 
 /*****************************************************************************/
@@ -1627,460 +1644,616 @@ _nm_utils_strv_equal (char **strv1, char **strv2)
 #define NM_UTILS_NSEC_PER_MSEC ((gint64) 1000000)
 
 static inline gint64
-NM_UTILS_NSEC_TO_MSEC_CEIL (gint64 nsec)
+NM_UTILS_NSEC_TO_MSEC_CEIL(gint64 nsec)
 {
-	return (nsec + (NM_UTILS_NSEC_PER_MSEC - 1)) / NM_UTILS_NSEC_PER_MSEC;
+    return (nsec + (NM_UTILS_NSEC_PER_MSEC - 1)) / NM_UTILS_NSEC_PER_MSEC;
 }
 
 /*****************************************************************************/
 
-int nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_nsec);
-ssize_t nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll);
-int nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll);
+int     nm_utils_fd_wait_for_event(int fd, int event, gint64 timeout_nsec);
+ssize_t nm_utils_fd_read_loop(int fd, void *buf, size_t nbytes, bool do_poll);
+int     nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_poll);
 
 /*****************************************************************************/
 
 #define NM_DEFINE_GDBUS_ARG_INFO_FULL(name_, ...) \
-	((GDBusArgInfo *) (&((const GDBusArgInfo) { \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	})))
+    ((GDBusArgInfo *) (&((const GDBusArgInfo){.ref_count = -1, .name = name_, __VA_ARGS__})))
 
 #define NM_DEFINE_GDBUS_ARG_INFO(name_, a_signature) \
-	NM_DEFINE_GDBUS_ARG_INFO_FULL ( \
-		name_, \
-		.signature = a_signature, \
-	)
+    NM_DEFINE_GDBUS_ARG_INFO_FULL(name_, .signature = a_signature, )
 
-#define NM_DEFINE_GDBUS_ARG_INFOS(...) \
-	((GDBusArgInfo **) ((const GDBusArgInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
+#define NM_DEFINE_GDBUS_ARG_INFOS(...)            \
+    ((GDBusArgInfo **) ((const GDBusArgInfo *[]){ \
+        __VA_ARGS__ NULL,                         \
+    }))
 
 #define NM_DEFINE_GDBUS_PROPERTY_INFO(name_, ...) \
-	((GDBusPropertyInfo *) (&((const GDBusPropertyInfo) { \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	})))
+    ((GDBusPropertyInfo *) (&(                    \
+        (const GDBusPropertyInfo){.ref_count = -1, .name = name_, __VA_ARGS__})))
 
 #define NM_DEFINE_GDBUS_PROPERTY_INFO_READABLE(name_, m_signature) \
-	NM_DEFINE_GDBUS_PROPERTY_INFO ( \
-		name_, \
-		.signature = m_signature, \
-		.flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE, \
-	)
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFOS(...) \
-	((GDBusPropertyInfo **) ((const GDBusPropertyInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
+    NM_DEFINE_GDBUS_PROPERTY_INFO(name_,                           \
+                                  .signature = m_signature,        \
+                                  .flags     = G_DBUS_PROPERTY_INFO_FLAGS_READABLE, )
+
+#define NM_DEFINE_GDBUS_PROPERTY_INFOS(...)                 \
+    ((GDBusPropertyInfo **) ((const GDBusPropertyInfo *[]){ \
+        __VA_ARGS__ NULL,                                   \
+    }))
 
 #define NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(name_, ...) \
-	{ \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	}
+    {                                                \
+        .ref_count = -1, .name = name_, __VA_ARGS__  \
+    }
 
 #define NM_DEFINE_GDBUS_SIGNAL_INFO(name_, ...) \
-	((GDBusSignalInfo *) (&((const GDBusSignalInfo) NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (name_, __VA_ARGS__))))
+    ((GDBusSignalInfo *) (&(                    \
+        (const GDBusSignalInfo) NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(name_, __VA_ARGS__))))
 
-#define NM_DEFINE_GDBUS_SIGNAL_INFOS(...) \
-	((GDBusSignalInfo **) ((const GDBusSignalInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
+#define NM_DEFINE_GDBUS_SIGNAL_INFOS(...)               \
+    ((GDBusSignalInfo **) ((const GDBusSignalInfo *[]){ \
+        __VA_ARGS__ NULL,                               \
+    }))
 
 #define NM_DEFINE_GDBUS_METHOD_INFO_INIT(name_, ...) \
-	{ \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	}
+    {                                                \
+        .ref_count = -1, .name = name_, __VA_ARGS__  \
+    }
 
 #define NM_DEFINE_GDBUS_METHOD_INFO(name_, ...) \
-	((GDBusMethodInfo *) (&((const GDBusMethodInfo) NM_DEFINE_GDBUS_METHOD_INFO_INIT (name_, __VA_ARGS__))))
+    ((GDBusMethodInfo *) (&(                    \
+        (const GDBusMethodInfo) NM_DEFINE_GDBUS_METHOD_INFO_INIT(name_, __VA_ARGS__))))
 
-#define NM_DEFINE_GDBUS_METHOD_INFOS(...) \
-	((GDBusMethodInfo **) ((const GDBusMethodInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
+#define NM_DEFINE_GDBUS_METHOD_INFOS(...)               \
+    ((GDBusMethodInfo **) ((const GDBusMethodInfo *[]){ \
+        __VA_ARGS__ NULL,                               \
+    }))
 
 #define NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, ...) \
-	{ \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	}
+    {                                                   \
+        .ref_count = -1, .name = name_, __VA_ARGS__     \
+    }
 
 #define NM_DEFINE_GDBUS_INTERFACE_INFO(name_, ...) \
-	((GDBusInterfaceInfo *) (&((const GDBusInterfaceInfo) NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (name_, __VA_ARGS__))))
+    ((GDBusInterfaceInfo *) (&(                    \
+        (const GDBusInterfaceInfo) NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, __VA_ARGS__))))
 
 #define NM_DEFINE_GDBUS_INTERFACE_VTABLE(...) \
-	((GDBusInterfaceVTable *) (&((const GDBusInterfaceVTable) { \
-		__VA_ARGS__ \
-	})))
+    ((GDBusInterfaceVTable *) (&((const GDBusInterfaceVTable){__VA_ARGS__})))
 
 /*****************************************************************************/
 
-guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
+guint64 nm_utils_get_start_time_for_pid(pid_t pid, char *out_state, pid_t *out_ppid);
 
 static inline gboolean
-nm_utils_process_state_is_dead (char pstate)
+nm_utils_process_state_is_dead(char pstate)
 {
-	/* "/proc/[pid]/stat" returns a state as the 3rd fields (see `man 5 proc`).
-	 * Some of these states indicate the the process is effectively dead (or a zombie).
-	 */
-	return NM_IN_SET (pstate, 'Z', 'x', 'X');
+    /* "/proc/[pid]/stat" returns a state as the 3rd fields (see `man 5 proc`).
+     * Some of these states indicate the process is effectively dead (or a zombie).
+     */
+    return NM_IN_SET(pstate, 'Z', 'x', 'X');
 }
 
 /*****************************************************************************/
 
-gpointer _nm_utils_user_data_pack (int nargs, gconstpointer *args);
+gpointer _nm_utils_user_data_pack(int nargs, gconstpointer *args);
 
 #define nm_utils_user_data_pack(...) \
-	_nm_utils_user_data_pack(NM_NARG (__VA_ARGS__), (gconstpointer[]) { __VA_ARGS__ })
+    _nm_utils_user_data_pack(NM_NARG(__VA_ARGS__), (gconstpointer[]){__VA_ARGS__})
 
-void _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...);
+void _nm_utils_user_data_unpack(gpointer user_data, int nargs, ...);
 
 #define nm_utils_user_data_unpack(user_data, ...) \
-	_nm_utils_user_data_unpack(user_data, NM_NARG (__VA_ARGS__), __VA_ARGS__)
+    _nm_utils_user_data_unpack(user_data, NM_NARG(__VA_ARGS__), __VA_ARGS__)
 
 /*****************************************************************************/
 
-typedef void (*NMUtilsInvokeOnIdleCallback) (gpointer user_data,
-                                             GCancellable *cancellable);
+typedef void (*NMUtilsInvokeOnIdleCallback)(gpointer user_data, GCancellable *cancellable);
 
-void nm_utils_invoke_on_idle (GCancellable *cancellable,
-                              NMUtilsInvokeOnIdleCallback callback,
-                              gpointer callback_user_data);
+void nm_utils_invoke_on_idle(GCancellable *              cancellable,
+                             NMUtilsInvokeOnIdleCallback callback,
+                             gpointer                    callback_user_data);
 
-void nm_utils_invoke_on_timeout (guint timeout_msec,
-                                 GCancellable *cancellable,
-                                 NMUtilsInvokeOnIdleCallback callback,
-                                 gpointer callback_user_data);
+void nm_utils_invoke_on_timeout(guint                       timeout_msec,
+                                GCancellable *              cancellable,
+                                NMUtilsInvokeOnIdleCallback callback,
+                                gpointer                    callback_user_data);
 
 /*****************************************************************************/
 
-GSource *nm_utils_g_main_context_create_integrate_source (GMainContext *internal);
+GSource *nm_utils_g_main_context_create_integrate_source(GMainContext *internal);
 
 /*****************************************************************************/
 
+static inline GPtrArray *
+nm_strv_ptrarray_ensure(GPtrArray **p_arr)
+{
+    nm_assert(p_arr);
+
+    if (G_UNLIKELY(!*p_arr))
+        *p_arr = g_ptr_array_new_with_free_func(g_free);
+
+    return *p_arr;
+}
+
+static inline const char *const *
+nm_strv_ptrarray_get_unsafe(GPtrArray *arr, guint *out_len)
+{
+    /* warning: the GPtrArray is not NULL terminated. So, it
+     * isn't really a strv array (sorry the misnomer). That's why
+     * the function is potentially "unsafe" and you must provide a
+     * out_len parameter. */
+    if (!arr || arr->len == 0) {
+        *out_len = 0;
+        return NULL;
+    }
+    *out_len = arr->len;
+    return (const char *const *) arr->pdata;
+}
+
+static inline GPtrArray *
+nm_strv_ptrarray_clone(const GPtrArray *src, gboolean null_if_empty)
+{
+    if (!src || (null_if_empty && src->len == 0))
+        return NULL;
+    return nm_g_ptr_array_copy((GPtrArray *) src, nm_copy_func_g_strdup, NULL, g_free);
+}
+
 static inline void
-nm_strv_ptrarray_add_string_take (GPtrArray *cmd,
-                                  char *str)
+nm_strv_ptrarray_add_string_take(GPtrArray *cmd, char *str)
 {
-	nm_assert (cmd);
-	nm_assert (str);
+    nm_assert(cmd);
+    nm_assert(str);
 
-	g_ptr_array_add (cmd, str);
+    g_ptr_array_add(cmd, str);
 }
 
 static inline void
-nm_strv_ptrarray_add_string_dup (GPtrArray *cmd,
-                                 const char *str)
+nm_strv_ptrarray_add_string_dup(GPtrArray *cmd, const char *str)
 {
-	nm_strv_ptrarray_add_string_take (cmd,
-	                                  g_strdup (str));
+    nm_strv_ptrarray_add_string_take(cmd, g_strdup(str));
 }
 
 #define nm_strv_ptrarray_add_string_concat(cmd, ...) \
-	nm_strv_ptrarray_add_string_take ((cmd), g_strconcat (__VA_ARGS__, NULL))
+    nm_strv_ptrarray_add_string_take((cmd), g_strconcat(__VA_ARGS__, NULL))
 
 #define nm_strv_ptrarray_add_string_printf(cmd, ...) \
-	nm_strv_ptrarray_add_string_take ((cmd), g_strdup_printf (__VA_ARGS__))
+    nm_strv_ptrarray_add_string_take((cmd), g_strdup_printf(__VA_ARGS__))
 
 #define nm_strv_ptrarray_add_int(cmd, val) \
-	nm_strv_ptrarray_add_string_take ((cmd), nm_strdup_int (val))
+    nm_strv_ptrarray_add_string_take((cmd), nm_strdup_int(val))
 
 static inline void
-nm_strv_ptrarray_take_gstring (GPtrArray *cmd,
-                               GString **gstr)
+nm_strv_ptrarray_take_gstring(GPtrArray *cmd, GString **gstr)
 {
-	nm_assert (gstr && *gstr);
+    nm_assert(gstr && *gstr);
+
+    nm_strv_ptrarray_add_string_take(cmd, g_string_free(g_steal_pointer(gstr), FALSE));
+}
+
+static inline gssize
+nm_strv_ptrarray_find_first(const GPtrArray *strv, const char *str)
+{
+    if (!strv)
+        return -1;
+    return nm_utils_strv_find_first((char **) strv->pdata, strv->len, str);
+}
+
+static inline gboolean
+nm_strv_ptrarray_contains(const GPtrArray *strv, const char *str)
+{
+    return nm_strv_ptrarray_find_first(strv, str) >= 0;
+}
 
-	nm_strv_ptrarray_add_string_take (cmd,
-	                                  g_string_free (g_steal_pointer (gstr),
-	                                                 FALSE));
+static inline int
+nm_strv_ptrarray_cmp(const GPtrArray *a, const GPtrArray *b)
+{
+    /* _nm_utils_strv_cmp_n() will treat NULL and empty arrays the same.
+     * That means, an empty strv array can both be represented by NULL
+     * and an array of length zero.
+     * If you need to distinguish between these case, do that yourself. */
+    return _nm_utils_strv_cmp_n((const char *const *) nm_g_ptr_array_pdata(a),
+                                nm_g_ptr_array_len(a),
+                                (const char *const *) nm_g_ptr_array_pdata(b),
+                                nm_g_ptr_array_len(b));
 }
 
 /*****************************************************************************/
 
-int nm_utils_getpagesize (void);
+int nm_utils_getpagesize(void);
 
 /*****************************************************************************/
 
-char *nm_utils_bin2hexstr_full (gconstpointer addr,
-                                gsize length,
-                                char delimiter,
-                                gboolean upper_case,
-                                char *out);
+extern const char _nm_hexchar_table_lower[16];
+extern const char _nm_hexchar_table_upper[16];
 
-guint8 *nm_utils_hexstr2bin_full (const char *hexstr,
-                                  gboolean allow_0x_prefix,
-                                  gboolean delimiter_required,
+static inline char
+nm_hexchar(int x, gboolean upper_case)
+{
+    return upper_case ? _nm_hexchar_table_upper[x & 15] : _nm_hexchar_table_lower[x & 15];
+}
+
+char *nm_utils_bin2hexstr_full(gconstpointer addr,
+                               gsize         length,
+                               char          delimiter,
+                               gboolean      upper_case,
+                               char *        out);
+
+#define nm_utils_bin2hexstr_a(addr, length, delimiter, upper_case, str_to_free)               \
+    ({                                                                                        \
+        gconstpointer _addr        = (addr);                                                  \
+        gsize         _length      = (length);                                                \
+        char          _delimiter   = (delimiter);                                             \
+        char **       _str_to_free = (str_to_free);                                           \
+        char *        _s;                                                                     \
+        gsize         _s_len;                                                                 \
+                                                                                              \
+        nm_assert(_str_to_free);                                                              \
+                                                                                              \
+        _s_len = _length == 0 ? 1u : (_delimiter == '\0' ? _length * 2u + 1u : _length * 3u); \
+        if (_s_len < 100)                                                                     \
+            _s = g_alloca(_s_len);                                                            \
+        else {                                                                                \
+            _s            = g_malloc(_s_len);                                                 \
+            *_str_to_free = _s;                                                               \
+        }                                                                                     \
+        nm_utils_bin2hexstr_full(_addr, _length, _delimiter, (upper_case), _s);               \
+    })
+
+static inline const char *
+nm_ether_addr_to_string(const NMEtherAddr *ether_addr, char sbuf[static(sizeof(NMEtherAddr) * 3)])
+{
+    nm_assert(ether_addr);
+    nm_assert(sbuf);
+
+    return nm_utils_bin2hexstr_full(ether_addr, sizeof(NMEtherAddr), ':', TRUE, sbuf);
+}
+
+#define nm_ether_addr_to_string_a(ether_addr) \
+    nm_ether_addr_to_string((ether_addr), g_alloca(sizeof(NMEtherAddr) * 3))
+
+guint8 *nm_utils_hexstr2bin_full(const char *hexstr,
+                                 gboolean    allow_0x_prefix,
+                                 gboolean    delimiter_required,
+                                 gboolean    hexdigit_pairs_required,
+                                 const char *delimiter_candidates,
+                                 gsize       required_len,
+                                 guint8 *    buffer,
+                                 gsize       buffer_len,
+                                 gsize *     out_len);
+
+#define nm_utils_hexstr2bin_buf(hexstr,               \
+                                allow_0x_prefix,      \
+                                delimiter_required,   \
+                                delimiter_candidates, \
+                                buffer)               \
+    nm_utils_hexstr2bin_full((hexstr),                \
+                             (allow_0x_prefix),       \
+                             (delimiter_required),    \
+                             FALSE,                   \
+                             (delimiter_candidates),  \
+                             G_N_ELEMENTS(buffer),    \
+                             (buffer),                \
+                             G_N_ELEMENTS(buffer),    \
+                             NULL)
+
+guint8 *nm_utils_hexstr2bin_alloc(const char *hexstr,
+                                  gboolean    allow_0x_prefix,
+                                  gboolean    delimiter_required,
                                   const char *delimiter_candidates,
-                                  gsize required_len,
-                                  guint8 *buffer,
-                                  gsize buffer_len,
-                                  gsize *out_len);
+                                  gsize       required_len,
+                                  gsize *     out_len);
+
+/**
+ * _nm_utils_hwaddr_aton:
+ * @asc: the ASCII representation of a hardware address
+ * @buffer: buffer to store the result into. Must have
+ *   at least a size of @buffer_length.
+ * @buffer_length: the length of the input buffer @buffer.
+ *   The result must fit into that buffer, otherwise
+ *   the function fails and returns %NULL.
+ * @out_length: the output length in case of success.
+ *
+ * Parses @asc and converts it to binary form in @buffer.
+ * Bytes in @asc can be separated by colons (:), or hyphens (-), but not mixed.
+ *
+ * It is like nm_utils_hwaddr_aton(), but contrary to that it
+ * can parse addresses of any length. That is, you don't need
+ * to know the length before-hand.
+ *
+ * Return value: @buffer, or %NULL if @asc couldn't be parsed.
+ */
+static inline guint8 *
+_nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length)
+{
+    g_return_val_if_fail(asc, NULL);
+    g_return_val_if_fail(buffer, NULL);
+    g_return_val_if_fail(buffer_length > 0, NULL);
+    g_return_val_if_fail(out_length, NULL);
 
-#define nm_utils_hexstr2bin_buf(hexstr, allow_0x_prefix, delimiter_required, delimiter_candidates, buffer) \
-    nm_utils_hexstr2bin_full ((hexstr), (allow_0x_prefix), (delimiter_required), (delimiter_candidates), G_N_ELEMENTS (buffer), (buffer), G_N_ELEMENTS (buffer), NULL)
+    return nm_utils_hexstr2bin_full(asc,
+                                    FALSE,
+                                    TRUE,
+                                    FALSE,
+                                    ":-",
+                                    0,
+                                    buffer,
+                                    buffer_length,
+                                    out_length);
+}
 
-guint8 *nm_utils_hexstr2bin_alloc (const char *hexstr,
-                                   gboolean allow_0x_prefix,
-                                   gboolean delimiter_required,
-                                   const char *delimiter_candidates,
-                                   gsize required_len,
-                                   gsize *out_len);
+static inline const char *
+_nm_utils_hwaddr_ntoa(gconstpointer addr,
+                      gsize         addr_len,
+                      gboolean      upper_case,
+                      char *        buf,
+                      gsize         buf_len)
+{
+    g_return_val_if_fail(addr, NULL);
+    g_return_val_if_fail(addr_len > 0, NULL);
+    g_return_val_if_fail(buf, NULL);
+    if (buf_len < addr_len * 3)
+        g_return_val_if_reached(NULL);
+
+    return nm_utils_bin2hexstr_full(addr, addr_len, ':', upper_case, buf);
+}
 
 /*****************************************************************************/
 
-#define _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \
-                                             value_type, \
-                                             value_type_result, \
-                                             entry_cmd, \
-                                             unknown_val_cmd, \
-                                             get_operator, \
-                                             ...) \
-value_type_result \
-fcn_name (const char *name) \
-{ \
-	static const struct { \
-		const char *name; \
-		value_type value; \
-	} LIST[] = { \
-		__VA_ARGS__ \
-	}; \
-	\
-	if (NM_MORE_ASSERT_ONCE (5)) { \
-		int i; \
-		\
-		for (i = 0; i < G_N_ELEMENTS (LIST); i++) { \
-			nm_assert (LIST[i].name); \
-			if (i > 0) \
-				nm_assert (strcmp (LIST[i - 1].name, LIST[i].name) < 0); \
-		} \
-	} \
-	\
-	{ entry_cmd; } \
-	\
-	if (G_LIKELY (name)) { \
-		G_STATIC_ASSERT (G_N_ELEMENTS (LIST) > 1); \
-		G_STATIC_ASSERT (G_N_ELEMENTS (LIST) < G_MAXINT / 2 - 10); \
-		int imin = 0; \
-		int imax = (G_N_ELEMENTS (LIST) - 1); \
-		int imid = (G_N_ELEMENTS (LIST) - 1) / 2; \
-		\
-		for (;;) { \
-			const int cmp = strcmp (LIST[imid].name, name); \
-			\
-			if (G_UNLIKELY (cmp == 0)) \
-				return get_operator (LIST[imid].value); \
-			\
-			if (cmp < 0) \
-				imin = imid + 1; \
-			else \
-				imax = imid - 1; \
-			\
-			if (G_UNLIKELY (imin > imax)) \
-				break; \
-			\
-			/* integer overflow cannot happen, because LIST is shorter than G_MAXINT/2. */ \
-			imid = (imin + imax) / 2;\
-		} \
-	} \
-	\
-	{ unknown_val_cmd; } \
-}
-
-#define NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE(fcn_name, \
-                                                   result_type, \
-                                                   entry_cmd, \
+#define _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name,                                         \
+                                             value_type,                                       \
+                                             value_type_result,                                \
+                                             entry_cmd,                                        \
+                                             unknown_val_cmd,                                  \
+                                             get_operator,                                     \
+                                             ...)                                              \
+    value_type_result fcn_name(const char *name)                                               \
+    {                                                                                          \
+        static const struct {                                                                  \
+            const char *name;                                                                  \
+            value_type  value;                                                                 \
+        } LIST[] = {__VA_ARGS__};                                                              \
+                                                                                               \
+        if (NM_MORE_ASSERT_ONCE(5)) {                                                          \
+            int i;                                                                             \
+                                                                                               \
+            for (i = 0; i < G_N_ELEMENTS(LIST); i++) {                                         \
+                nm_assert(LIST[i].name);                                                       \
+                if (i > 0)                                                                     \
+                    nm_assert(strcmp(LIST[i - 1].name, LIST[i].name) < 0);                     \
+            }                                                                                  \
+        }                                                                                      \
+                                                                                               \
+        {                                                                                      \
+            entry_cmd;                                                                         \
+        }                                                                                      \
+                                                                                               \
+        if (G_LIKELY(name)) {                                                                  \
+            G_STATIC_ASSERT(G_N_ELEMENTS(LIST) > 1);                                           \
+            G_STATIC_ASSERT(G_N_ELEMENTS(LIST) < G_MAXINT / 2 - 10);                           \
+            int imin = 0;                                                                      \
+            int imax = (G_N_ELEMENTS(LIST) - 1);                                               \
+            int imid = (G_N_ELEMENTS(LIST) - 1) / 2;                                           \
+                                                                                               \
+            for (;;) {                                                                         \
+                const int cmp = strcmp(LIST[imid].name, name);                                 \
+                                                                                               \
+                if (G_UNLIKELY(cmp == 0))                                                      \
+                    return get_operator(LIST[imid].value);                                     \
+                                                                                               \
+                if (cmp < 0)                                                                   \
+                    imin = imid + 1;                                                           \
+                else                                                                           \
+                    imax = imid - 1;                                                           \
+                                                                                               \
+                if (G_UNLIKELY(imin > imax))                                                   \
+                    break;                                                                     \
+                                                                                               \
+                /* integer overflow cannot happen, because LIST is shorter than G_MAXINT/2. */ \
+                imid = (imin + imax) / 2;                                                      \
+            }                                                                                  \
+        }                                                                                      \
+                                                                                               \
+        {                                                                                      \
+            unknown_val_cmd;                                                                   \
+        }                                                                                      \
+    }
+
+#define NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE(fcn_name,        \
+                                                   result_type,     \
+                                                   entry_cmd,       \
                                                    unknown_val_cmd, \
-                                                   ...) \
-	_NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (fcn_name, \
-	                                      result_type, \
-	                                      const result_type *, \
-	                                      entry_cmd, \
-	                                      unknown_val_cmd, \
-	                                      &, \
-	                                      __VA_ARGS__)
-
-#define NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \
-                                            result_type, \
-                                            entry_cmd, \
+                                                   ...)             \
+    _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name,                  \
+                                         result_type,               \
+                                         const result_type *,       \
+                                         entry_cmd,                 \
+                                         unknown_val_cmd,           \
+                                             &,                     \
+                                         __VA_ARGS__)
+
+#define NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name,        \
+                                            result_type,     \
+                                            entry_cmd,       \
                                             unknown_val_cmd, \
-                                            ...) \
-	_NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (fcn_name, \
-	                                      result_type, \
-	                                      result_type, \
-	                                      entry_cmd, \
-	                                      unknown_val_cmd, \
-	                                      , \
-	                                      __VA_ARGS__)
+                                            ...)             \
+    _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name,           \
+                                         result_type,        \
+                                         result_type,        \
+                                         entry_cmd,          \
+                                         unknown_val_cmd,    \
+                                         ,                   \
+                                         __VA_ARGS__)
 
 /*****************************************************************************/
 
 static inline GTask *
-nm_g_task_new (gpointer source_object,
-               GCancellable *cancellable,
-               gpointer source_tag,
-               GAsyncReadyCallback callback,
-               gpointer callback_data)
+nm_g_task_new(gpointer            source_object,
+              GCancellable *      cancellable,
+              gpointer            source_tag,
+              GAsyncReadyCallback callback,
+              gpointer            callback_data)
 {
-	GTask *task;
+    GTask *task;
 
-	task = g_task_new (source_object, cancellable, callback, callback_data);
-	if (source_tag)
-		g_task_set_source_tag (task, source_tag);
-	return task;
+    task = g_task_new(source_object, cancellable, callback, callback_data);
+    if (source_tag)
+        g_task_set_source_tag(task, source_tag);
+    return task;
 }
 
 static inline gboolean
-nm_g_task_is_valid (gpointer task,
-                    gpointer source_object,
-                    gpointer source_tag)
+nm_g_task_is_valid(gpointer task, gpointer source_object, gpointer source_tag)
 {
-	return    g_task_is_valid (task, source_object)
-	       && g_task_get_source_tag (task) == source_tag;
+    return g_task_is_valid(task, source_object) && g_task_get_source_tag(task) == source_tag;
 }
 
-guint nm_utils_parse_debug_string (const char *string,
-                                   const GDebugKey *keys,
-                                   guint nkeys);
+guint nm_utils_parse_debug_string(const char *string, const GDebugKey *keys, guint nkeys);
 
 /*****************************************************************************/
 
 static inline gboolean
-nm_utils_strdup_reset (char **dst, const char *src)
+nm_utils_strdup_reset(char **dst, const char *src)
 {
-	nm_assert (dst);
-
-	if (nm_streq0 (*dst, src))
-		return FALSE;
-	g_free (*dst);
-	*dst = g_strdup (src);
-	return TRUE;
-}
+    char *old;
 
-void nm_indirect_g_free (gpointer arg);
+    nm_assert(dst);
 
-/*****************************************************************************/
+    if (nm_streq0(*dst, src))
+        return FALSE;
+    old  = *dst;
+    *dst = g_strdup(src);
+    g_free(old);
+    return TRUE;
+}
 
-/* nm_utils_get_next_realloc_size() is used to grow buffers exponentially, when
- * the final size is unknown. As such, it has borders for which it allocates
- * certain buffer sizes.
- *
- * The use of these defines is to get favorable allocation sequences.
- * For example, nm_str_buf_init() asks for an initial allocation size. Note that
- * it reserves the exactly requested amount, under the assumption that the
- * user may know how many bytes will be required. However, often the caller
- * doesn't know in advance, and NMStrBuf grows exponentially by calling
- * nm_utils_get_next_realloc_size().
- * Imagine you call nm_str_buf_init() with an initial buffer size 100, and you
- * add one character at a time. Then the first reallocation will increase the
- * buffer size only from 100 to 104.
- * If you however start with an initial buffer size of 104, then the next reallocation
- * via nm_utils_get_next_realloc_size() gives you 232, and so on. By using
- * these sizes, it results in one less allocation, if you anyway don't know the
- * exact size in advance. */
-#define NM_UTILS_GET_NEXT_REALLOC_SIZE_104     ((gsize) 104)
-#define NM_UTILS_GET_NEXT_REALLOC_SIZE_1000    ((gsize) 1000)
-
-gsize nm_utils_get_next_realloc_size (gboolean true_realloc, gsize requested);
+void nm_indirect_g_free(gpointer arg);
 
 /*****************************************************************************/
 
 typedef enum {
-	NMU_IFACE_ANY,
-	NMU_IFACE_KERNEL,
-	NMU_IFACE_OVS,
-	NMU_IFACE_OVS_AND_KERNEL,
+    NMU_IFACE_ANY,
+    NMU_IFACE_KERNEL,
+    NMU_IFACE_OVS,
+    NMU_IFACE_OVS_AND_KERNEL,
 } NMUtilsIfaceType;
 
-gboolean nm_utils_ifname_valid_kernel (const char *name, GError **error);
+gboolean nm_utils_ifname_valid_kernel(const char *name, GError **error);
 
-gboolean nm_utils_ifname_valid (const char* name,
-                                NMUtilsIfaceType type,
-                                GError **error);
+gboolean nm_utils_ifname_valid(const char *name, NMUtilsIfaceType type, GError **error);
 
 /*****************************************************************************/
 
 static inline GArray *
-nm_strvarray_ensure (GArray **p)
+nm_strvarray_ensure(GArray **p)
 {
-	if (!*p) {
-		*p = g_array_new (TRUE, FALSE, sizeof (char *));
-		g_array_set_clear_func (*p, nm_indirect_g_free);
-	}
-	return *p;
+    if (!*p) {
+        *p = g_array_new(TRUE, FALSE, sizeof(char *));
+        g_array_set_clear_func(*p, nm_indirect_g_free);
+    }
+    return *p;
 }
 
 static inline void
-nm_strvarray_add (GArray *array, const char *str)
+nm_strvarray_add(GArray *array, const char *str)
 {
-	char *s;
+    char *s;
 
-	s = g_strdup (str);
-	g_array_append_val (array, s);
+    s = g_strdup(str);
+    g_array_append_val(array, s);
 }
 
-static inline const char *const*
-nm_strvarray_get_strv_non_empty (GArray *arr, guint *length)
+static inline const char *const *
+nm_strvarray_get_strv_non_empty(GArray *arr, guint *length)
 {
-	if (!arr || arr->len == 0) {
-		NM_SET_OUT (length, 0);
-		return NULL;
-	}
+    if (!arr || arr->len == 0) {
+        NM_SET_OUT(length, 0);
+        return NULL;
+    }
 
-	NM_SET_OUT (length, arr->len);
-	return &g_array_index (arr, const char *, 0);
+    NM_SET_OUT(length, arr->len);
+    return &g_array_index(arr, const char *, 0);
 }
 
-static inline const char *const*
-nm_strvarray_get_strv (GArray **arr, guint *length)
+static inline const char *const *
+nm_strvarray_get_strv(GArray **arr, guint *length)
 {
-	if (!*arr) {
-		NM_SET_OUT (length, 0);
-		return (const char *const*) arr;
-	}
+    if (!*arr) {
+        NM_SET_OUT(length, 0);
+        return (const char *const *) arr;
+    }
 
-	NM_SET_OUT (length, (*arr)->len);
-	return &g_array_index (*arr, const char *, 0);
+    NM_SET_OUT(length, (*arr)->len);
+    return &g_array_index(*arr, const char *, 0);
 }
 
 static inline void
-nm_strvarray_set_strv (GArray **array, const char *const*strv)
+nm_strvarray_set_strv(GArray **array, const char *const *strv)
 {
-	gs_unref_array GArray *array_old = NULL;
+    gs_unref_array GArray *array_old = NULL;
+
+    array_old = g_steal_pointer(array);
 
-	array_old = g_steal_pointer (array);
+    if (!strv || !strv[0])
+        return;
+
+    nm_strvarray_ensure(array);
+    for (; strv[0]; strv++)
+        nm_strvarray_add(*array, strv[0]);
+}
+
+static inline gboolean
+nm_strvarray_remove_first(GArray *strv, const char *needle)
+{
+    guint i;
 
-	if (!strv || !strv[0])
-		return;
+    nm_assert(needle);
 
-	nm_strvarray_ensure (array);
-	for (; strv[0]; strv++)
-		nm_strvarray_add (*array, strv[0]);
+    if (strv) {
+        for (i = 0; i < strv->len; i++) {
+            if (nm_streq(needle, g_array_index(strv, const char *, i))) {
+                g_array_remove_index(strv, i);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
 }
 
 /*****************************************************************************/
 
-void _nm_utils_format_variant_attributes_full (GString *str,
-                                               const NMUtilsNamedValue *values,
-                                               guint num_values,
-                                               char attr_separator,
-                                               char key_value_separator);
+struct _NMVariantAttributeSpec {
+    char *              name;
+    const GVariantType *type;
+    bool                v4 : 1;
+    bool                v6 : 1;
+    bool                no_value : 1;
+    bool                consumes_rest : 1;
+    char                str_type;
+};
+
+typedef struct _NMVariantAttributeSpec NMVariantAttributeSpec;
+
+void _nm_utils_format_variant_attributes_full(GString *                            str,
+                                              const NMUtilsNamedValue *            values,
+                                              guint                                num_values,
+                                              const NMVariantAttributeSpec *const *spec,
+                                              char                                 attr_separator,
+                                              char key_value_separator);
+
+char *_nm_utils_format_variant_attributes(GHashTable *                         attributes,
+                                          const NMVariantAttributeSpec *const *spec,
+                                          char                                 attr_separator,
+                                          char                                 key_value_separator);
+
+/*****************************************************************************/
+
+gboolean nm_utils_is_localhost(const char *name);
+
+gboolean nm_utils_is_specific_hostname(const char *name);
 
-char *_nm_utils_format_variant_attributes (GHashTable *attributes,
-                                           char attr_separator,
-                                           char key_value_separator);
+char *   nm_utils_uid_to_name(uid_t uid);
+gboolean nm_utils_name_to_uid(const char *name, uid_t *out_uid);
 
 #endif /* __NM_SHARED_UTILS_H__ */