]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: array - new copy-making array iterator
authorPhil Carmody <phil@dovecot.fi>
Wed, 3 Feb 2016 15:33:05 +0000 (17:33 +0200)
committerGitLab <gitlab@git.dovecot.net>
Tue, 19 Apr 2016 17:29:28 +0000 (20:29 +0300)
Previously macros took a pointer, and that pointer was made to pointed
to each element of the array in turn. Typical use cases for things like
char* or struct* arrays were to immediately/repeatedly, dereference that
pointer.

This new iter (only one implementation done so far, more a proof of
concept) gets rid of the user-visable pointer, and performs the
dereference every time, and only when, a valid element is being
iterated over. Empty array => no assignment. No U.B.

NOTE: This cannot be done without assuming C99. It breaks the build
on compilers that old if any components that are enabled use the
macro. It strongly suggests we just need to make C99 mandatory.

Signed-off-by: Phil Carmody <phil@dovecot.fi>
src/lib/array.h

index 7065a02a3d9af812112ca594f6565c3e53139465..ee209a4b15d21d5b2de1f8f96002b5a93faafbcb 100644 (file)
                        buffer_get_modifiable_data((array)->arr.buffer, NULL)) + \
                        (array)->arr.buffer->used; \
             elem != elem ## _end; (elem)++)
+/* Bikeshed: which is better
+   array_foreach_elem(array, myvar) { ... use myvar ... }  // not clear myvar is modified
+   array_foreach_elem(array, &myvar) { ... use myvar ... } // clearer, as more pass-by-referencey
+   Latter is impossible if we want to use the variable name as the base for the other variable names
+*/
+#  define array_foreach_elem(array, elem) \
+       for (unsigned int _foreach_offset = ARRAY_TYPE_CHECK(array, &elem) + \
+                               COMPILE_ERROR_IF_TRUE(sizeof(elem) > 16)\
+                    ;                                                  \
+            (_foreach_offset < (array)->arr.buffer->used) &&           \
+            (memcpy(&elem, CONST_PTR_OFFSET(*(array)->v, _foreach_offset), sizeof(elem)), TRUE) \
+               ;                                                       \
+            _foreach_offset += sizeof(elem)                            \
+               )
+
 #else
 #  define array_foreach(array, elem) \
        for (elem = *(array)->v; \