[network-manager-openvpn/th/helper-parse-route-bgo788137: 1/2] shared: re-import shared files



commit 80afc0378b0b4c420d5f72e3a585b83524c4b0d2
Author: Thomas Haller <thaller redhat com>
Date:   Mon Sep 25 16:38:24 2017 +0200

    shared: re-import shared files

 shared/nm-utils/nm-glib.h            |   29 ++++
 shared/nm-utils/nm-macros-internal.h |  144 ++++++++++++++---
 shared/nm-utils/nm-shared-utils.c    |  284 ++++++++++++++++++++++++++++++++++
 shared/nm-utils/nm-shared-utils.h    |  186 ++++++++++++++++++++++
 shared/nm-utils/nm-test-utils.h      |   91 ++++++++---
 5 files changed, 689 insertions(+), 45 deletions(-)
---
diff --git a/shared/nm-utils/nm-glib.h b/shared/nm-utils/nm-glib.h
index dd18756..4ef538e 100644
--- a/shared/nm-utils/nm-glib.h
+++ b/shared/nm-utils/nm-glib.h
@@ -452,4 +452,33 @@ _nm_g_variant_new_take_string (gchar *string)
 }
 #define g_variant_new_take_string _nm_g_variant_new_take_string
 
+#if !GLIB_CHECK_VERSION(2, 38, 0)
+_nm_printf (1, 2)
+static inline GVariant *
+_nm_g_variant_new_printf (const char *format_string, ...)
+{
+       char *string;
+       va_list ap;
+
+       g_return_val_if_fail (format_string, NULL);
+
+       va_start (ap, format_string);
+       string = g_strdup_vprintf (format_string, ap);
+       va_end (ap);
+
+       return g_variant_new_take_string (string);
+}
+#define g_variant_new_printf(...) _nm_g_variant_new_printf(__VA_ARGS__)
+#else
+#define g_variant_new_printf(...) \
+       ({ \
+               GVariant *_v; \
+               \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               _v = g_variant_new_printf (__VA_ARGS__); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+               _v; \
+       })
+#endif
+
 #endif  /* __NM_GLIB_H__ */
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index cde257e..b946a27 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -26,16 +26,16 @@
 #include <stdlib.h>
 #include <errno.h>
 
-#include "nm-glib.h"
-
-/*****************************************************************************/
-
 #define _nm_packed __attribute__ ((packed))
 #define _nm_unused __attribute__ ((unused))
 #define _nm_pure   __attribute__ ((pure))
 #define _nm_const  __attribute__ ((const))
 #define _nm_printf(a,b) __attribute__ ((__format__ (__printf__, a, b)))
 
+#include "nm-glib.h"
+
+/*****************************************************************************/
+
 #define nm_offsetofend(t,m) (G_STRUCT_OFFSET (t,m) + sizeof (((t *) NULL)->m))
 
 #define nm_auto(fcn) __attribute__ ((cleanup(fcn)))
@@ -56,10 +56,10 @@ _nm_auto_unset_gvalue_impl (GValue *v)
 #define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl)
 
 static inline void
-_nm_auto_unref_gtypeclass (GTypeClass **v)
+_nm_auto_unref_gtypeclass (gpointer v)
 {
-       if (v && *v)
-               g_type_class_unref (*v);
+       if (v && *((gpointer *) v))
+               g_type_class_unref (*((gpointer *) v));
 }
 #define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
 
@@ -242,6 +242,35 @@ NM_G_ERROR_MSG (GError *error)
 
 /*****************************************************************************/
 
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 9 ))) || (defined 
(__clang__))
+#define _NM_CC_SUPPORT_GENERIC 1
+#else
+#define _NM_CC_SUPPORT_GENERIC 0
+#endif
+
+#if _NM_CC_SUPPORT_GENERIC
+#define _NM_CONSTCAST(type, obj) \
+       (_Generic ((obj), \
+                  void *           : ((type *) (obj)), \
+                  void *const      : ((type *) (obj)), \
+                  const void *     : ((const type *) (obj)), \
+                  const void *const: ((const type *) (obj)), \
+                  const type *     : (obj), \
+                  const type *const: (obj), \
+                  type *           : (obj), \
+                  type *const      : (obj)))
+#else
+/* _NM_CONSTCAST() is there to preserve constness of a pointer.
+ * It uses C11's _Generic(). If that is not supported, we fall back
+ * to casting away constness. So, with _Generic, we get some additional
+ * static type checking by preserving constness, without, we cast it
+ * to a non-const pointer. */
+#define _NM_CONSTCAST(type, obj) \
+       ((type *) (obj))
+#endif
+
+/*****************************************************************************/
+
 #define _NM_IN_SET_EVAL_1( op, _x, y)           (_x == (y))
 #define _NM_IN_SET_EVAL_2( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_1  (op, _x, __VA_ARGS__)
 #define _NM_IN_SET_EVAL_3( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_2  (op, _x, __VA_ARGS__)
