summaryrefslogtreecommitdiffstats
path: root/src/list.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/list.h')
-rw-r--r--src/list.h158
1 files changed, 90 insertions, 68 deletions
diff --git a/src/list.h b/src/list.h
index b30a96e..48f0d06 100644
--- a/src/list.h
+++ b/src/list.h
@@ -82,15 +82,17 @@
#ifndef BFS_LIST_H
#define BFS_LIST_H
+#include "bfs.h"
#include "diag.h"
#include <stddef.h>
+#include <stdint.h>
#include <string.h>
/**
* Initialize a singly-linked list.
*
- * @param list
+ * @list
* The list to initialize.
*
* ---
@@ -117,9 +119,9 @@
/**
* Initialize a singly-linked list item.
*
- * @param item
+ * @item
* The item to initialize.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
*
* ---
@@ -201,7 +203,7 @@
/**
* Get the head of a singly-linked list.
*
- * @param list
+ * @list
* The list in question.
* @return
* The first item in the list.
@@ -228,9 +230,9 @@
/**
* Get the tail of a singly-linked list.
*
- * @param list
+ * @list
* The list in question.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
* @return
* The last item in the list.
@@ -247,11 +249,11 @@
/**
* Check if an item is attached to a singly-linked list.
*
- * @param list
+ * @list
* The list to check.
- * @param item
+ * @item
* The item to check.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
* @return
* Whether the item is attached to the list.
@@ -268,13 +270,13 @@
/**
* Insert an item into a singly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param cursor
+ * @cursor
* A pointer to the item to insert after, e.g. &list->head or list->tail.
- * @param item
+ * @item
* The item to insert.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
* @return
* A cursor for the next item.
@@ -295,11 +297,11 @@
/**
* Add an item to the tail of a singly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param item
+ * @item
* The item to append.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
*/
#define SLIST_APPEND(list, ...) \
@@ -311,11 +313,11 @@
/**
* Add an item to the head of a singly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param item
+ * @item
* The item to prepend.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
*/
#define SLIST_PREPEND(list, ...) \
@@ -327,11 +329,11 @@
/**
* Splice a singly-linked list into another.
*
- * @param dest
+ * @dest
* The destination list.
- * @param cursor
+ * @cursor
* A pointer to the item to splice after, e.g. &list->head or list->tail.
- * @param src
+ * @src
* The source list.
*/
#define SLIST_SPLICE(dest, cursor, src) \
@@ -346,9 +348,9 @@
/**
* Add an entire singly-linked list to the tail of another.
*
- * @param dest
+ * @dest
* The destination list.
- * @param src
+ * @src
* The source list.
*/
#define SLIST_EXTEND(dest, src) \
@@ -357,11 +359,11 @@
/**
* Remove an item from a singly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param cursor
+ * @cursor
* A pointer to the item to remove, either &list->head or &prev->next.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
* @return
* The removed item.
@@ -372,26 +374,31 @@
#define SLIST_REMOVE_(list, cursor, ...) \
SLIST_REMOVE__((list), (cursor), LIST_NEXT_(__VA_ARGS__))
-#define SLIST_REMOVE__(list, cursor, next) \
- (list->tail = (*cursor)->next ? list->tail : cursor, \
- slist_remove_impl(*cursor, cursor, &(*cursor)->next, sizeof(*cursor)))
-
-// Helper for SLIST_REMOVE()
-static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_t size) {
- // ret = *cursor;
- // *cursor = ret->next;
- memcpy(cursor, next, size);
- // ret->next = NULL;
- memset(next, 0, size);
- return ret;
+// Scratch variables for the type-safe SLIST_REMOVE() implementation.
+// Not a pointer type due to https://github.com/llvm/llvm-project/issues/109718.
+_maybe_unused
+static thread_local uintptr_t _slist_prev, _slist_next;
+
+/** Suppress -Wunused-value. */
+_maybe_unused
+static inline void *_slist_cast(uintptr_t ptr) {
+ return (void *)ptr;
}
+#define SLIST_REMOVE__(list, cursor, next) \
+ (_slist_prev = (uintptr_t)(void *)*cursor, \
+ _slist_next = (uintptr_t)(void *)(*cursor)->next, \
+ (*cursor)->next = NULL, \
+ *cursor = (void *)_slist_next, \
+ list->tail = *cursor ? list->tail : cursor, \
+ _slist_cast(_slist_prev))
+
/**
* Pop the head off a singly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param node (optional)
+ * @node (optional)
* If specified, use head->node.next rather than head->next.
* @return
* The popped item, or NULL if the list was empty.
@@ -408,13 +415,13 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Loop over the items in a singly-linked list.
*
- * @param type
+ * @type
* The list item type.
- * @param item
+ * @item
* The induction variable name.
- * @param list
+ * @list
* The list to iterate.
- * @param node (optional)
+ * @node (optional)
* If specified, use head->node.next rather than head->next.
*/
#define for_slist(type, item, ...) \
@@ -429,9 +436,24 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
item = _next)
/**
+ * Loop over a singly-linked list, popping each item.
+ *
+ * @type
+ * The list item type.
+ * @item
+ * The induction variable name.
+ * @list
+ * The list to drain.
+ * @node (optional)
+ * If specified, use head->node.next rather than head->next.
+ */
+#define drain_slist(type, item, ...) \
+ for (type *item; (item = SLIST_POP(__VA_ARGS__));)
+
+/**
* Initialize a doubly-linked list.
*
- * @param list
+ * @list
* The list to initialize.
*/
#define LIST_INIT(list) \
@@ -450,9 +472,9 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Initialize a doubly-linked list item.
*
- * @param item
+ * @item
* The item to initialize.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.next rather than item->next.
*/
#define LIST_ITEM_INIT(...) \
@@ -482,11 +504,11 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Add an item to the tail of a doubly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param item
+ * @item
* The item to append.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.{prev,next} rather than item->{prev,next}.
*/
#define LIST_APPEND(list, ...) \
@@ -495,11 +517,11 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Add an item to the head of a doubly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param item
+ * @item
* The item to prepend.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.{prev,next} rather than item->{prev,next}.
*/
#define LIST_PREPEND(list, ...) \
@@ -508,11 +530,11 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Check if an item is attached to a doubly-linked list.
*
- * @param list
+ * @list
* The list to check.
- * @param item
+ * @item
* The item to check.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.{prev,next} rather than item->{prev,next}.
* @return
* Whether the item is attached to the list.
@@ -529,13 +551,13 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Insert into a doubly-linked list after the given cursor.
*
- * @param list
+ * @list
* The list to modify.
- * @param cursor
+ * @cursor
* Insert after this element.
- * @param item
+ * @item
* The item to insert.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.{prev,next} rather than item->{prev,next}.
*/
#define LIST_INSERT(list, cursor, ...) \
@@ -554,11 +576,11 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Remove an item from a doubly-linked list.
*
- * @param list
+ * @list
* The list to modify.
- * @param item
+ * @item
* The item to remove.
- * @param node (optional)
+ * @node (optional)
* If specified, use item->node.{prev,next} rather than item->{prev,next}.
*/
#define LIST_REMOVE(list, ...) \
@@ -575,13 +597,13 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
/**
* Loop over the items in a doubly-linked list.
*
- * @param type
+ * @type
* The list item type.
- * @param item
+ * @item
* The induction variable name.
- * @param list
+ * @list
* The list to iterate.
- * @param node (optional)
+ * @node (optional)
* If specified, use head->node.next rather than head->next.
*/
#define for_list(type, item, ...) \