Skip to content

Commit

Permalink
c-list: add reverse iterators
Browse files Browse the repository at this point in the history
Add reverse versions of each for_each macro, allowing for reverse
iteration of lists.
  • Loading branch information
ronand-atl committed Nov 19, 2024
1 parent 9aa81d8 commit 8ec1071
Showing 1 changed file with 98 additions and 34 deletions.
132 changes: 98 additions & 34 deletions src/c-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,72 +362,136 @@ static inline CList *c_list_last(CList *list) {
* it assumes the entire list will be unlinked. You must not
* break out of the loop, or the list will be in an inconsistent
* state.
*
* - "reverse": The list is iterated in reverse order.
*
* Note: macros starting with "__" are not meant to be used directly.
*/

/* direct/raw iterators */

#define c_list_for_each(_iter, _list) \
for (_iter = (_list)->next; \
#define __c_list_for_each(_iter, _list, _dir) \
for (_iter = (_list)->_dir; \
(_iter) != (_list); \
_iter = (_iter)->next)
_iter = (_iter)->_dir)

#define c_list_for_each_safe(_iter, _safe, _list) \
for (_iter = (_list)->next, _safe = (_iter)->next; \
#define __c_list_for_each_safe(_iter, _safe, _list, _dir) \
for (_iter = (_list)->_dir, _safe = (_iter)->_dir; \
(_iter) != (_list); \
_iter = (_safe), _safe = (_safe)->next)
_iter = (_safe), _safe = (_safe)->_dir)

#define c_list_for_each_continue(_iter, _list) \
for (_iter = (_iter) ? (_iter)->next : (_list)->next; \
#define __c_list_for_each_continue(_iter, _list, _dir) \
for (_iter = (_iter) ? (_iter)->_dir : (_list)->_dir; \
(_iter) != (_list); \
_iter = (_iter)->next)
_iter = (_iter)->_dir)

#define c_list_for_each_safe_continue(_iter, _safe, _list) \
for (_iter = (_iter) ? (_iter)->next : (_list)->next, \
_safe = (_iter)->next; \
#define __c_list_for_each_safe_continue(_iter, _safe, _list, _dir) \
for (_iter = (_iter) ? (_iter)->_dir : (_list)->_dir, \
_safe = (_iter)->_dir; \
(_iter) != (_list); \
_iter = (_safe), _safe = (_safe)->next)
_iter = (_safe), _safe = (_safe)->_dir)

#define c_list_for_each_safe_unlink(_iter, _safe, _list) \
for (_iter = (_list)->next, _safe = (_iter)->next; \
#define __c_list_for_each_safe_unlink(_iter, _safe, _list, _dir) \
for (_iter = (_list)->_dir, _safe = (_iter)->_dir; \
c_list_init(_iter) != (_list); \
_iter = (_safe), _safe = (_safe)->next)
_iter = (_safe), _safe = (_safe)->_dir)

#define c_list_for_each(_iter, _list) \
__c_list_for_each(_iter, _list, next)

#define c_list_for_each_reverse(_iter, _list) \
__c_list_for_each(_iter, _list, prev)

#define c_list_for_each_safe(_iter, _safe, _list) \
__c_list_for_each_safe(_iter, _safe, _list, next)

#define c_list_for_each_safe_reverse(_iter, _safe, _list) \
__c_list_for_each_safe(_iter, _safe, _list, prev)

#define c_list_for_each_continue(_iter, _list) \
__c_list_for_each_continue(_iter, _list, next)

#define c_list_for_each_continue_reverse(_iter, _list) \
__c_list_for_each_continue(_iter, _list, prev)

#define c_list_for_each_safe_continue(_iter, _safe, _list) \
__c_list_for_each_safe_continue(_iter, _safe, _list, next)

#define c_list_for_each_safe_continue_reverse(_iter, _safe, _list) \
__c_list_for_each_safe_continue(_iter, _safe, _list, prev)

#define c_list_for_each_safe_unlink(_iter, _safe, _list) \
__c_list_for_each_safe_unlink(_iter, _safe, _list, next)

#define c_list_for_each_safe_unlink_reverse(_iter, _safe, _list) \
__c_list_for_each_safe_unlink(_iter, _safe, _list, prev)

/* c_list_entry() based iterators */

#define c_list_for_each_entry(_iter, _list, _m) \
for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m); \
#define __c_list_for_each_entry(_iter, _list, _m, _dir) \
for (_iter = c_list_entry((_list)->_dir, __typeof__(*_iter), _m); \
&(_iter)->_m != (_list); \
_iter = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m))
_iter = c_list_entry((_iter)->_m._dir, __typeof__(*_iter), _m))

