From: Phil Carmody Date: Wed, 3 Feb 2016 15:33:05 +0000 (+0200) Subject: lib: array - new copy-making array iterator X-Git-Tag: 2.3.0.rc1~4006 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2d729323913a672708dc600242e1cc3085985dcc;p=thirdparty%2Fdovecot%2Fcore.git lib: array - new copy-making array iterator 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 --- diff --git a/src/lib/array.h b/src/lib/array.h index 7065a02a3d..ee209a4b15 100644 --- a/src/lib/array.h +++ b/src/lib/array.h @@ -78,6 +78,21 @@ 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; \