From: Arran Cudbard-Bell Date: Sat, 8 Jan 2022 00:29:54 +0000 (-0800) Subject: Fix various issues with dcursor that would prevent them from working correctly with... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38a9b102f976c4282e583003e47b146f817879a7;p=thirdparty%2Ffreeradius-server.git Fix various issues with dcursor that would prevent them from working correctly with stateful iterators --- diff --git a/src/lib/io/schedule.c b/src/lib/io/schedule.c index 0faf3b08df..8a938c0017 100644 --- a/src/lib/io/schedule.c +++ b/src/lib/io/schedule.c @@ -222,8 +222,8 @@ static void *fr_schedule_worker_thread(void *arg) * Add this worker to all network threads. */ for (sn = fr_dlist_head(&sc->networks); - sn != NULL; - sn = fr_dlist_next(&sc->networks, sn)) { + sn != NULL; + sn = fr_dlist_next(&sc->networks, sn)) { (void) fr_network_worker_add(sn->nr, sw->worker); } diff --git a/src/lib/util/dcursor.c b/src/lib/util/dcursor.c index 5d425d2157..b54fca9beb 100644 --- a/src/lib/util/dcursor.c +++ b/src/lib/util/dcursor.c @@ -63,6 +63,8 @@ void *fr_dcursor_intersect_head(fr_dcursor_t *a, fr_dcursor_t *b) * If a and b are not currently set to the same item, b will be reset, * and wound to the item before a's current item. * + * The purpose of this function is to return items that match both iterators. + * * @note Both cursors must operate on the same list of items. * * @param[in] a First cursor. @@ -73,76 +75,51 @@ void *fr_dcursor_intersect_head(fr_dcursor_t *a, fr_dcursor_t *b) */ void *fr_dcursor_intersect_next(fr_dcursor_t *a, fr_dcursor_t *b) { - fr_dcursor_iter_t b_iter; - void *b_uctx; + void *a_next, *b_next; if (unlikely(a->dlist != b->dlist)) return NULL; /* - * If either of the iterators lack an iterator - * just use cursor_next... + * If either of the cursors lack an iterator + * just use cursor_next... i.e. return items + * from the list that's actually filtered. */ if (!a->iter) return fr_dcursor_next(b); if (!b->iter) return fr_dcursor_next(a); - /* - * Both have iterators... - */ - b_iter = b->iter; - b_uctx = b->iter_uctx; - /* * Deal with the case where the two iterators * are out of sync. */ - if (a->current != b->current) { - fr_dcursor_head(b); /* reset */ + if (a->current == b->current) { + a_next = fr_dcursor_next(a); + b_next = fr_dcursor_next(b); + + /* + * Fast path... + */ + if (a_next == b_next) return a_next; } else { - a->current = dcursor_next(a, a->current); - a->prev = fr_dlist_prev(a->dlist, a->current); + a_next = fr_dcursor_next(a); } + if (!a_next) return NULL; + /* - * Use a's iterator to select the item to - * check. + * b_next doesn't match a_next, we don't know + * if b is ahead or behind a, so we rewind + * b, and compare every item to see if it + * matches a. + * + * This is slow and inefficient, but there's + * nothing else we can do for stateful + * iterators. */ do { - void *a_prev = fr_dcursor_list_prev_peek(a); - b->iter = NULL; /* Disable b's iterator */ - - /* - * Find a in b (the slow way *sigh*) - */ - while ((b->current = dcursor_next(b, b->current)) && (b->current != a_prev)); - - /* - * No more items... - */ - if (!b->current) { - fr_dcursor_copy(a, b); - return NULL; - } - - /* - * We're now one item before the item - * returned by a, see if b's iterator - * returns the same item as a's. - */ - b->iter = b_iter; - b->current = dcursor_next(b, b->current); - - /* - * Matched, we're done... - */ - if (a->current == b->current) return a->current; - - /* - * Reset b's position to a's and try again. - */ - fr_dcursor_copy(b, a); - b->iter = b_iter; - b->iter_uctx = b_uctx; - } while ((a->current = dcursor_next(a, a->current))); + for (b_next = fr_dcursor_head(b); + b_next; + b_next = fr_dcursor_next(b)) if (a_next == b_next) return b_next; + } while ((a_next = fr_dcursor_next(a))); return NULL; } diff --git a/src/lib/util/dcursor.h b/src/lib/util/dcursor.h index 382c409c15..8a05b0096c 100644 --- a/src/lib/util/dcursor.h +++ b/src/lib/util/dcursor.h @@ -34,6 +34,8 @@ extern "C" { #include #include +typedef struct fr_dcursor_s fr_dcursor_t; + /** Callback for implementing custom iterators * * @param[in] list head of the dlist. @@ -46,6 +48,7 @@ extern "C" { * - NULL if no more matching attributes were found. */ typedef void *(*fr_dcursor_iter_t)(fr_dlist_head_t *list, void *to_eval, void *uctx); + /** Callback for performing additional actions on insert * * @param[in] list head of the dlist. @@ -56,6 +59,7 @@ typedef void *(*fr_dcursor_iter_t)(fr_dlist_head_t *list, void *to_eval, void *u * - -1 on failure. */ typedef int (*fr_dcursor_insert_t)(fr_dlist_head_t *list, void *to_insert, void *uctx); + /** Callback for performing additional actions on removal * * @param[in] list head of the dlist. @@ -66,6 +70,14 @@ typedef int (*fr_dcursor_insert_t)(fr_dlist_head_t *list, void *to_insert, void * - -1 on failure. */ typedef int (*fr_dcursor_remove_t)(fr_dlist_head_t *list, void *to_delete, void *uctx); + +/** Copy callback for duplicating complex dcursor state + * + * @param[out] out dcursor to copy to. + * @param[in] in dcursor to copy from. + */ +typedef void (*fr_dcursor_copy_t)(fr_dcursor_t *out, fr_dcursor_t const *in); + /** Type of evaluation functions to pass to the fr_dcursor_filter_*() functions. * * @param[in] item the item to be evaluated @@ -75,17 +87,25 @@ typedef int (*fr_dcursor_remove_t)(fr_dlist_head_t *list, void *to_delete, void * - false if the evaluation function is not satisfied. */ typedef bool (*fr_dcursor_eval_t)(void const *item, void const *uctx); -typedef struct { + +struct fr_dcursor_s { fr_dlist_head_t *dlist; //!< Head of the doubly linked list being iterated over. void *current; //!< The current item in the dlist. - void *prev; //!< The previous item in the dlist. + fr_dcursor_iter_t iter; //!< Iterator function. + fr_dcursor_iter_t peek; //!< Distinct "peek" function. This is sometimes necessary + ///< for iterators with complex state. void *iter_uctx; //!< to pass to iterator function. + fr_dcursor_insert_t insert; //!< Callback function on insert. fr_dcursor_remove_t remove; //!< Callback function on delete. void *mod_uctx; //!< to pass to modification functions. + + fr_dcursor_copy_t copy; //!< Copy dcursor state. + bool is_const; //!< The list we're iterating over is immutable. -} fr_dcursor_t; + bool at_end; //!< We're at the end of the list. +}; typedef struct { uint8_t depth; //!< Which cursor is currently in use. @@ -98,6 +118,20 @@ typedef struct { #define VALIDATE(_item) #endif +/** If current is set to a NULL pointer, we record that fact + * + * This stops us jumping back to the start of the dlist. + */ +static inline void *dcursor_current_set(fr_dcursor_t *cursor, void *current) +{ + VALIDATE(current); + + cursor->at_end = (current == NULL); + cursor->current = current; + + return current; +} + /** Internal function to get the next item * * @param[in] cursor to operate on. @@ -106,29 +140,27 @@ typedef struct { * - The next attribute. * - NULL if no more attributes. */ -static inline void *dcursor_next(fr_dcursor_t *cursor, void *current) +static inline void *dcursor_next(fr_dcursor_t *cursor, fr_dcursor_iter_t iter, void *current) { void *next; /* - * First time next has been called + * First time next has been called, or potentially + * another call after we hit the end of the list. */ if (!current) { - if (fr_dlist_empty(cursor->dlist)) return NULL; - if (cursor->prev) return NULL; /* At tail of the list */ - if (!cursor->iter) return (fr_dlist_head(cursor->dlist)); /* Fast path without custom iter */ + if (cursor->at_end) return NULL; /* At tail of the list */ + + if (!iter) return (fr_dlist_head(cursor->dlist)); /* Fast path without custom iter */ current = fr_dlist_head(cursor->dlist); - next = cursor->iter(cursor->dlist, current, cursor->iter_uctx); + next = iter(cursor->dlist, current, cursor->iter_uctx); VALIDATE(next); return next; } - VALIDATE(current); - if (!cursor->iter) { - return fr_dlist_next(cursor->dlist, current); /* Fast path without custom iter */ - } + if (!iter) return fr_dlist_next(cursor->dlist, current); /* Fast path without custom iter */ /* * Pre-advance current @@ -140,8 +172,9 @@ static inline void *dcursor_next(fr_dcursor_t *cursor, void *current) * The iterator can just return what it was passed for curr * if it just wants to advance by one. */ - next = cursor->iter(cursor->dlist, next, cursor->iter_uctx); + next = iter(cursor->dlist, next, cursor->iter_uctx); VALIDATE(next); + return next; } @@ -155,6 +188,8 @@ static inline void *dcursor_next(fr_dcursor_t *cursor, void *current) static inline void fr_dcursor_copy(fr_dcursor_t *out, fr_dcursor_t const *in) { memcpy(out, in, sizeof(*out)); + + if (in->copy) fr_dcursor_copy(out, in); } /** Rewind cursor to the start of the list @@ -164,11 +199,9 @@ static inline void fr_dcursor_copy(fr_dcursor_t *out, fr_dcursor_t const *in) * * @hidecallergraph */ +CC_HINT(nonnull) static inline void *fr_dcursor_head(fr_dcursor_t *cursor) { - if (unlikely(!cursor)) return NULL; - - cursor->prev = NULL; /* * If we have a custom iterator, the dlist attribute * may not be in the subset the iterator would @@ -176,15 +209,12 @@ static inline void *fr_dcursor_head(fr_dcursor_t *cursor) * dcursor_next figure it out. */ if (cursor->iter) { - cursor->current = dcursor_next(cursor, NULL); - return cursor->current; - } - - cursor->current = fr_dlist_head(cursor->dlist); + cursor->at_end = false; /* reset the flag, else next will just return NULL */ - VALIDATE(cursor->current); + return dcursor_current_set(cursor, dcursor_next(cursor, cursor->iter, NULL)); + } - return cursor->current; + return dcursor_current_set(cursor, fr_dlist_head(cursor->dlist)); } /** Wind cursor to the tail item in the list @@ -194,20 +224,24 @@ static inline void *fr_dcursor_head(fr_dcursor_t *cursor) * * @hidecallergraph */ +CC_HINT(nonnull) static inline void *fr_dcursor_tail(fr_dcursor_t *cursor) { - if (!cursor || fr_dlist_empty(cursor->dlist)) return NULL; + /* + * Keep calling next on the custom iterator + * until we hit the end of the list. + */ + if (cursor->iter) { + void *current = cursor->current; - cursor->current = fr_dlist_tail(cursor->dlist); - if (cursor->current) { - cursor->prev = fr_dlist_prev(cursor->dlist, cursor->current); - } else { - cursor->prev = NULL; - } + while ((cursor->current = dcursor_next(cursor, cursor->iter, cursor->current))) { + current = cursor->current; + } - VALIDATE(cursor->current); + return dcursor_current_set(cursor, current); + } - return cursor->current; + return dcursor_current_set(cursor, fr_dlist_tail(cursor->dlist)); } /** Advanced the cursor to the next item @@ -219,16 +253,10 @@ static inline void *fr_dcursor_tail(fr_dcursor_t *cursor) * * @hidecallergraph */ -static inline void * fr_dcursor_next(fr_dcursor_t *cursor) +CC_HINT(nonnull) +static inline void *fr_dcursor_next(fr_dcursor_t *cursor) { - if (!cursor || fr_dlist_empty(cursor->dlist)) return NULL; - cursor->current = dcursor_next(cursor, cursor->current); - - cursor->prev = fr_dlist_prev(cursor->dlist, cursor->current); - - VALIDATE(cursor->current); - - return cursor->current; + return dcursor_current_set(cursor, dcursor_next(cursor, cursor->iter, cursor->current)); } /** Return the next iterator item without advancing the cursor @@ -240,9 +268,10 @@ static inline void * fr_dcursor_next(fr_dcursor_t *cursor) * * @hidecallergraph */ +CC_HINT(nonnull) static inline void *fr_dcursor_next_peek(fr_dcursor_t *cursor) { - return dcursor_next(cursor, cursor->current); + return dcursor_next(cursor, cursor->peek, cursor->current); } /** Returns the next list item without advancing the cursor @@ -258,36 +287,10 @@ static inline void *fr_dcursor_next_peek(fr_dcursor_t *cursor) * * @hidecallergraph */ +CC_HINT(nonnull) static inline void *fr_dcursor_list_next_peek(fr_dcursor_t *cursor) { - if (!cursor || !cursor->current) return NULL; - - return fr_dlist_next(cursor->dlist, cursor->current); -} - -/** Returns the previous list item without rewinding the cursor - * - * @note This returns the previous item in the list, which may not be the - * previous 'current' value. - * - * @param[in] cursor to operator on. - * @return - * - Previous item. - * - NULL if no previous item available. - * - * @hidecallergraph - */ -static inline void *fr_dcursor_list_prev_peek(fr_dcursor_t *cursor) -{ - if (unlikely(!cursor)) return NULL; - - /* - * If cursor->current is not set then there's no prev. - * fr_dlist_prev would return the tail - */ - if (!cursor->prev) return NULL; - - return fr_dlist_prev(cursor->dlist, cursor->current); + return dcursor_next(cursor, NULL, cursor->current); } /** Return the item the cursor current points to @@ -299,12 +302,10 @@ static inline void *fr_dcursor_list_prev_peek(fr_dcursor_t *cursor) * * @hidecallergraph */ +CC_HINT(nonnull) static inline void *fr_dcursor_current(fr_dcursor_t *cursor) { - if (unlikely(!cursor)) return NULL; - VALIDATE(cursor->current); - return cursor->current; } @@ -318,24 +319,15 @@ static inline void *fr_dcursor_current(fr_dcursor_t *cursor) * * @hidecallergraph */ -static inline void * fr_dcursor_set_current(fr_dcursor_t *cursor, void *item) +static inline void *fr_dcursor_set_current(fr_dcursor_t *cursor, void *item) { if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return NULL; - if (fr_dlist_empty(cursor->dlist)) return NULL; - if (!item) return NULL; - - VALIDATE(item); - - /* - * Item must be in the dlist - */ - if (!fr_dlist_in_list(cursor->dlist, item)) return NULL; - - cursor->current = item; - cursor->prev = fr_dlist_prev(cursor->dlist, item); + if (!item || + !fr_dlist_in_list(cursor->dlist, item) || + (cursor->iter && !cursor->iter(cursor->dlist, item, cursor->iter_uctx))) return NULL; - return cursor->current; + return dcursor_current_set(cursor, item); } /** Insert a single item at the start of the list @@ -365,15 +357,6 @@ static inline int fr_dcursor_prepend(fr_dcursor_t *cursor, void *v) */ fr_dlist_insert_head(cursor->dlist, v); - /* - * Set previous if the cursor was already set but not - * prev - this will be if there was only one item in the - * list - */ - if (cursor->current && !cursor->prev) { - cursor->prev = v; - } - return 0; } @@ -401,6 +384,8 @@ static inline int fr_dcursor_append(fr_dcursor_t *cursor, void *v) fr_dlist_insert_tail(cursor->dlist, v); + cursor->at_end = false; /* Can't be at the end if we just inserted something */ + return 0; } @@ -461,35 +446,23 @@ static inline int fr_dcursor_insert(fr_dcursor_t *cursor, void *v) * * @hidecallergraph */ -static inline void * fr_dcursor_remove(fr_dcursor_t *cursor) +static inline void *fr_dcursor_remove(fr_dcursor_t *cursor) { - void *v, *p; + void *v; if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return NULL; if (!cursor->current) return NULL; /* don't do anything fancy, it's just a noop */ v = cursor->current; - VALIDATE(v); - if (cursor->remove) if (cursor->remove(cursor->dlist, v, cursor->mod_uctx) < 0) return NULL; + if (cursor->remove && (cursor->remove(cursor->dlist, v, cursor->mod_uctx) < 0)) return NULL; - p = fr_dcursor_list_prev_peek(cursor); - fr_dlist_remove(cursor->dlist, v); + dcursor_current_set(cursor, dcursor_next(cursor, cursor->iter, v)); - if (fr_dlist_head(cursor->dlist) == v) { - cursor->current = NULL; - cursor->prev = NULL; - } else { - cursor->current = p; - cursor->prev = p; - } + fr_dlist_remove(cursor->dlist, v); - /* - * Advance the cursor to the next item after the one which we just removed. - */ - cursor->current = dcursor_next(cursor, cursor->current); return v; } @@ -517,9 +490,9 @@ static inline void fr_dcursor_merge(fr_dcursor_t *cursor, fr_dcursor_t *to_appen p = cursor->current; while ((v = fr_dcursor_remove(to_append))) { fr_dcursor_insert(cursor, v); - cursor->current = v; + dcursor_current_set(cursor, v); } - cursor->current = p; + dcursor_current_set(cursor, p); } /** Return the next item, skipping the current item, that satisfies an evaluation function. @@ -602,7 +575,7 @@ void *fr_dcursor_intersect_next(fr_dcursor_t *a, fr_dcursor_t *b) CC_HINT(nonnul */ static inline void *fr_dcursor_replace(fr_dcursor_t *cursor, void *r) { - void *v, *p; + void *v; if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return NULL; @@ -626,8 +599,6 @@ static inline void *fr_dcursor_replace(fr_dcursor_t *cursor, void *r) fr_dcursor_append(cursor, r); return NULL; } - p = fr_dcursor_list_prev_peek(cursor); - VALIDATE(p); if (cursor->remove) if (cursor->remove(cursor->dlist, v, cursor->mod_uctx) < 0) return NULL; @@ -636,15 +607,11 @@ static inline void *fr_dcursor_replace(fr_dcursor_t *cursor, void *r) /* * Fixup current pointer. */ - cursor->current = p; - - /* - * re-advance the cursor. - * - * This ensures if the iterator skips the item - * we just replaced, it doesn't become current. - */ - fr_dcursor_next(cursor); + if (cursor->iter) { + dcursor_current_set(cursor, cursor->iter(cursor->dlist, r, cursor->iter_uctx)); /* Verify r matches */ + } else { + dcursor_current_set(cursor, r); /* Current becomes replacement */ + } return v; } @@ -673,19 +640,21 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor) /** Initialise a cursor with a custom iterator * - * @param[in] _cursor to initialise. - * @param[in] _head of item list. - * @param[in] _iter function. - * @param[in] _uctx _iter function _uctx. + * @param[in] _cursor to initialise. + * @param[in] _head of item list. + * @param[in] _iter function. + * @param[in] _peek function. If NULL _iter will be used for peeking. + * @param[in] _iter_uctx _iter function _uctx. * @return * - NULL if _head does not point to any items, or the iterator matches no items * in the current list. * - The first item returned by the iterator. */ -#define fr_dcursor_iter_mod_init(_cursor, _list, _iter, _iter_uctx, _insert, _remove, _mod_uctx) \ +#define fr_dcursor_iter_mod_init(_cursor, _list, _iter, _peek, _iter_uctx, _insert, _remove, _mod_uctx) \ _fr_dcursor_init(_cursor, \ _list, \ _iter, \ + _peek, \ _iter_uctx, \ _insert, \ _remove, \ @@ -697,16 +666,18 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor) * @param[in] _cursor to initialise. * @param[in] _head of item list. * @param[in] _iter function. + * @param[in] _peek function. If NULL _iter will be used for peeking. * @param[in] _uctx _iter function _uctx. * @return * - NULL if _head does not point to any items, or the iterator matches no items * in the current list. * - The first item returned by the iterator. */ -#define fr_dcursor_iter_init(_cursor, _head, _iter, _uctx) \ +#define fr_dcursor_iter_init(_cursor, _head, _iter, _peek, _uctx) \ _fr_dcursor_init(_cursor, \ _head, \ _iter, \ + _peek, \ _uctx, \ NULL, \ NULL, \ @@ -729,6 +700,7 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor) NULL, \ NULL, \ NULL, \ + NULL, \ IS_CONST(fr_dlist_head_t *, _head)) /** Setup a cursor to iterate over attribute items in dlists @@ -736,6 +708,7 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor) * @param[in] cursor Where to initialise the cursor (uses existing structure). * @param[in] head of dlist. * @param[in] iter Iterator callback. + * @param[in] peek Iterator callback that should not modify iterator state. * @param[in] iter_uctx to pass to iterator function. * @param[in] insert Callback for inserts. * @param[in] remove Callback for removals. @@ -747,12 +720,13 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor) */ static inline CC_HINT(nonnull(1,2)) void *_fr_dcursor_init(fr_dcursor_t *cursor, fr_dlist_head_t const *head, - fr_dcursor_iter_t iter, void const *iter_uctx, + fr_dcursor_iter_t iter, fr_dcursor_iter_t peek, void const *iter_uctx, fr_dcursor_insert_t insert, fr_dcursor_remove_t remove, void const *mod_uctx, bool is_const) { *cursor = (fr_dcursor_t){ .dlist = UNCONST(fr_dlist_head_t *, head), .iter = iter, + .peek = peek ? peek : iter, .iter_uctx = UNCONST(void *, iter_uctx), .insert = insert, .remove = remove, @@ -764,6 +738,27 @@ void *_fr_dcursor_init(fr_dcursor_t *cursor, fr_dlist_head_t const *head, return NULL; } +/** re-initialise a cursor, changing its list + * + * @param[in] _cursor to re-initialise. + * @param[in] _head of item list. + * @return + * - NULL if _head does not point to any items. + * - The first item in the list. + */ +#define fr_dcursor_reinit(_cursor, _head) \ + _fr_dcursor_reinit(_cursor, \ + _head, \ + IS_CONST(fr_dlist_head_t *, _head)) + +static inline CC_HINT(nonnull(1,2)) +void _fr_dcursor_list_reinit(fr_dcursor_t *cursor, fr_dlist_head_t const *head, bool is_const) +{ + cursor->dlist = UNCONST(fr_dlist_head_t *, head); + cursor->current = NULL; + cursor->is_const = is_const; +} + /** talloc_free the current item * * @param[in] cursor to free items from. diff --git a/src/lib/util/dcursor_tests.c b/src/lib/util/dcursor_tests.c index a286e3d3f4..cfdaeb3f71 100644 --- a/src/lib/util/dcursor_tests.c +++ b/src/lib/util/dcursor_tests.c @@ -36,11 +36,10 @@ static void test_init_null_item(void) test_list_init(&list); - item_p = fr_dcursor_iter_init(&cursor, &list.head, test_iter, &cursor); + item_p = fr_dcursor_iter_init(&cursor, &list.head, test_iter, NULL, &cursor); TEST_CHECK(!item_p); TEST_CHECK((cursor.dlist) == &list.head); TEST_CHECK(!fr_dcursor_current(&cursor)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(!fr_dcursor_list_next_peek(&cursor)); TEST_CHECK(cursor.iter_uctx == &cursor); } @@ -59,7 +58,6 @@ static void test_init_1i_start(void) TEST_CHECK(item_p == &item1); TEST_CHECK((cursor.dlist) == &list.head); TEST_CHECK(fr_dcursor_current(&cursor) == &item1); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); } static void test_init_2i_start(void) @@ -77,7 +75,6 @@ static void test_init_2i_start(void) item_p = fr_dcursor_init(&cursor, &list.head); TEST_CHECK(item_p == &item1); TEST_CHECK(fr_dcursor_current(&cursor) == &item1); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); } static void test_next(void) @@ -99,7 +96,6 @@ static void test_next(void) TEST_CHECK(item_p == &item2); TEST_CHECK(fr_dcursor_current(&cursor) == &item2); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); } static void test_next_wrap(void) @@ -118,13 +114,11 @@ static void test_next_wrap(void) fr_dcursor_next(&cursor); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); TEST_CHECK(!fr_dcursor_current(&cursor)); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); TEST_CHECK(!fr_dcursor_current(&cursor)); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); } @@ -159,7 +153,58 @@ static void test_dcursor_head(void) fr_dcursor_init(&cursor, &list.head); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); +} + +static void test_dcursor_head_reset(void) +{ + fr_dcursor_t cursor; + test_item_t item1 = { "item1", { NULL, NULL } }; + test_item_t item2 = { "item2", { NULL, NULL } }; + test_item_t *item_p; + test_item_list_t list; + + test_list_init(&list); + fr_dlist_insert_tail(&list.head, &item1); + fr_dlist_insert_tail(&list.head, &item2); + + fr_dcursor_init(&cursor, &list.head); + + item_p = fr_dcursor_head(&cursor); + TEST_CHECK(item_p == &item1); + + item_p = fr_dcursor_next(&cursor); + TEST_CHECK(item_p == &item2); + + item_p = fr_dcursor_next(&cursor); + TEST_CHECK(item_p == NULL); + + item_p = fr_dcursor_head(&cursor); + TEST_CHECK(item_p == &item1); +} + +static void test_dcursor_iter_head_reset(void) +{ + fr_dcursor_t cursor; + test_item_t item1 = { "item1", { NULL, NULL } }; + test_item_t item2 = { "item2", { NULL, NULL } }; + test_item_t *item_p; + test_item_list_t list; + + test_list_init(&list); + fr_dlist_insert_tail(&list.head, &item1); + fr_dlist_insert_tail(&list.head, &item2); + + item_p = fr_dcursor_iter_init(&cursor, &list.head, test_iter, NULL, &cursor); + TEST_CHECK(item_p == &item1); + + item_p = fr_dcursor_next(&cursor); + TEST_CHECK(item_p == &item2); + + item_p = fr_dcursor_next(&cursor); + TEST_CHECK(item_p == NULL); + + item_p = fr_dcursor_head(&cursor); + TEST_CHECK(item_p == &item1); } static void test_dcursor_head_after_next(void) @@ -180,7 +225,6 @@ static void test_dcursor_head_after_next(void) fr_dcursor_next(&cursor); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); } static void test_dcursor_tail(void) @@ -201,7 +245,6 @@ static void test_dcursor_tail(void) fr_dcursor_next(&cursor); item_p = fr_dcursor_tail(&cursor); TEST_CHECK(item_p == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); } static void test_dcursor_head_after_tail(void) @@ -222,7 +265,6 @@ static void test_dcursor_head_after_tail(void) fr_dcursor_tail(&cursor); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); } static void test_dcursor_wrap_after_tail(void) @@ -243,11 +285,9 @@ static void test_dcursor_wrap_after_tail(void) fr_dcursor_tail(&cursor); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); } static void test_dcursor_append_empty(void) @@ -265,7 +305,6 @@ static void test_dcursor_append_empty(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(!item_p); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item1); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == NULL); } static void test_dcursor_append_empty_3(void) @@ -306,7 +345,6 @@ static void test_dcursor_prepend_empty(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(!item_p); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item1); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == NULL); } static void test_dcursor_insert_into_empty(void) @@ -324,7 +362,6 @@ static void test_dcursor_insert_into_empty(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(!item_p); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item1); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == NULL); } static void test_dcursor_insert_into_empty_3(void) @@ -365,7 +402,6 @@ static void test_dcursor_replace_in_empty(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(!item_p); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item1); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == NULL); } static void test_dcursor_prepend_1i_start(void) @@ -384,11 +420,9 @@ static void test_dcursor_prepend_1i_start(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item1); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); /* Inserted before item 1 */ item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item2); @@ -413,11 +447,9 @@ static void test_dcursor_append_1i_start(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item1); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item2); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item2); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -442,11 +474,9 @@ static void test_dcursor_insert_1i_start(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item1); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item2); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item2); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -473,8 +503,6 @@ static void test_dcursor_replace_1i_start(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(item_p == &item2); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); - item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item2); @@ -500,15 +528,12 @@ static void test_dcursor_prepend_2i_start(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item1); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item2); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item2); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item3); @@ -535,11 +560,9 @@ static void test_dcursor_append_2i_start(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item1); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item2); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item2); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -573,15 +596,12 @@ static void test_dcursor_insert_2i_start(void) */ TEST_CHECK(fr_dcursor_current(&cursor) == &item1); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item3); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item2); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -616,8 +636,6 @@ static void test_dcursor_replace_2i_start(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(item_p == &item3); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); - item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item3); @@ -646,15 +664,12 @@ static void test_dcursor_prepend_3i_mid(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item2); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item4); @@ -684,11 +699,9 @@ static void test_dcursor_append_3i_mid(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item2); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -718,15 +731,12 @@ static void test_dcursor_insert_3i_mid(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item2); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item4); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -758,7 +768,6 @@ static void test_dcursor_replace_3i_mid(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(item_p == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item3); item_p = fr_dcursor_head(&cursor); @@ -790,11 +799,9 @@ static void test_dcursor_prepend_3i_end(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item3); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item4); @@ -825,11 +832,9 @@ static void test_dcursor_append_3i_end(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item3); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -860,15 +865,12 @@ static void test_dcursor_insert_3i_end(void) TEST_CHECK(fr_dcursor_current(&cursor) == &item3); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); item_p = fr_dcursor_next(&cursor); TEST_CHECK(item_p == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item3); item_p = fr_dcursor_next(&cursor); TEST_CHECK(!item_p); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item4); item_p = fr_dcursor_head(&cursor); TEST_CHECK(item_p == &item1); @@ -901,7 +903,6 @@ static void test_dcursor_replace_3i_end(void) item_p = fr_dcursor_current(&cursor); TEST_CHECK(item_p == &item4); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); item_p = fr_dcursor_head(&cursor); @@ -918,7 +919,7 @@ static void test_dcursor_remove_empty(void) test_list_init(&list); - _fr_dcursor_init(&cursor, (fr_dlist_head_t *)&list, test_iter, NULL, NULL, NULL, NULL, false); + _fr_dcursor_init(&cursor, (fr_dlist_head_t *)&list, test_iter, NULL, NULL, NULL, NULL, NULL, false); TEST_CHECK(!fr_dcursor_remove(&cursor)); } @@ -938,7 +939,6 @@ static void test_dcursor_remove_1i(void) TEST_CHECK(item_p == &item1); TEST_CHECK(!fr_dcursor_current(&cursor)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(!fr_dcursor_next(&cursor)); TEST_CHECK(!fr_dcursor_tail(&cursor)); TEST_CHECK(!fr_dcursor_head(&cursor)); @@ -961,7 +961,6 @@ static void test_dcursor_remove_2i(void) TEST_CHECK(item_p == &item1); TEST_CHECK(fr_dcursor_current(&cursor) == &item2); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(!fr_dcursor_next(&cursor)); TEST_CHECK(fr_dcursor_tail(&cursor) == &item2); TEST_CHECK(fr_dcursor_head(&cursor) == &item2); @@ -970,7 +969,6 @@ static void test_dcursor_remove_2i(void) TEST_CHECK(item_p == &item2); TEST_CHECK(!fr_dcursor_current(&cursor)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(!fr_dcursor_next(&cursor)); TEST_CHECK(!fr_dcursor_tail(&cursor)); TEST_CHECK(!fr_dcursor_head(&cursor)); @@ -994,13 +992,11 @@ static void test_dcursor_remove_3i_start(void) item_p = fr_dcursor_remove(&cursor); TEST_CHECK(item_p == &item1); TEST_CHECK(fr_dcursor_current(&cursor) == &item2); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(fr_dcursor_next_peek(&cursor) == &item3); item_p = fr_dcursor_remove(&cursor); TEST_CHECK(item_p == &item2); TEST_CHECK(fr_dcursor_current(&cursor) == &item3); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); item_p = fr_dcursor_remove(&cursor); @@ -1030,7 +1026,6 @@ static void test_dcursor_remove_3i_mid(void) item_p = fr_dcursor_remove(&cursor); TEST_CHECK(item_p == &item2); TEST_CHECK(fr_dcursor_current(&cursor) == &item3); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); item_p = fr_dcursor_remove(&cursor); @@ -1043,7 +1038,6 @@ static void test_dcursor_remove_3i_mid(void) * We don't implicitly start moving backwards. */ TEST_CHECK(!fr_dcursor_current(&cursor)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item1); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); item_p = fr_dcursor_remove(&cursor); @@ -1073,14 +1067,12 @@ static void test_dcursor_remove_3i_end(void) item_p = fr_dcursor_remove(&cursor); TEST_CHECK(item_p == &item3); TEST_CHECK(!fr_dcursor_current(&cursor)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); item_p = fr_dcursor_remove(&cursor); TEST_CHECK(!item_p); TEST_CHECK(!fr_dcursor_current(&cursor)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor) == &item2); TEST_CHECK(!fr_dcursor_next_peek(&cursor)); } @@ -1148,7 +1140,6 @@ static void test_dcursor_merge_start_a_b(void) TEST_CHECK(!fr_dcursor_next(&cursor_a)); TEST_CHECK(!fr_dcursor_current(&cursor_b)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor_b)); TEST_CHECK(!fr_dcursor_list_next_peek(&cursor_b)); } @@ -1211,7 +1202,6 @@ static void test_dcursor_merge_mid_a(void) TEST_CHECK(!fr_dcursor_next(&cursor_a)); TEST_CHECK(!fr_dcursor_current(&cursor_b)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor_b)); TEST_CHECK(!fr_dcursor_list_next_peek(&cursor_b)); } @@ -1270,7 +1260,6 @@ static void test_dcursor_merge_end_a(void) */ TEST_CHECK(!fr_dcursor_list_next_peek(&cursor_a)); TEST_CHECK(!fr_dcursor_current(&cursor_b)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor_b)); TEST_CHECK(!fr_dcursor_list_next_peek(&cursor_b)); } @@ -1336,7 +1325,6 @@ static void test_dcursor_merge_mid_b(void) TEST_CHECK(!fr_dcursor_next(&cursor_a)); TEST_CHECK(!fr_dcursor_current(&cursor_b)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor_b) == &item1b); TEST_CHECK(!fr_dcursor_list_next_peek(&cursor_b)); } @@ -1400,7 +1388,6 @@ static void test_dcursor_merge_end_b(void) TEST_CHECK(!fr_dcursor_next(&cursor_a)); TEST_CHECK(!fr_dcursor_current(&cursor_b)); - TEST_CHECK(fr_dcursor_list_prev_peek(&cursor_b) == &item2b); TEST_CHECK(fr_dcursor_head(&cursor_b) == &item1b); } @@ -1430,7 +1417,6 @@ static void test_dcursor_merge_with_empty(void) TEST_CHECK(fr_dcursor_next(&cursor_a) == &item3b); TEST_CHECK(!fr_dcursor_current(&cursor_b)); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor_b)); TEST_CHECK(!fr_dcursor_list_next_peek(&cursor_b)); } @@ -1505,7 +1491,6 @@ static void test_dcursor_free(void) fr_dcursor_free_list(&cursor); TEST_CHECK(fr_dcursor_current(&cursor) == NULL); - TEST_CHECK(!fr_dcursor_list_prev_peek(&cursor)); TEST_CHECK(!fr_dcursor_tail(&cursor)); TEST_CHECK(!fr_dcursor_head(&cursor)); @@ -1595,7 +1580,7 @@ static void test_intersect_iterator_a(void) fr_dlist_insert_tail(&list.head, &item3); fr_dlist_insert_tail(&list.head, &item4); - fr_dcursor_iter_init(&cursor_a, &list.head, iter_name_check, &filter_a); + fr_dcursor_iter_init(&cursor_a, &list.head, iter_name_check, NULL, &filter_a); fr_dcursor_init(&cursor_b, &list.head); TEST_CHECK(fr_dcursor_intersect_head(&cursor_a, &cursor_b) == &item1); @@ -1622,7 +1607,7 @@ static void test_intersect_iterator_b(void) fr_dlist_insert_tail(&list.head, &item4); fr_dcursor_init(&cursor_a, &list.head); - fr_dcursor_iter_init(&cursor_b, &list.head, iter_name_check, &filter_b); + fr_dcursor_iter_init(&cursor_b, &list.head, iter_name_check, NULL, &filter_b); TEST_CHECK(fr_dcursor_intersect_head(&cursor_a, &cursor_b) == &item1); TEST_CHECK(fr_dcursor_intersect_next(&cursor_a, &cursor_b) == &item3); @@ -1649,8 +1634,8 @@ static void test_intersect_iterator_ab(void) fr_dlist_insert_tail(&list.head, &item4); fr_dlist_insert_tail(&list.head, &item5); - fr_dcursor_iter_init(&cursor_a, &list.head, iter_name_check, &filter_a); - fr_dcursor_iter_init(&cursor_b, &list.head, iter_name_check, &filter_b); + fr_dcursor_iter_init(&cursor_a, &list.head, iter_name_check, NULL, &filter_a); + fr_dcursor_iter_init(&cursor_b, &list.head, iter_name_check, NULL, &filter_b); TEST_CHECK(fr_dcursor_intersect_head(&cursor_a, &cursor_b) == &item1); TEST_CHECK(fr_dcursor_intersect_next(&cursor_a, &cursor_b) == &item3); @@ -1679,8 +1664,8 @@ static void test_intersect_iterator_disjoint(void) fr_dlist_insert_tail(&list.head, &item4); fr_dlist_insert_tail(&list.head, &item5); - fr_dcursor_iter_init(&cursor_a, &list.head, iter_name_check, &filter_a); - fr_dcursor_iter_init(&cursor_b, &list.head, iter_name_check, &filter_b); + fr_dcursor_iter_init(&cursor_a, &list.head, iter_name_check, NULL, &filter_a); + fr_dcursor_iter_init(&cursor_b, &list.head, iter_name_check, NULL, &filter_b); TEST_CHECK(fr_dcursor_intersect_head(&cursor_a, &cursor_b) == NULL); } @@ -1796,6 +1781,8 @@ TEST_LIST = { */ { "head_tail_null", test_dcursor_head_tail_null }, { "head", test_dcursor_head }, + { "head_reset", test_dcursor_head_reset }, + { "head_iter_reset", test_dcursor_iter_head_reset }, { "head_after_next", test_dcursor_head_after_next }, { "tail", test_dcursor_tail }, { "head_after_tail", test_dcursor_head_after_tail }, diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index e8b3b4737d..8ddbb4adb3 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -841,7 +841,7 @@ fr_pair_t *_fr_pair_dcursor_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const bool is_const) { return _fr_dcursor_init(cursor, fr_pair_order_list_list_head(&list->order), - iter, uctx, + iter, NULL, uctx, _pair_list_dcursor_insert, _pair_list_dcursor_remove, list, is_const); } @@ -862,7 +862,7 @@ fr_pair_t *_fr_pair_dcursor_init(fr_dcursor_t *cursor, fr_pair_list_t const *lis bool is_const) { return _fr_dcursor_init(cursor, fr_pair_order_list_list_head(&list->order), - NULL, NULL, + NULL, NULL, NULL, _pair_list_dcursor_insert, _pair_list_dcursor_remove, list, is_const); } @@ -882,7 +882,7 @@ fr_pair_t *_fr_pair_dcursor_by_da_init(fr_dcursor_t *cursor, bool is_const) { return _fr_dcursor_init(cursor, fr_pair_order_list_list_head(&list->order), - fr_pair_iter_next_by_da, da, + fr_pair_iter_next_by_da, NULL, da, _pair_list_dcursor_insert, _pair_list_dcursor_remove, list, is_const); } @@ -901,7 +901,7 @@ fr_pair_t *_fr_pair_dcursor_by_ancestor_init(fr_dcursor_t *cursor, bool is_const) { return _fr_dcursor_init(cursor, fr_pair_order_list_list_head(&list->order), - fr_pair_iter_next_by_ancestor, da, + fr_pair_iter_next_by_ancestor, NULL, da, _pair_list_dcursor_insert, _pair_list_dcursor_remove, list, is_const); }