From e4304e8b9e74577947647743fd51937ac51956c9 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 25 Sep 2023 13:53:15 -0400 Subject: list: New for_[s]list() macros --- src/list.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/list.h b/src/list.h index 235dc55..5587543 100644 --- a/src/list.h +++ b/src/list.h @@ -190,6 +190,12 @@ #define SLIST_ITEM_INIT__(item, next) \ 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. */ @@ -197,7 +203,7 @@ 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. @@ -319,6 +325,29 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, void #define SLIST_POP__(list, ...) \ (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. * @@ -355,6 +384,12 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, void #define LIST_ITEM_INIT__(item, prev, next) \ 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. */ @@ -362,7 +397,7 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, void 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 -- cgit v1.2.3