@@ -381,6 +410,21 @@ _NM_IN_STRSET_streq (const char *x, const char *s)
 
 /*****************************************************************************/
 
+static inline guint
+NM_HASH_COMBINE (guint h, guint val)
+{
+       /* see g_str_hash() for reasons */
+       return (h << 5) + h + val;
+}
+
+static inline guint
+NM_HASH_COMBINE_UINT64 (guint h, guint64 val)
+{
+       return NM_HASH_COMBINE (h, (((guint) val) & 0xFFFFFFFFu) + ((guint) (val >> 32)));
+}
+
+/*****************************************************************************/
+
 /* NM_CACHED_QUARK() returns the GQuark for @string, but caches
  * it in a static variable to speed up future lookups.
  *
@@ -420,6 +464,16 @@ fcn (void) \
 
 /*****************************************************************************/
 
+static inline GString *
+nm_gstring_prepare (GString **l)
+{
+       if (*l)
+               g_string_set_size (*l, 0);
+       else
+               *l = g_string_sized_new (30);
+       return *l;
+}
+
 static inline const char *
 nm_str_not_empty (const char *str)
 {
@@ -512,7 +566,7 @@ _notify (obj_type *obj, _PropertyEnums prop) \
 /* these are implemented as a macro, because they accept self
  * as both (type*) and (const type*), and return a const
  * private pointer accordingly. */
-#define __NM_GET_PRIVATE(self, type, is_check, result_cmd) \
+#define __NM_GET_PRIVATE(self, type, is_check, addrop) \
        ({ \
                /* preserve the const-ness of self. Unfortunately, that
                 * way, @self cannot be a void pointer */ \
@@ -522,11 +576,11 @@ _notify (obj_type *obj, _PropertyEnums prop) \
                _nm_unused const type *const _self2 = (_self); \
                \
                nm_assert (is_check (_self)); \
-               ( result_cmd ); \
+               ( addrop ( _NM_CONSTCAST (type, _self)->_priv) ); \
        })
 
-#define _NM_GET_PRIVATE(self, type, is_check)     __NM_GET_PRIVATE(self, type, is_check, &_self->_priv)
-#define _NM_GET_PRIVATE_PTR(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check,  _self->_priv)
+#define _NM_GET_PRIVATE(self, type, is_check)     __NM_GET_PRIVATE(self, type, is_check, &)
+#define _NM_GET_PRIVATE_PTR(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check,  )
 
 #define __NM_GET_PRIVATE_VOID(self, type, is_check, result_cmd) \
        ({ \
@@ -565,6 +619,36 @@ nm_g_object_unref (gpointer obj)
                g_object_unref (obj);
 }
 
+/* Assigns GObject @obj to destination @pdst, and takes an additional ref.
+ * The previous value of @pdst is unrefed.
+ *
+ * It makes sure to first increase the ref-count of @obj, and handles %NULL
+ * @obj correctly.
+ * */
+#define nm_g_object_ref_set(pp, obj) \
+       ({ \
+               typeof (*(pp)) *const _pp = (pp); \
+               typeof (**_pp) *const _obj = (obj); \
+               typeof (**_pp) *_p; \
+               gboolean _changed = FALSE; \
+               \
+               if (   _pp \
+                   && ((_p = *_pp) != _obj)) { \
+                       if (_obj) { \
+                               nm_assert (G_IS_OBJECT (_obj)); \
+                                g_object_ref (_obj); \
+                       } \
+                       if (_p) { \
+                               nm_assert (G_IS_OBJECT (_p)); \
+                               *_pp = NULL; \
+                               g_object_unref (_p); \
+                       } \
+                       *_pp = _obj; \
+                       _changed = TRUE; \
+               } \
+               _changed; \
+       })
+
 /* basically, replaces
  *   g_clear_pointer (&location, g_free)
  * with
@@ -577,13 +661,32 @@ nm_g_object_unref (gpointer obj)
 #define nm_clear_g_free(pp) \
        ({  \
                typeof (*(pp)) *_pp = (pp); \
-               typeof (**_pp) *_p = *_pp; \
+               typeof (**_pp) *_p; \
+               gboolean _changed = FALSE; \
                \
-               if (_p) { \
+               if (  _pp \
+                   && (_p = *_pp)) { \
                        *_pp = NULL; \
                        g_free (_p); \
+                       _changed = TRUE; \
+               } \
+               _changed; \
+       })
+
+#define nm_clear_g_object(pp) \
+       ({ \
+               typeof (*(pp)) *_pp = (pp); \
+               typeof (**_pp) *_p; \
+               gboolean _changed = FALSE; \
+               \
+               if (   _pp \
+                   && (_p = *_pp)) { \
+                       nm_assert (G_IS_OBJECT (_p)); \
+                       *_pp = NULL; \
+                       g_object_unref (_p); \
+                       _changed = TRUE; \
                } \
-               !!_p; \
+               _changed; \
        })
 
 static inline gboolean
@@ -634,18 +737,13 @@ nm_clear_g_cancellable (GCancellable **cancellable)
 /*****************************************************************************/
 
 /* Determine whether @x is a power of two (@x being an integer type).
- * For the special cases @x equals zero or one, it also returns true.
- * In case @x being a signed type, for negative @x always return FALSE. */
+ * Basically, this returns TRUE, if @x has exactly one bit set.
+ * For negative values and zero, this always returns FALSE. */
 #define nm_utils_is_power_of_two(x) ({ \
                typeof(x) __x = (x); \
                \
-               /* Check if the value is negative. In that case, return FALSE.
-                * The first expression is a compile time constant, depending on whether
-                * the type is signed. The second expression is a clumsy way for (__x >= 0),
-                * which otherwise causes a compiler warning for unsigned types. */ \
-                   (    (((typeof(__x)) -1) > ((typeof(__x)) 0)) \
-                     || (__x > 0 || __x == 0) ) \
-                && ((__x & (__x - 1)) == 0); \
+               (    (__x > ((typeof(__x)) 0)) \
+                && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \
        })
 
 /*****************************************************************************/
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
index 9a87536..0810d7b 100644
--- a/shared/nm-utils/nm-shared-utils.c
+++ b/shared/nm-utils/nm-shared-utils.c
@@ -24,6 +24,7 @@
 #include "nm-shared-utils.h"
 
 #include <errno.h>
+#include <arpa/inet.h>
 
 /*****************************************************************************/
 
@@ -31,6 +32,10 @@ const void *const _NM_PTRARRAY_EMPTY[1] = { NULL };
 
 /*****************************************************************************/
 
+const NMIPAddr nm_ip_addr_zero = { 0 };
+
+/*****************************************************************************/
+
 void
 nm_utils_strbuf_append_c (char **buf, gsize *len, char c)
 {
@@ -110,6 +115,163 @@ nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
 
 /*****************************************************************************/
 
+/**
+ * _nm_utils_ip4_prefix_to_netmask:
+ * @prefix: a CIDR prefix
+ *
+ * Returns: the netmask represented by the prefix, in network byte order
+ **/
+guint32
+_nm_utils_ip4_prefix_to_netmask (guint32 prefix)
+{
+       return prefix < 32 ? ~htonl(0xFFFFFFFF >> prefix) : 0xFFFFFFFF;
+}
+
+/**
+ * _nm_utils_ip4_get_default_prefix:
+ * @ip: an IPv4 address (in network byte order)
+ *
+ * When the Internet was originally set up, various ranges of IP addresses were
+ * segmented into three network classes: A, B, and C.  This function will return
+ * a prefix that is associated with the IP address specified defining where it
+ * falls in the predefined classes.
+ *
+ * Returns: the default class prefix for the given IP
+ **/
+/* The function is originally from ipcalc.c of Red Hat's initscripts. */
+guint32
+_nm_utils_ip4_get_default_prefix (guint32 ip)
+{
+       if (((ntohl (ip) & 0xFF000000) >> 24) <= 127)
+               return 8;  /* Class A - 255.0.0.0 */
+       else if (((ntohl (ip) & 0xFF000000) >> 24) <= 191)
+               return 16;  /* Class B - 255.255.0.0 */
+
+       return 24;  /* Class C - 255.255.255.0 */
+}
+
+gboolean
+nm_utils_ip_is_site_local (int addr_family,
+                           const void *address)
+{
+       in_addr_t addr4;
+
+       switch (addr_family) {
+       case AF_INET:
+               /* RFC1918 private addresses
+                * 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
+               addr4 = ntohl (*((const in_addr_t *) address));
+               return    (addr4 & 0xff000000) == 0x0a000000
+                      || (addr4 & 0xfff00000) == 0xac100000
+                      || (addr4 & 0xffff0000) == 0xc0a80000;
+       case AF_INET6:
+               return IN6_IS_ADDR_SITELOCAL (address);
+       default:
+               g_return_val_if_reached (FALSE);
+       }
+}
+
+/*****************************************************************************/
+
+gboolean
+nm_utils_parse_inaddr_bin  (const char *text,
+                            int family,
+                            gpointer out_addr)
+{
+       NMIPAddr addrbin;
+
+       g_return_val_if_fail (text, FALSE);
+
+       if (family == AF_UNSPEC)
+               family = strchr (text, ':') ? AF_INET6 : AF_INET;
+       else
+               g_return_val_if_fail (NM_IN_SET (family, AF_INET, AF_INET6), FALSE);
+
+       if (inet_pton (family, text, out_addr ?: &addrbin) != 1)
+               return FALSE;
+       return TRUE;
+}
+
+gboolean
+nm_utils_parse_inaddr (const char *text,
+                       int family,
+                       char **out_addr)
+{
+       NMIPAddr addrbin;
+       char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
+
+       if (!nm_utils_parse_inaddr_bin (text, family, &addrbin))
+               return FALSE;
+       NM_SET_OUT (out_addr, g_strdup (inet_ntop (family, &addrbin, addrstr_buf, sizeof (addrstr_buf))));
+       return TRUE;
+}
+
+gboolean
+nm_utils_parse_inaddr_prefix_bin (const char *text,
+                                  int family,
+                                  gpointer out_addr,
+                                  int *out_prefix)
+{
+       gs_free char *addrstr_free = NULL;
+       int prefix = -1;
+       const char *slash;
+       const char *addrstr;
+       NMIPAddr addrbin;
+       int addr_len;
+
+       g_return_val_if_fail (text, FALSE);
+
+       if (family == AF_UNSPEC)
+               family = strchr (text, ':') ? AF_INET6 : AF_INET;
+
+       if (family == AF_INET)
+               addr_len = sizeof (in_addr_t);
+       else if (family == AF_INET6)
+               addr_len = sizeof (struct in6_addr);
+       else
+               g_return_val_if_reached (FALSE);
+
+       slash = strchr (text, '/');
+       if (slash)
+               addrstr = addrstr_free = g_strndup (text, slash - text);
+       else
+               addrstr = text;
+
+       if (inet_pton (family, addrstr, &addrbin) != 1)
+               return FALSE;
+
+       if (slash) {
+               prefix = _nm_utils_ascii_str_to_int64 (slash + 1, 10,
+                                                      0,
+                                                      family == AF_INET ? 32 : 128,
+                                                      -1);
+               if (prefix == -1)
+                       return FALSE;
+       }
+
+       if (out_addr)
+               memcpy (out_addr, &addrbin, addr_len);
+       NM_SET_OUT (out_prefix, prefix);
+       return TRUE;
+}
+
+gboolean
+nm_utils_parse_inaddr_prefix (const char *text,
+                              int family,
+                              char **out_addr,
+                              int *out_prefix)
+{
+       NMIPAddr addrbin;
+       char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
+
+       if (!nm_utils_parse_inaddr_prefix_bin (text, family, &addrbin, out_prefix))
+               return FALSE;
+       NM_SET_OUT (out_addr, g_strdup (inet_ntop (family, &addrbin, addrstr_buf, sizeof (addrstr_buf))));
+       return TRUE;
+}
+
+/*****************************************************************************/
+
 /* _nm_utils_ascii_str_to_int64:
  *
  * A wrapper for g_ascii_strtoll, that checks whether the whole string
@@ -163,6 +325,118 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
 /*****************************************************************************/
 
 /**
+ * nm_utils_strsplit_set:
+ * @str: the string to split.
+ * @delimiters: the set of delimiters. If %NULL, defaults to " \t\n",
+ *   like bash's $IFS.
+ *
+ * This is a replacement for g_strsplit_set() which avoids copying
+ * each word once (the entire strv array), but instead copies it once
+ * and all words point into that internal copy.
+ *
+ * Another difference from g_strsplit_set() is that this never returns
+ * empty words. Multiple delimiters are combined and treated as one.
+ *
+ * Returns: %NULL if @str is %NULL or contains only delimiters.
+ *   Otherwise, a %NULL terminated strv array containing non-empty
+ *   words, split at the delimiter characters (delimiter characters
+ *   are removed).
+ *   The strings to which the result strv array points to are allocated
+ *   after the returned result itself. Don't free the strings themself,
+ *   but free everything with g_free().
+ */
+const char **
+nm_utils_strsplit_set (const char *str, const char *delimiters)
+{
+       const char **ptr, **ptr0;
+       gsize alloc_size, plen, i;
+       gsize str_len;
+       char *s0;
+       char *s;
+       guint8 delimiters_table[256];
+
+       if (!str)
+               return NULL;
+
+       /* initialize lookup table for delimiter */
+       if (!delimiters)
+               delimiters = " \t\n";
+       memset (delimiters_table, 0, sizeof (delimiters_table));
+       for (i = 0; delimiters[i]; i++)
+               delimiters_table[(guint8) delimiters[i]] = 1;
+
+#define _is_delimiter(ch, delimiters_table) \
+       ((delimiters_table)[(guint8) (ch)] != 0)
+
+       /* skip initial delimiters, and return of the remaining string is
+        * empty. */
+       while (_is_delimiter (str[0], delimiters_table))
+               str++;
+       if (!str[0])
+               return NULL;
+
+       str_len = strlen (str) + 1;
+       alloc_size = 8;
+
+       /* we allocate the buffer larger, so to copy @str at the
+        * end of it as @s0. */
+       ptr0 = g_malloc ((sizeof (const char *) * (alloc_size + 1)) + str_len);
+       s0 = (char *) &ptr0[alloc_size + 1];
+       memcpy (s0, str, str_len);
+
+       plen = 0;
+       s = s0;
+       ptr = ptr0;
+
+       while (TRUE) {
+               if (plen >= alloc_size) {
+                       const char **ptr_old = ptr;
+
+                       /* reallocate the buffer. Note that for now the string
+                        * continues to be in ptr0/s0. We fix that at the end. */
+                       alloc_size += 2;
+                       ptr = g_malloc ((sizeof (const char *) * (alloc_size + 1)) + str_len);
+                       memcpy (ptr, ptr_old, sizeof (const char *) * plen);
+                       if (ptr_old != ptr0)
+                               g_free (ptr_old);
+               }
+
+               ptr[plen++] = s;
+
+               nm_assert (s[0] && !_is_delimiter (s[0], delimiters_table));
+
+               while (TRUE) {
+                       s++;
+                       if (_is_delimiter (s[0], delimiters_table))
+                               break;
+                       if (s[0] == '\0')
+                               goto done;
+               }
+
+               s[0] = '\0';
+               s++;
+               while (_is_delimiter (s[0], delimiters_table))
+                       s++;
+               if (s[0] == '\0')
+                       break;
+       }
+done:
+       ptr[plen] = NULL;
+
+       if (ptr != ptr0) {
+               /* we reallocated the buffer. We must copy over the
+                * string @s0 and adjust the pointers. */
+               s = (char *) &ptr[alloc_size + 1];
+               memcpy (s, s0, str_len);
+               for (i = 0; i < plen; i++)
+                       ptr[i] = &s[ptr[i] - s0];
+               g_free (ptr0);
+       }
+
+       return ptr;
+}
+
+/**
  * nm_utils_strv_find_first:
  * @list: the strv list to search
  * @len: the length of the list, or a negative value if @list is %NULL terminated.
@@ -396,6 +670,16 @@ nm_g_object_set_property (GObject *object,
        return TRUE;
 }
 
+GParamSpec *
+nm_g_object_class_find_property_from_gtype (GType gtype,
+                                            const char *property_name)
+{
+       nm_auto_unref_gtypeclass GObjectClass *gclass = NULL;
+
+       gclass = g_type_class_ref (gtype);
+       return g_object_class_find_property (gclass, property_name);
+}
+
 /*****************************************************************************/
 
 static void
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 438a7a9..4a93016 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -22,6 +22,112 @@
 #ifndef __NM_SHARED_UTILS_H__
 #define __NM_SHARED_UTILS_H__
 
+#include <netinet/in.h>
+
+/*****************************************************************************/
+
+typedef struct {
+       union {
+               guint8 addr_ptr[1];
+               in_addr_t addr4;
+               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*/];
+       };
+} NMIPAddr;
+
+extern const NMIPAddr nm_ip_addr_zero;
+
+/*****************************************************************************/
+
+#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_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
+
+#define NM_CMP_DIRECT_MEMCMP(a, b, size) \
+    NM_CMP_RETURN (memcmp ((a), (b), (size)))
+
+#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 (g_strcmp0 (_a, _b)); \
+        } \
+    } G_STMT_END
+
+#define NM_CMP_FIELD_STR0(a, b, field) \
+    NM_CMP_RETURN (g_strcmp0 (((a)->field), ((b)->field)))
+
+#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
+    NM_CMP_RETURN (memcmp (&((a)->field), &((b)->field), \
+                           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
+
 /*****************************************************************************/
 
 extern const void *const _NM_PTRARRAY_EMPTY[1];
@@ -47,6 +153,8 @@ void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
 
 /*****************************************************************************/
 
+const char **nm_utils_strsplit_set (const char *str, const char *delimiters);
+
 gssize nm_utils_strv_find_first (char **list, gssize len, const char *needle);
 
 char **_nm_utils_strv_cleanup (char **strv,
@@ -56,6 +164,32 @@ char **_nm_utils_strv_cleanup (char **strv,
 
 /*****************************************************************************/
 
+guint32 _nm_utils_ip4_prefix_to_netmask (guint32 prefix);
+guint32 _nm_utils_ip4_get_default_prefix (guint32 ip);
+
+gboolean nm_utils_ip_is_site_local (int addr_family,
+                                    const void *address);
+
+/*****************************************************************************/
+
+gboolean nm_utils_parse_inaddr_bin  (const char *text,
+                                     int family,
+                                     gpointer out_addr);
+
+gboolean nm_utils_parse_inaddr (const char *text,
+                                int family,
+                                char **out_addr);
+
+gboolean nm_utils_parse_inaddr_prefix_bin (const char *text,
+                                           int family,
+                                           gpointer out_addr,
+                                           int *out_prefix);
+
+gboolean nm_utils_parse_inaddr_prefix (const char *text,
+                                       int family,
+                                       char **out_addr,
+                                       int *out_prefix);
+
 gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
 
 gint _nm_utils_ascii_str_to_bool (const char *str,
@@ -63,6 +197,55 @@ gint _nm_utils_ascii_str_to_bool (const char *str,
 
 /*****************************************************************************/
 
+#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 (12)
+_nm_g_slice_free_fcn_define (16)
+
+#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. */ \
+               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 12: _fcn = _nm_g_slice_free_fcn_12;  break; \
+               case 16: _fcn = _nm_g_slice_free_fcn_16; break; \
+               default: g_assert_not_reached (); _fcn = NULL; break; \
+               } \
+               _fcn; \
+       })
+
+/**
+ * nm_g_slice_free_fcn:
+ * @type: type argument for sizeof() operator that you would
+ *   pass to g_slice_new().
+ *
+ * Returns: a function pointer with GDestroyNotify signature
+ *   for g_slice_free(type,*).
+ *
+ * Only certain types are implemented. You'll get an assertion
+ * using the wrong 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))
+
+/*****************************************************************************/
+
 /**
  * NMUtilsError:
  * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
@@ -95,6 +278,9 @@ gboolean nm_g_object_set_property (GObject *object,
                                    const GValue *value,
                                    GError **error);
 
+GParamSpec *nm_g_object_class_find_property_from_gtype (GType gtype,
+                                                        const char *property_name);
+
 /*****************************************************************************/
 
 typedef enum {
diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h
index 0dfdfce..f7a87aa 100644
--- a/shared/nm-utils/nm-test-utils.h
+++ b/shared/nm-utils/nm-test-utils.h
@@ -41,7 +41,7 @@
  * NMTST_SEED_RAND environment variable:
  *   Tests that use random numbers from nmtst_get_rand() get seeded randomly at each start.
  *   You can specify the seed by setting NMTST_SEED_RAND. Also, tests will print the seed
- *   to stdout, so that you know the choosen seed.
+ *   to stdout, so that you know the chosen seed.
  *
  *
  * NMTST_DEBUG environment variable:
@@ -82,7 +82,8 @@
  *   Whether long-running tests are enabled is determined as follows (highest priority first):
  *     - specifying the value in NMTST_DEBUG has highest priority
  *     - respect g_test_quick(), if the command line contains '-mslow', '-mquick', '-mthorough'.
- *     - use compile time default
+ *     - use compile time default (CFLAGS=-DNMTST_TEST_QUICK=TRUE)
+ *     - enable slow tests by default
  *
  * "p=PATH"|"s=PATH": passes the path to g_test_init() as "-p" and "-s", respectively.
  *   Unfortunately, these options conflict with "--tap" which our makefile passes to the
@@ -137,12 +138,13 @@
 #define NMTST_WAIT(max_wait_ms, wait) \
        ({ \
                gboolean _not_expired = TRUE; \
-               gint64 _nmtst_end, _nmtst_max_wait_us = (max_wait_ms) * 1000L; \
+               const gint64 nmtst_wait_start_us = g_get_monotonic_time (); \
+               const gint64 nmtst_wait_duration_us = (max_wait_ms) * 1000L; \
+               const gint64 nmtst_wait_end_us = nmtst_wait_start_us + nmtst_wait_duration_us; \
                \
-               _nmtst_end = g_get_monotonic_time () + _nmtst_max_wait_us; \
                while (TRUE) { \
                        { wait }; \
-                       if (g_get_monotonic_time () > _nmtst_end) { \
+                       if (g_get_monotonic_time () > nmtst_wait_end_us) { \
                                _not_expired = FALSE; \
                                break; \
                        } \
@@ -281,6 +283,15 @@ nmtst_free (void)
 }
 
 static inline void
+_nmtst_log_handler (const gchar   *log_domain,
+                    GLogLevelFlags log_level,
+                    const gchar   *message,
+                    gpointer       user_data)
+{
+       g_print ("%s\n", message);
+}
+
+static inline void
 __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_level, const char 
*log_domains, gboolean *out_set_logging)
 {
        const char *nmtst_debug;
@@ -589,6 +600,11 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
                g_assert_no_error (error);
        }
 #endif
+
+       g_log_set_handler (G_LOG_DOMAIN,
+                          G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
+                          _nmtst_log_handler,
+                          NULL);
 }
 
 #ifndef _NMTST_INSIDE_CORE
@@ -647,13 +663,18 @@ nmtst_test_quick (void)
 
 typedef struct _NmtstTestData NmtstTestData;
 
-typedef void (*NmtstTestDataRelease) (const NmtstTestData *test_data);
+typedef void (*NmtstTestHandler) (const NmtstTestData *test_data);
 
 struct _NmtstTestData {
-       const char *testpath;
-       NmtstTestDataRelease fcn_release;
+       union {
+               const char *testpath;
+               char *_testpath;
+       };
        gsize n_args;
-       gpointer args[1];
+       gpointer *args;
+       NmtstTestHandler _func_setup;
+       GTestDataFunc _func_test;
+       NmtstTestHandler _func_teardown;
 };
 
 static inline void
@@ -670,8 +691,8 @@ _nmtst_test_data_unpack (const NmtstTestData *test_data, gsize n_args, ...)
        for (i = 0; i < n_args; i++) {
                p = va_arg (ap, gpointer *);
 
-               g_assert (p);
-               *p = test_data->args[i];
+               if (p)
+                       *p = test_data->args[i];
        }
        va_end (ap);
 }
@@ -684,25 +705,42 @@ _nmtst_test_data_free (gpointer data)
 
        g_assert (test_data);
 
-       if (test_data->fcn_release)
-               test_data->fcn_release (test_data);
-
-       g_free ((gpointer) test_data->testpath);
+       g_free (test_data->_testpath);
        g_free (test_data);
 }
 
 static inline void
-_nmtst_add_test_func_full (const char *testpath, GTestDataFunc test_func, NmtstTestDataRelease fcn_release, 
gsize n_args, ...)
+_nmtst_test_run (gconstpointer data)
+{
+       const NmtstTestData *test_data = data;
+
+       if (test_data->_func_setup)
+               test_data->_func_setup (test_data);
+
+       test_data->_func_test (test_data);
+
+       if (test_data->_func_teardown)
+               test_data->_func_teardown (test_data);
+}
+
+static inline void
+_nmtst_add_test_func_full (const char *testpath, GTestDataFunc func_test, NmtstTestHandler func_setup, 
NmtstTestHandler func_teardown, gsize n_args, ...)
 {
        gsize i;
        NmtstTestData *data;
        va_list ap;
 
-       data = g_malloc (G_STRUCT_OFFSET (NmtstTestData, args) + sizeof (gpointer) * (n_args + 1));
+       g_assert (testpath && testpath[0]);
+       g_assert (func_test);
+
+       data = g_malloc0 (sizeof (NmtstTestData) + (sizeof (gpointer) * (n_args + 1)));
 
-       data->testpath = g_strdup (testpath);
-       data->fcn_release = fcn_release;
+       data->_testpath = g_strdup (testpath);
+       data->_func_test = func_test;
+       data->_func_setup = func_setup;
+       data->_func_teardown = func_teardown;
        data->n_args = n_args;
+       data->args = (gpointer) &data[1];
        va_start (ap, n_args);
        for (i = 0; i < n_args; i++)
                data->args[i] = va_arg (ap, gpointer);
@@ -711,11 +749,11 @@ _nmtst_add_test_func_full (const char *testpath, GTestDataFunc test_func, NmtstT
 
        g_test_add_data_func_full (testpath,
                                   data,
-                                  test_func,
+                                  _nmtst_test_run,
                                   _nmtst_test_data_free);
 }
-#define nmtst_add_test_func_full(testpath, test_func, fcn_release, ...) _nmtst_add_test_func_full(testpath, 
test_func, fcn_release, NM_NARG (__VA_ARGS__), ##__VA_ARGS__)
-#define nmtst_add_test_func(testpath, test_func, ...) nmtst_add_test_func_full(testpath, test_func, NULL, 
##__VA_ARGS__)
+#define nmtst_add_test_func_full(testpath, func_test, func_setup, func_teardown, ...) 
_nmtst_add_test_func_full(testpath, func_test, func_setup, func_teardown, NM_NARG (__VA_ARGS__), 
##__VA_ARGS__)
+#define nmtst_add_test_func(testpath, func_test, ...) nmtst_add_test_func_full(testpath, func_test, NULL, 
NULL, ##__VA_ARGS__)
 
 /*****************************************************************************/
 
@@ -1183,6 +1221,15 @@ nmtst_file_get_contents (const char *filename)
        return contents;
 }
 
+#define nmtst_file_set_contents(filename, content) \
+       G_STMT_START { \
+               GError *_error = NULL; \
+               gboolean _success; \
+               \
+               _success = g_file_set_contents ((filename), (content), -1, &_error); \
+               nmtst_assert_success (_success, _error); \
+       } G_STMT_END
+
 /*****************************************************************************/
 
 static inline void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]