aboutsummaryrefslogtreecommitdiff
path: root/src/list.h
diff options
context:
space:
mode:
authorallusive-dev <[email protected]>2023-09-19 17:47:33 +1000
committerallusive-dev <[email protected]>2023-09-19 17:47:33 +1000
commita93aba600b1c5d019b680b9f4ff3fa85d5d43a60 (patch)
tree77f8152222655657472a70e0bfa413a0495dd555 /src/list.h
parentreset (diff)
downloadcompfy-a93aba600b1c5d019b680b9f4ff3fa85d5d43a60.tar.xz
compfy-a93aba600b1c5d019b680b9f4ff3fa85d5d43a60.zip
Fixed broken files/code and other errors
Diffstat (limited to 'src/list.h')
-rw-r--r--src/list.h108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/list.h b/src/list.h
new file mode 100644
index 0000000..19e2c2c
--- /dev/null
+++ b/src/list.h
@@ -0,0 +1,108 @@
+#pragma once
+#include <stdbool.h>
+#include <stddef.h>
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) \
+ ({ \
+ const __typeof__(((type *)0)->member) *__mptr = (ptr); \
+ (type *)((char *)__mptr - offsetof(type, member)); \
+ })
+
+struct list_node {
+ struct list_node *next, *prev;
+};
+
+#define list_entry(ptr, type, node) container_of(ptr, type, node)
+#define list_next_entry(ptr, node) list_entry((ptr)->node.next, __typeof__(*(ptr)), node)
+#define list_prev_entry(ptr, node) list_entry((ptr)->node.prev, __typeof__(*(ptr)), node)
+
+/// Insert a new node between two adjacent nodes in the list
+static inline void __list_insert_between(struct list_node *prev, struct list_node *next,
+ struct list_node *new_) {
+ new_->prev = prev;
+ new_->next = next;
+ next->prev = new_;
+ prev->next = new_;
+}
+
+/// Insert a new node after `curr`
+static inline void list_insert_after(struct list_node *curr, struct list_node *new_) {
+ __list_insert_between(curr, curr->next, new_);
+}
+
+/// Insert a new node before `curr`
+static inline void list_insert_before(struct list_node *curr, struct list_node *new_) {
+ __list_insert_between(curr->prev, curr, new_);
+}
+
+/// Link two nodes in the list, so `next` becomes the successor node of `prev`
+static inline void __list_link(struct list_node *prev, struct list_node *next) {
+ next->prev = prev;
+ prev->next = next;
+}
+
+/// Remove a node from the list
+static inline void list_remove(struct list_node *to_remove) {
+ __list_link(to_remove->prev, to_remove->next);
+ to_remove->prev = (void *)-1;
+ to_remove->next = (void *)-2;
+}
+
+/// Move `to_move` so that it's before `new_next`
+static inline void list_move_before(struct list_node *to_move, struct list_node *new_next) {
+ list_remove(to_move);
+ list_insert_before(new_next, to_move);
+}
+
+/// Move `to_move` so that it's after `new_prev`
+static inline void list_move_after(struct list_node *to_move, struct list_node *new_prev) {
+ list_remove(to_move);
+ list_insert_after(new_prev, to_move);
+}
+
+/// Initialize a list node that's intended to be the head node
+static inline void list_init_head(struct list_node *head) {
+ head->next = head->prev = head;
+}
+
+/// Replace list node `old` with `n`
+static inline void list_replace(struct list_node *old, struct list_node *n) {
+ __list_insert_between(old->prev, old->next, n);
+ old->prev = (void *)-1;
+ old->next = (void *)-2;
+}
+
+/// Return true if head is the only node in the list. Under usual circumstances this means
+/// the list is empty
+static inline bool list_is_empty(const struct list_node *head) {
+ return head->prev == head;
+}
+
+/// Return true if `to_check` is the first node in list headed by `head`
+static inline bool
+list_node_is_first(const struct list_node *head, const struct list_node *to_check) {
+ return head->next == to_check;
+}
+
+/// Return true if `to_check` is the last node in list headed by `head`
+static inline bool
+list_node_is_last(const struct list_node *head, const struct list_node *to_check) {
+ return head->prev == to_check;
+}
+
+#define list_foreach(type, i, head, member) \
+ for (type *i = list_entry((head)->next, type, member); &i->member != (head); \
+ i = list_next_entry(i, member))
+
+/// Like list_for_each, but it's safe to remove the current list node from the list
+#define list_foreach_safe(type, i, head, member) \
+ for (type *i = list_entry((head)->next, type, member), \
+ *__tmp = list_next_entry(i, member); \
+ &i->member != (head); i = __tmp, __tmp = list_next_entry(i, member))