summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-12-01 16:04:02 +0100
committerThomas Haller <thaller@redhat.com>2022-12-09 09:15:53 +0100
commitcfc6e63403ae0d22d14ba8b5c9e9d934d7dcc70b (patch)
tree881e618c03e90f733d0ac3ffca4249f49a754a6b
parentafac3d810216652afa114aee91e2d87d1db1ca69 (diff)
downloadNetworkManager-cfc6e63403ae0d22d14ba8b5c9e9d934d7dcc70b.tar.gz
glib-aux: add nm_g_array_first_p() and fix nm_g_array_index_p() with NULL array
nm_g_array_first_p() is a convenient helper to get the pointer to the first index. But this one should also accept that the array is NULL, has array->data as NULL or is empty.
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.h38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h
index 206f10fb01..110d617ac5 100644
--- a/src/libnm-glib-aux/nm-shared-utils.h
+++ b/src/libnm-glib-aux/nm-shared-utils.h
@@ -1869,6 +1869,8 @@ char *nm_utils_g_slist_strlist_join(const GSList *a, const char *separator);
static inline gpointer
nm_g_array_data(const GArray *arr)
{
+ /* You may want to use nm_g_array_first_p() instead, which can assert
+ * for the expected type. */
return arr ? arr->data : NULL;
}
@@ -1890,21 +1892,25 @@ nm_g_array_unref(GArray *arr)
* - returns a pointer to the element.
* - it asserts that @idx is <= arr->len. That is, it allows
* to get a pointer after the data, of course, you are not
- * allowed to dereference in that case. */
-#define nm_g_array_index_p(arr, Type, idx) \
- ({ \
- const GArray *const _arr_55 = (arr); \
- const guint _idx_55 = (idx); \
- \
- nm_assert(_arr_55); \
- nm_assert(sizeof(Type) == g_array_get_element_size((GArray *) _arr_55)); \
- nm_assert(_idx_55 <= _arr_55->len); \
- \
- /* If arr->len is zero, arr->data might be NULL. The macro
- * allows to access at index [arr->len] (one past the data).
- * We need to take care of undefined behavior, but (NULL + 0)
- * should work mostly fine for us. */ \
- ((Type *) ((gpointer) _arr_55->data)) + (_idx_55); \
+ * allowed to dereference in that case.
+ * - in particular, unlike nm_g_array_index(), you are allowed to call this
+ * with "arr" NULL (for index zero) or with "arr->data" NULL
+ * (for index zero). In that case, NULL is returned.
+ *
+ * When accessing index zero, then this returns NULL if-and-only-if
+ * "arr" is NULL or "arr->data" is NULL. In all other cases, this
+ * returns the pointer &((Type*) arr->data)[idx]. Note that the pointer
+ * may not be followed, if "idx" is equal to "arr->len". */
+#define nm_g_array_index_p(arr, Type, idx) \
+ ({ \
+ const GArray *const _arr_55 = (arr); \
+ const guint _idx_55 = (idx); \
+ \
+ nm_assert(_arr_55 || _idx_55 == 0); \
+ nm_assert(_idx_55 <= (_arr_55 ? _arr_55->len : 0u)); \
+ nm_assert(!_arr_55 || sizeof(Type) == g_array_get_element_size((GArray *) _arr_55)); \
+ \
+ ((_arr_55 && _arr_55->data) ? &(((Type *) ((gpointer) _arr_55->data))[_idx_55]) : NULL); \
})
/* Very similar to g_array_index().
@@ -1928,6 +1934,8 @@ nm_g_array_unref(GArray *arr)
#define nm_g_array_first(arr, Type) nm_g_array_index(arr, Type, 0)
+#define nm_g_array_first_p(arr, Type) nm_g_array_index_p(arr, Type, 0)
+
/* Same as g_array_index(arr, Type, arr->len-1). */
#define nm_g_array_last(arr, Type) \
(*({ \