Ajla 0.1.0
[ajla.git] / list.h
blobc0d25cd5a11097bb84f9dbd3357712d9922e079c
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifndef AJLA_LIST_H
20 #define AJLA_LIST_H
22 struct list {
23 struct list *next, *prev;
26 #ifdef DEBUG_LIST
27 static inline void list_verify(const struct list *head, const char *function, const char *position)
29 if (unlikely(head->next->prev != head) ||
30 unlikely(head->prev->next != head))
31 internal(position, "list corrupted in %s: head %p, head->next %p, head->next->prev %p, head->prev %p, head->prev->next %p", function, (const void *)head, (const void *)head->next, (const void *)head->next->prev, (const void *)head->prev, (const void *)head->prev->next);
33 #else
34 #define list_verify(head, position, function) ((void)0)
35 #endif
37 #define list_is_empty(entry) list_is_empty_(entry, file_line)
39 #define list_for_each(var, list) \
40 for (list_verify(list, "list_for_each 1", file_line), \
41 (var) = (list)->next, \
42 list_verify(var, "list_for_each 2", file_line); \
43 (var) != (list); \
44 (var) = (var)->next, \
45 list_verify(var, "list_for_each 3", file_line))
47 #define list_for_each_back(var, list) \
48 for (list_verify(list, "list_for_each 1", file_line), \
49 (var) = (list)->prev, \
50 list_verify(var, "list_for_each_back 3", file_line); \
51 (var) != (list); \
52 (var) = (var)->prev, \
53 list_verify(var, "list_for_each_back 3", file_line))
55 static inline void list_init(struct list *head)
57 head->next = head->prev = head;
60 static inline void list_init_add(struct list *head, struct list *entry)
62 head->next = head->prev = entry;
63 entry->next = entry->prev = head;
66 static inline void list_add_(struct list *head, struct list *entry, const char attr_unused *position)
68 #ifdef DEBUG_LIST
69 struct list *l;
70 unsigned i = 0;
71 list_for_each(l, head) {
72 if (unlikely(l == entry))
73 internal(position, "list_add: adding entry %p twice", entry);
74 if (++i >= 100)
75 break;
77 #endif
78 /*list_verify(head, "list_add 1", position);
79 list_verify(head->next, "list_add 2", position);*/
80 entry->prev = head;
81 entry->next = head->next;
82 head->next->prev = entry;
83 head->next = entry;
86 #define list_add(head, entry) list_add_(head, entry, file_line)
88 static inline void list_del_(struct list *entry, const char attr_unused *position)
90 list_verify(entry, "list_del", position);
91 entry->prev->next = entry->next;
92 entry->next->prev = entry->prev;
93 #ifdef DEBUG_LIST
94 entry->next = cast_cpp(struct list *, BAD_POINTER_1);
95 entry->prev = cast_cpp(struct list *, BAD_POINTER_2);
96 #endif
99 #define list_del(entry) list_del_(entry, file_line)
101 static inline bool list_is_empty_(struct list *head, const char attr_unused *position)
103 list_verify(head, "list_is_empty", position);
104 return head->next == head;
107 static inline void list_take_(struct list *dst, struct list *src, const char attr_unused *position)
109 if (list_is_empty_(src, position)) {
110 list_init(dst);
111 } else {
112 *dst = *src;
113 dst->next->prev = dst;
114 dst->prev->next = dst;
115 list_init(src);
119 #define list_take(dst, src) list_take_(dst, src, file_line)
121 #if 0
122 static inline void list_join_(struct list *dst, struct list *src, const char attr_unused *position)
124 list_verify(dst, "list_join dst", position);
125 if (!list_is_empty_(src, position)) {
126 src->next->prev = dst;
127 src->prev->next = dst->next;
128 dst->next->prev = src->prev;
129 dst->next = src->next;
132 #define list_join(dst, src) list_join_(dst, src, file_line)
133 #endif
135 #endif