]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add array_idx_elem()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 4 May 2021 13:40:09 +0000 (16:40 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 7 May 2021 10:09:35 +0000 (10:09 +0000)
This returns array_idx()'s value dereferenced, so it only works for
arrays of pointers.

Note that using *array_idx() does the same, but it won't compile if the
compiler doesn't have typeof() support.

src/lib/array.h
src/lib/test-array.c

index e4e5cede2b3944ace54b0392c09a3eb36fe41b1a..38f8bec0cd9c482afab32ed37ab639fe573f8aee 100644 (file)
@@ -256,6 +256,16 @@ array_idx_i(const struct array *array, unsigned int idx)
 
 #define array_idx(array, idx) \
        ARRAY_TYPE_CAST_CONST(array)array_idx_i(&(array)->arr, idx)
+/* Using *array_idx() will fail if the compiler doesn't support typeof().
+   The same can be done with array_idx_elem() for arrays that have pointers. */
+#ifdef HAVE_TYPEOF
+#  define array_idx_elem(array, idx) \
+       (TRUE ? *array_idx(array, idx) : \
+               COMPILE_ERROR_IF_TRUE(sizeof(**(array)->v) != sizeof(void *)))
+#else
+#  define array_idx_elem(array, idx) \
+       (*(void **)array_idx_i(&(array)->arr, idx))
+#endif
 
 static inline void *
 array_get_modifiable_i(struct array *array, unsigned int *count_r)
index 36a64ba81698d147d6cd4b970f9b4d69f19e4318..ccaf1c3e7ab80092af439523f1d94b60a84b36fc 100644 (file)
@@ -8,6 +8,36 @@ struct foo {
        unsigned int a, b, c;
 };
 
+static void test_array_elem(void)
+{
+       ARRAY(struct foo *) foos;
+       struct foo *nfoo;
+       unsigned int i;
+
+       test_begin("array elem");
+       t_array_init(&foos, 32);
+
+       for (i = 1; i <= 3; i++) {
+               nfoo = t_new(struct foo, 1);
+               nfoo->a = i;
+               array_push_back(&foos, &nfoo);
+       }
+
+       struct foo *const *foo_p = array_idx(&foos, 1);
+       unsigned int idx = 1;
+       struct foo *foo = array_idx_elem(&foos, idx++);
+       /* make sure idx isn't expanded multiple times in the macro */
+       test_assert(idx == 2);
+       test_assert(*foo_p == foo);
+
+       i = 1;
+       array_foreach_elem(&foos, foo) {
+               test_assert(foo->a == i);
+               i++;
+       }
+       test_end();
+}
+
 static void test_array_count(void)
 {
        ARRAY(struct foo) foos;
@@ -264,6 +294,7 @@ test_array_free(void)
 
 void test_array(void)
 {
+       test_array_elem();
        test_array_count();
        test_array_foreach();
        test_array_foreach_elem_string();