#define c_list_for_each_entry_safe(_iter, _safe, _list, _m) \
for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m), \
_safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \
#define __c_list_for_each_entry_safe(_iter, _safe, _list, _m, _dir) \
for (_iter = c_list_entry((_list)->_dir, __typeof__(*_iter), _m), \
_safe = c_list_entry((_iter)->_m._dir, __typeof__(*_iter), _m); \
&(_iter)->_m != (_list); \
_iter = (_safe), \
_safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m))
_safe = c_list_entry((_safe)->_m._dir, __typeof__(*_iter), _m))

#define c_list_for_each_entry_continue(_iter, _list, _m) \
for (_iter = c_list_entry((_iter) ? (_iter)->_m.next : (_list)->next, \
#define __c_list_for_each_entry_continue(_iter, _list, _m, _dir) \
for (_iter = c_list_entry((_iter) ? (_iter)->_m._dir : (_list)->_dir, \
__typeof__(*_iter), \
_m); \
&(_iter)->_m != (_list); \
_iter = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m))
_iter = c_list_entry((_iter)->_m._dir, __typeof__(*_iter), _m))

#define c_list_for_each_entry_safe_continue(_iter, _safe, _list, _m) \
for (_iter = c_list_entry((_iter) ? (_iter)->_m.next : (_list)->next, \
#define __c_list_for_each_entry_safe_continue(_iter, _safe, _list, _m, _dir) \
for (_iter = c_list_entry((_iter) ? (_iter)->_m._dir : (_list)->_dir, \
__typeof__(*_iter), \
_m), \
_safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \
_safe = c_list_entry((_iter)->_m._dir, __typeof__(*_iter), _m); \
&(_iter)->_m != (_list); \
_iter = (_safe), \
_safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m))
_safe = c_list_entry((_safe)->_m._dir, __typeof__(*_iter), _m))

#define c_list_for_each_entry_safe_unlink(_iter, _safe, _list, _m) \
for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m), \
_safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \
#define __c_list_for_each_entry_safe_unlink(_iter, _safe, _list, _m, _dir) \
for (_iter = c_list_entry((_list)->_dir, __typeof__(*_iter), _m), \
_safe = c_list_entry((_iter)->_m._dir, __typeof__(*_iter), _m); \
c_list_init(&(_iter)->_m) != (_list); \
_iter = (_safe), \
_safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m))
_safe = c_list_entry((_safe)->_m._dir, __typeof__(*_iter), _m))

#define c_list_for_each_entry(_iter, _list, _m) \
__c_list_for_each_entry(_iter, _list, _m, next)

#define c_list_for_each_entry_reverse(_iter, _list, _m) \
__c_list_for_each_entry(_iter, _list, _m, prev)

#define c_list_for_each_entry_safe(_iter, _safe, _list, _m) \
__c_list_for_each_entry_safe(_iter, _safe, _list, _m, next)

#define c_list_for_each_entry_safe_reverse(_iter, _safe, _list, _m) \
__c_list_for_each_entry_safe(_iter, _safe, _list, _m, prev)

#define c_list_for_each_entry_continue(_iter, _list, _m) \
__c_list_for_each_entry_continue(_iter, _list, _m, next)

#define c_list_for_each_entry_continue_reverse(_iter, _list, _m) \
__c_list_for_each_entry_continue(_iter, _list, _m, prev)

#define c_list_for_each_entry_safe_continue(_iter, _safe, _list, _m) \
__c_list_for_each_entry_safe_continue(_iter, _safe, _list, _m, next)

#define c_list_for_each_entry_safe_continue_reverse(_iter, _safe, _list, _m) \
__c_list_for_each_entry_safe_continue(_iter, _safe, _list, _m, prev)

#define c_list_for_each_entry_safe_unlink(_iter, _safe, _list, _m) \
__c_list_for_each_entry_safe_unlink(_iter, _safe, _list, _m, next)

#define c_list_for_each_entry_safe_unlink_reverse(_iter, _safe, _list, _m) \
__c_list_for_each_entry_safe_unlink(_iter, _safe, _list, _m, prev)

/**
* c_list_flush() - flush all entries from a list
Expand Down

0 comments on commit 8ec1071

Please sign in to comment.