summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-04-06 09:47:05 +0200
committerThomas Haller <thaller@redhat.com>2017-04-12 11:24:03 +0200
commit31d0d0ef8330294d6c11fd534b0ac0be6061f5d3 (patch)
treef08abf8fd455512cae9b55a72ee1a53b00590bdb
parentc9c029181e6f2f9a02a8a7ebfcda1a36764546b5 (diff)
downloadNetworkManager-31d0d0ef8330294d6c11fd534b0ac0be6061f5d3.tar.gz
shared: add NM_PTRARRAY_LEN() utility macro
I used to use g_strv_length ((char **) p) instead, but that feels ugly because it g_strv_length() is not designed to operate on arbitrary pointer arrays.
-rw-r--r--libnm-core/tests/test-general.c76
-rw-r--r--shared/nm-utils/nm-macros-internal.h17
2 files changed, 93 insertions, 0 deletions
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 0f65e8f6ae..0d6cb5322d 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -4655,6 +4655,81 @@ test_nm_utils_strstrdictkey (void)
/*****************************************************************************/
+static guint
+_g_strv_length (gconstpointer arr)
+{
+ return arr ? g_strv_length ((char **) arr) : 0;
+}
+
+static void
+test_nm_ptrarray_len (void)
+{
+#define _PTRARRAY_cmp(len, arr) \
+ G_STMT_START { \
+ g_assert_cmpint (len, ==, NM_PTRARRAY_LEN (arr)); \
+ g_assert_cmpint (len, ==, _g_strv_length (arr)); \
+ } G_STMT_END
+#define _PTRARRAY_LEN0(T) \
+ G_STMT_START { \
+ T **vnull = NULL; \
+ T *const*vnull1 = NULL; \
+ T *const*const vnull2 = NULL; \
+ T *v0[] = { NULL }; \
+ T *const*v01 = v0; \
+ T *const*const v02 = v0; \
+ T **const v03 = v0; \
+ \
+ _PTRARRAY_cmp (0, vnull); \
+ _PTRARRAY_cmp (0, vnull1); \
+ _PTRARRAY_cmp (0, vnull2); \
+ _PTRARRAY_cmp (0, v0); \
+ _PTRARRAY_cmp (0, v01); \
+ _PTRARRAY_cmp (0, v02); \
+ _PTRARRAY_cmp (0, v03); \
+ } G_STMT_END
+
+ _PTRARRAY_LEN0 (char);
+ _PTRARRAY_LEN0 (const char);
+ _PTRARRAY_LEN0 (int);
+ _PTRARRAY_LEN0 (const int);
+ _PTRARRAY_LEN0 (void *);
+ _PTRARRAY_LEN0 (void);
+ _PTRARRAY_LEN0 (const void);
+
+#define _PTRARRAY_LENn(T) \
+ G_STMT_START { \
+ T x[5] = { 0 }; \
+ \
+ T *v1[] = { &x[0], NULL }; \
+ T *const*v11 = v1; \
+ T *const*const v12 = v1; \
+ T **const v13 = v1; \
+ \
+ T *v2[] = { &x[0], &x[1], NULL }; \
+ T *const*v21 = v2; \
+ T *const*const v22 = v2; \
+ T **const v23 = v2; \
+ \
+ _PTRARRAY_cmp (1, v1); \
+ _PTRARRAY_cmp (1, v11); \
+ _PTRARRAY_cmp (1, v12); \
+ _PTRARRAY_cmp (1, v13); \
+ \
+ _PTRARRAY_cmp (2, v2); \
+ _PTRARRAY_cmp (2, v21); \
+ _PTRARRAY_cmp (2, v22); \
+ _PTRARRAY_cmp (2, v23); \
+ } G_STMT_END
+
+ _PTRARRAY_LENn (char);
+ _PTRARRAY_LENn (const char);
+ _PTRARRAY_LENn (int);
+ _PTRARRAY_LENn (const int);
+ _PTRARRAY_LENn (void *);
+}
+
+/*****************************************************************************/
+
static void
test_nm_utils_dns_option_validate_do (char *option, gboolean ipv6, const NMUtilsDNSOptionDesc *descs,
gboolean exp_result, char *exp_name, gboolean exp_value)
@@ -5716,6 +5791,7 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array);
g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
+ g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len);
g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index f362968f58..eaf8b9e54d 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -209,6 +209,23 @@ NM_G_ERROR_MSG (GError *error)
/* macro to return strlen() of a compile time string. */
#define NM_STRLEN(str) ( sizeof ("" str) - 1 )
+/* returns the length of a NULL terminated array of pointers,
+ * like g_strv_length() does. The difference is:
+ * - it operats on arrays of pointers (of any kind, requiring no cast).
+ * - it accepts NULL to return zero. */
+#define NM_PTRARRAY_LEN(array) \
+ ({ \
+ typeof (*(array)) *const _array = (array); \
+ gsize _n = 0; \
+ \
+ if (_array) { \
+ _nm_unused typeof (*(_array[0])) *_array_check = _array[0]; \
+ while (_array[_n]) \
+ _n++; \
+ } \
+ _n; \
+ })
+
/* Note: @value is only evaluated when *out_val is present.
* Thus,
* NM_SET_OUT (out_str, g_strdup ("hallo"));