diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-09-25 13:53:15 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-09-25 13:59:32 -0400 |
commit | e4304e8b9e74577947647743fd51937ac51956c9 (patch) | |
tree | 06c7f0dd603f73ebb01b5bebcf7a487b07ff8e49 /src/list.h | |
parent | 6b341c9a7ed531cfd84301b59d2da0fd9d5474b1 (diff) | |
download | bfs-e4304e8b9e74577947647743fd51937ac51956c9.tar.xz |
list: New for_[s]list() macros
Diffstat (limited to 'src/list.h')
-rw-r--r-- | src/list.h | 62 |
1 files changed, 60 insertions, 2 deletions
@@ -191,13 +191,19 @@ LIST_VOID_(item->next = NULL) /** + * Type-checking macro for singly-linked lists. + */ +#define SLIST_CHECK_(list) \ + (void)sizeof(list->tail - &list->head) + +/** * Check if a singly-linked list is empty. */ #define SLIST_EMPTY(list) \ SLIST_EMPTY_((list)) #define SLIST_EMPTY_(list) \ - ((void)sizeof(list->tail - &list->head), !list->head) + (SLIST_CHECK_(list), !list->head) /** * Insert an item into a singly-linked list. @@ -320,6 +326,29 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, void (list->head ? SLIST_REMOVE_(list, &list->head, __VA_ARGS__) : NULL) /** + * Loop over the items in a singly-linked list. + * + * @param type + * The list item type. + * @param item + * The induction variable name. + * @param list + * The list to iterate. + * @param node (optional) + * If specified, use head->node.next rather than head->next. + */ +#define for_slist(type, item, ...) \ + for_slist_(type, item, __VA_ARGS__, ) + +#define for_slist_(type, item, list, ...) \ + for_slist__(type, item, (list), LIST_NEXT_(__VA_ARGS__)) + +#define for_slist__(type, item, list, next) \ + for (type *item = list->head, *_next; \ + item && (SLIST_CHECK_(list), _next = item->next, true); \ + item = _next) + +/** * Initialize a doubly-linked list. * * @param list @@ -356,13 +385,19 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, void LIST_VOID_(item->prev = item->next = NULL) /** + * Type-checking macro for doubly-linked lists. + */ +#define LIST_CHECK_(list) \ + (void)sizeof(list->tail - list->head) + +/** * Check if a doubly-linked list is empty. */ #define LIST_EMPTY(list) \ LIST_EMPTY_((list)) #define LIST_EMPTY_(list) \ - ((void)sizeof(list->tail - list->head), !list->head) + (LIST_CHECK_(list), !list->head) /** * Add an item to the tail of a doubly-linked list. @@ -456,4 +491,27 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, void #define LIST_ATTACHED__(list, item, prev, next) \ (item->prev || item->next || list->head == item || list->tail == item) +/** + * Loop over the items in a doubly-linked list. + * + * @param type + * The list item type. + * @param item + * The induction variable name. + * @param list + * The list to iterate. + * @param node (optional) + * If specified, use head->node.next rather than head->next. + */ +#define for_list(type, item, ...) \ + for_list_(type, item, __VA_ARGS__, ) + +#define for_list_(type, item, list, ...) \ + for_list__(type, item, (list), LIST_NEXT_(__VA_ARGS__)) + +#define for_list__(type, item, list, next) \ + for (type *item = list->head, *_next; \ + item && (LIST_CHECK_(list), _next = item->next, true); \ + item = _next) + #endif // BFS_LIST_H |