array_foreach(&foo_arr, foo) {
..
- } */
+ }
+
+ Note that deleting an element while iterating will cause the iteration to
+ skip over the next element. So deleting a single element and breaking out
+ of the loop is fine, but continuing the loop is likely a bug. Use
+ array_foreach_reverse() instead when deleting multiple elements.
+*/
#define array_foreach(array, elem) \
for (const void *elem ## __foreach_end = \
(const char *)(elem = *(array)->v) + (array)->arr.buffer->used; \
buffer_get_modifiable_data((array)->arr.buffer, NULL)) + \
(array)->arr.buffer->used; \
elem != elem ## _end; (elem)++)
+
+/* Iterate the array in reverse order. */
+#define array_foreach_reverse(array, elem) \
+ for (elem = CONST_PTR_OFFSET(*(array)->v, (array)->arr.buffer->used); \
+ (const char *)(elem--) > (const char *)*(array)->v; )
+#define array_foreach_reverse_modifiable(array, elem) \
+ for (elem = ARRAY_TYPE_CAST_MODIFIABLE(array) \
+ ((char *)buffer_get_modifiable_data((array)->arr.buffer, NULL) + \
+ (array)->arr.buffer->used); \
+ (const char *)(elem--) > (const char *)*(array)->v; )
+
/* Usage:
ARRAY(struct foo *) foo_ptrs_arr;
struct foo *foo;
test_assert(foo == array_idx(&foos, i)+1);
test_end();
}
+
+static void test_array_foreach_reverse(void)
+{
+ ARRAY(unsigned int) arr;
+ const unsigned int *i_p;
+ unsigned int i, i2, *imod_p;
+
+ test_begin("array foreach reverse");
+ t_array_init(&arr, 32);
+
+ /* first test that array_foreach() + array_delete() doesn't really
+ work as we might hope.. */
+ for (i = 1; i <= 5; i++)
+ array_push_back(&arr, &i);
+ array_foreach(&arr, i_p) {
+ i = array_foreach_idx(&arr, i_p);
+ array_delete(&arr, i, 1);
+ }
+ test_assert(array_count(&arr) == 2);
+
+ /* but using array_foreach_reverse() + array_delete() does work: */
+ array_clear(&arr);
+ i2 = 5;
+ for (i = 1; i <= i2; i++)
+ array_push_back(&arr, &i);
+ array_foreach_reverse(&arr, i_p) {
+ i = array_foreach_idx(&arr, i_p);
+ test_assert(*i_p == i2);
+ test_assert(*i_p == i + 1);
+ array_delete(&arr, i, 1);
+ i2--;
+ }
+ test_assert(array_count(&arr) == 0);
+
+ /* also array_foreach_reverse_modifiable() + array_delete() works: */
+ i2 = 5;
+ for (i = 1; i <= i2; i++)
+ array_push_back(&arr, &i);
+ array_foreach_reverse_modifiable(&arr, imod_p) {
+ i = array_foreach_idx(&arr, imod_p);
+ test_assert(*imod_p == i2);
+ test_assert(*imod_p == i + 1);
+ array_delete(&arr, i, 1);
+ i2--;
+ }
+ test_assert(array_count(&arr) == 0);
+
+ test_end();
+}
+
static void test_array_foreach_elem_string(void)
{
ARRAY(char *) blurbs;
test_array_elem();
test_array_count();
test_array_foreach();
+ test_array_foreach_reverse();
test_array_foreach_elem_string();
test_array_reverse();
test_array_cmp();