void *fr_heap_iter_init(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
void *fr_heap_iter_next(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
+/** Iterate over the contents of a heap
+ *
+ * @note The initializer section of a for loop can't declare variables with distinct
+ * base types, so we require a containing block, and can't follow the standard
+ * do {...} while(0) dodge. The code to be run for each item in the heap should
+ * thus start with one open brace and end with two close braces, and shouldn't
+ * be followed with a semicolon.
+ * This may fake out code formatting programs and code-aware editors.
+ *
+ * @param[in] _heap to iterate over.
+ * @param[in] _type of item the heap contains.
+ * @param[in] _data Name of variable holding a pointer to the heap element.
+ * Will be declared in the scope of the loop.
+ */
+#define fr_heap_foreach(_heap, _type, _data) \
+{ \
+ fr_heap_iter_t _iter; \
+ for (_type *_data = fr_heap_iter_init(_heap, &_iter); _data; _data = fr_heap_iter_next(_heap, &_iter))
+
+
#ifdef __cplusplus
}
#endif
free(array);
}
+#define HEAP_ITER_SIZE 20
+
+static void heap_iter(void)
+{
+ fr_heap_t *hp;
+ heap_thing *array;
+ unsigned int data_set;
+
+ hp = fr_heap_alloc(NULL, heap_cmp, heap_thing, heap, 0);
+ TEST_CHECK(hp != NULL);
+
+ array = calloc(HEAP_ITER_SIZE, sizeof(heap_thing));
+
+ for (size_t i = 0; i < HEAP_ITER_SIZE; i++) {
+ array[i].data = i;
+ TEST_CHECK(fr_heap_insert(hp, &array[i]) >= 0);
+ }
+
+ data_set = 0;
+ fr_heap_foreach(hp, heap_thing, item) {
+ TEST_CHECK((data_set & (1U << item->data)) == 0);
+ data_set |= (1U << item->data);
+ }}
+ TEST_CHECK(data_set == ((1U << HEAP_ITER_SIZE) - 1U));
+
+ talloc_free(hp);
+ free(array);
+}
+
static void heap_cycle(void)
{
fr_heap_t *hp;
{ "heap_test_skip_2", heap_test_skip_2 },
{ "heap_test_skip_10", heap_test_skip_10 },
{ "heap_test_order", heap_test_order },
+ { "heap_iter", heap_iter },
{ "heap_cycle", heap_cycle },
{ NULL }
};
void *fr_lst_iter_next(fr_lst_t *lst, fr_lst_iter_t *iter) CC_HINT(nonnull);
+/** Iterate over the contents of an LST
+ *
+ * @note The initializer section of a for loop can't declare variables with distinct
+ * base types, so we require a containing block, and can't follow the standard
+ * do {...} while(0) dodge. The code to be run for each item in the LST should
+ * thus start with one open brace and end with two close braces, and shouldn't
+ * be followed with a semicolon.
+ * This may fake out code formatting programs and code-aware editors.
+ *
+ * @param[in] _lst to iterate over.
+ * @param[in] _type of item the heap contains.
+ * @param[in] _data Name of variable holding a pointer to the LST element.
+ * Will be declared in the scope of the loop.
+ */
+#define fr_lst_foreach(_lst, _type, _data) \
+{ \
+ fr_lst_iter_t _iter; \
+ for (_type *_data = fr_lst_iter_init(_lst, &_iter); _data; _data = fr_lst_iter_next(_lst, &_iter))
+
+
#ifdef __cplusplus
}
#endif
fr_lst_t *lst;
fr_lst_iter_t iter;
lst_thing values[NVALUES], *data;
-
+ unsigned int total;
lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
TEST_CHECK(lst != NULL);
}
TEST_CHECK(data == NULL);
+
+ total = 0;
+ fr_lst_foreach(lst, lst_thing, item) {
+ total += item->data;
+ }}
+ TEST_CHECK(total = 190);
+
talloc_free(lst);
}