CAPS Universe documentation  1.0.4
All you need to know to be successful
list.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2#pragma once
3
11#include <stdbool.h>
12
17#define LIST_HEAD(t,name) \
18 t *name
19
23#define LIST_FIELDS(t,name) \
24 t *name##_next, *name##_prev
25
31#define LIST_HEAD_INIT(head) \
32 do { \
33 (head) = NULL; } \
34 while (false)
35
42#define LIST_INIT(name,item) \
43 do { \
44 typeof(*(item)) *_item = (item); \
45 caps_assert(_item); \
46 _item->name##_prev = _item->name##_next = NULL; \
47 } while (false)
55#define LIST_PREPEND(name,head,item) \
56 do { \
57 typeof(*(head)) **_head = &(head), *_item = (item); \
58 caps_assert(_item); \
59 if ((_item->name##_next = *_head)) \
60 _item->name##_next->name##_prev = _item; \
61 _item->name##_prev = NULL; \
62 *_head = _item; \
63 } while (false)
73#define LIST_APPEND(name,head,item) \
74 do { \
75 typeof(*(head)) *_tail; \
76 LIST_FIND_TAIL(name,head,_tail); \
77 LIST_INSERT_AFTER(name,head,_tail,item); \
78 } while (false)
86#define LIST_REMOVE(name,head,item) \
87 do { \
88 typeof(*(head)) **_head = &(head), *_item = (item); \
89 caps_assert(_item); \
90 if (_item->name##_next) \
91 _item->name##_next->name##_prev = _item->name##_prev; \
92 if (_item->name##_prev) \
93 _item->name##_prev->name##_next = _item->name##_next; \
94 else { \
95 caps_assert(*_head == _item); \
96 *_head = _item->name##_next; \
97 } \
98 _item->name##_next = _item->name##_prev = NULL; \
99 } while (false)
100
113#define LIST_FIND_HEAD(name,item,head) \
114 do { \
115 typeof(*(item)) *_item = (item); \
116 if (!_item) \
117 (head) = NULL; \
118 else { \
119 while (_item->name##_prev) \
120 _item = _item->name##_prev; \
121 (head) = _item; \
122 } \
123 } while (false)
124
137#define LIST_FIND_TAIL(name,item,tail) \
138 do { \
139 typeof(*(item)) *_item = (item); \
140 if (!_item) \
141 (tail) = NULL; \
142 else { \
143 while (_item->name##_next) \
144 _item = _item->name##_next; \
145 (tail) = _item; \
146 } \
147 } while (false)
148
152#define LIST_INSERT_AFTER(name,head,a,b) \
153 do { \
154 typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
155 caps_assert(_b); \
156 if (!_a) { \
157 if ((_b->name##_next = *_head)) \
158 _b->name##_next->name##_prev = _b; \
159 _b->name##_prev = NULL; \
160 *_head = _b; \
161 } else { \
162 if ((_b->name##_next = _a->name##_next)) \
163 _b->name##_next->name##_prev = _b; \
164 _b->name##_prev = _a; \
165 _a->name##_next = _b; \
166 } \
167 } while (false)
168
172#define LIST_INSERT_BEFORE(name,head,a,b) \
173 do { \
174 typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
175 caps_assert(_b); \
176 if (!_a) { \
177 if (!*_head) { \
178 _b->name##_next = NULL; \
179 _b->name##_prev = NULL; \
180 *_head = _b; \
181 } else { \
182 typeof(*(head)) *_tail = (head); \
183 while (_tail->name##_next) \
184 _tail = _tail->name##_next; \
185 _b->name##_next = NULL; \
186 _b->name##_prev = _tail; \
187 _tail->name##_next = _b; \
188 } \
189 } else { \
190 if ((_b->name##_prev = _a->name##_prev)) \
191 _b->name##_prev->name##_next = _b; \
192 else \
193 *_head = _b; \
194 _b->name##_next = _a; \
195 _a->name##_prev = _b; \
196 } \
197 } while (false)
206#define LIST_JUST_US(name,item) \
207 (!(item)->name##_prev && !(item)->name##_next)
229#define LIST_FOREACH(name,i,head) \
230 for ((i) = (head); (i); (i) = (i)->name##_next)
253#define LIST_FOREACH_SAFE(name,i,n,head) \
254 for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
265#define LIST_FOREACH_BEFORE(name,i,p) \
266 for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev)
277#define LIST_FOREACH_AFTER(name,i,p) \
278 for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
286#define LIST_FOREACH_OTHERS(name,i,p) \
287 for (({ \
288 (i) = (p); \
289 while ((i) && (i)->name##_prev) \
290 (i) = (i)->name##_prev; \
291 if ((i) == (p)) \
292 (i) = (p)->name##_next; \
293 }); \
294 (i); \
295 (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next)
296
301#define LIST_LOOP_BUT_ONE(name,i,head,p) \
302 for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
303 (i) != (p); \
304 (i) = (i)->name##_next ? (i)->name##_next : (head))
312#define LIST_IS_EMPTY(head) \
313 (!(head))