1 | //===-- Macros defined in sys/queue.h header file -------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H |
10 | #define LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H |
11 | |
12 | #include "llvm-libc-macros/containerof-macro.h" |
13 | #include "llvm-libc-macros/null-macro.h" |
14 | |
15 | #ifdef __cplusplus |
16 | #define QUEUE_TYPEOF(type) type |
17 | #else |
18 | #define QUEUE_TYPEOF(type) struct type |
19 | #endif |
20 | |
21 | // Singly-linked list definitions. |
22 | |
23 | #define SLIST_HEAD(name, type) \ |
24 | struct name { \ |
25 | struct type *slh_first; \ |
26 | } |
27 | |
28 | #define SLIST_CLASS_HEAD(name, type) \ |
29 | struct name { \ |
30 | class type *slh_first; \ |
31 | } |
32 | |
33 | #define SLIST_HEAD_INITIALIZER(head) \ |
34 | { NULL } |
35 | |
36 | #define SLIST_ENTRY(type) \ |
37 | struct { \ |
38 | struct type *next; \ |
39 | } |
40 | |
41 | #define SLIST_CLASS_ENTRY(type) \ |
42 | struct { \ |
43 | class type *next; \ |
44 | } |
45 | |
46 | // Singly-linked list access methods. |
47 | |
48 | #define SLIST_EMPTY(head) ((head)->slh_first == NULL) |
49 | #define SLIST_FIRST(head) ((head)->slh_first) |
50 | #define SLIST_NEXT(elem, field) ((elem)->field.next) |
51 | |
52 | #define SLIST_FOREACH(var, head, field) \ |
53 | for ((var) = SLIST_FIRST(head); (var); (var) = SLIST_NEXT(var, field)) |
54 | |
55 | #define SLIST_FOREACH_FROM(var, head, field) \ |
56 | if (!(var)) \ |
57 | (var) = SLIST_FIRST(head); \ |
58 | for (; (var); (var) = SLIST_NEXT(var, field)) |
59 | |
60 | #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ |
61 | for ((var) = SLIST_FIRST(head); \ |
62 | (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar)) |
63 | |
64 | #define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ |
65 | if (!(var)) \ |
66 | (var) = SLIST_FIRST(head); \ |
67 | for (; (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar)) |
68 | |
69 | // Singly-linked list functions. |
70 | |
71 | #define SLIST_CONCAT(head1, head2, type, field) \ |
72 | do { \ |
73 | if (SLIST_EMPTY(head1)) { \ |
74 | if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ |
75 | SLIST_INIT(head2); \ |
76 | } else if (!SLIST_EMPTY(head2)) { \ |
77 | QUEUE_TYPEOF(type) *cur = SLIST_FIRST(head1); \ |
78 | while (SLIST_NEXT(cur, field) != NULL) \ |
79 | cur = SLIST_NEXT(cur, field); \ |
80 | SLIST_NEXT(cur, field) = SLIST_FIRST(head2); \ |
81 | SLIST_INIT(head2); \ |
82 | } \ |
83 | } while (0) |
84 | |
85 | #define SLIST_INIT(head) \ |
86 | do { \ |
87 | SLIST_FIRST(head) = NULL; \ |
88 | } while (0) |
89 | |
90 | #define SLIST_INSERT_AFTER(slistelem, elem, field) \ |
91 | do { \ |
92 | SLIST_NEXT(elem, field) = SLIST_NEXT(slistelem, field); \ |
93 | SLIST_NEXT(slistelem, field) = (elem); \ |
94 | } while (0) |
95 | |
96 | #define SLIST_INSERT_HEAD(head, elem, field) \ |
97 | do { \ |
98 | SLIST_NEXT(elem, field) = SLIST_FIRST(head); \ |
99 | SLIST_FIRST(head) = (elem); \ |
100 | } while (0) |
101 | |
102 | #define SLIST_REMOVE(head, elem, type, field) \ |
103 | do { \ |
104 | if (SLIST_FIRST(head) == (elem)) { \ |
105 | SLIST_REMOVE_HEAD(head, field); \ |
106 | } else { \ |
107 | QUEUE_TYPEOF(type) *cur = SLIST_FIRST(head); \ |
108 | while (SLIST_NEXT(cur, field) != (elem)) \ |
109 | cur = SLIST_NEXT(cur, field); \ |
110 | SLIST_REMOVE_AFTER(cur, field); \ |
111 | } \ |
112 | } while (0) |
113 | |
114 | #define SLIST_REMOVE_AFTER(elem, field) \ |
115 | do { \ |
116 | SLIST_NEXT(elem, field) = SLIST_NEXT(SLIST_NEXT(elem, field), field); \ |
117 | } while (0) |
118 | |
119 | #define SLIST_REMOVE_HEAD(head, field) \ |
120 | do { \ |
121 | SLIST_FIRST(head) = SLIST_NEXT(SLIST_FIRST(head), field); \ |
122 | } while (0) |
123 | |
124 | #define SLIST_SWAP(head1, head2, type) \ |
125 | do { \ |
126 | QUEUE_TYPEOF(type) *first = SLIST_FIRST(head1); \ |
127 | SLIST_FIRST(head1) = SLIST_FIRST(head2); \ |
128 | SLIST_FIRST(head2) = first; \ |
129 | } while (0) |
130 | |
131 | // Singly-linked tail queue definitions. |
132 | |
133 | #define STAILQ_HEAD(name, type) \ |
134 | struct name { \ |
135 | struct type *stqh_first; \ |
136 | struct type **stqh_last; \ |
137 | } |
138 | |
139 | #define STAILQ_CLASS_HEAD(name, type) \ |
140 | struct name { \ |
141 | class type *stqh_first; \ |
142 | class type **stqh_last; \ |
143 | } |
144 | |
145 | #define STAILQ_HEAD_INITIALIZER(head) \ |
146 | { NULL, &(head).stqh_first } |
147 | |
148 | #define STAILQ_ENTRY(type) \ |
149 | struct { \ |
150 | struct type *next; \ |
151 | } |
152 | |
153 | #define STAILQ_CLASS_ENTRY(type) \ |
154 | struct { \ |
155 | class type *next; \ |
156 | } |
157 | |
158 | // Singly-linked tail queue access methods. |
159 | |
160 | #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) |
161 | #define STAILQ_FIRST(head) ((head)->stqh_first) |
162 | #define STAILQ_LAST(head, type, field) \ |
163 | (STAILQ_EMPTY(head) \ |
164 | ? NULL \ |
165 | : __containerof((head)->stqh_last, QUEUE_TYPEOF(type), field.next)) |
166 | #define STAILQ_NEXT(elem, field) ((elem)->field.next) |
167 | |
168 | #define STAILQ_FOREACH(var, head, field) \ |
169 | for ((var) = STAILQ_FIRST(head); (var); (var) = STAILQ_NEXT(var, field)) |
170 | |
171 | #define STAILQ_FOREACH_FROM(var, head, field) \ |
172 | if (!(var)) \ |
173 | (var) = STAILQ_FIRST(head); \ |
174 | for (; (var); (var) = STAILQ_NEXT(var, field)) |
175 | |
176 | #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ |
177 | for ((var) = STAILQ_FIRST(head); \ |
178 | (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar)) |
179 | |
180 | #define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ |
181 | if (!(var)) \ |
182 | (var) = STAILQ_FIRST(head); \ |
183 | for (; (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar)) |
184 | |
185 | // Singly-linked tail queue functions. |
186 | |
187 | #define STAILQ_CONCAT(head1, head2, type, field) \ |
188 | do { \ |
189 | if (!STAILQ_EMPTY(head2)) { \ |
190 | *(head1)->stqh_last = (head2)->stqh_first; \ |
191 | (head1)->stqh_last = (head2)->stqh_last; \ |
192 | STAILQ_INIT(head2); \ |
193 | } \ |
194 | } while (0) |
195 | |
196 | #define STAILQ_INIT(head) \ |
197 | do { \ |
198 | STAILQ_FIRST(head) = NULL; \ |
199 | (head)->stqh_last = &STAILQ_FIRST(head); \ |
200 | } while (0) |
201 | |
202 | #define STAILQ_INSERT_AFTER(head, listelem, elem, field) \ |
203 | do { \ |
204 | if ((STAILQ_NEXT(elem, field) = STAILQ_NEXT(listelem, field)) == NULL) \ |
205 | (head)->stqh_last = &STAILQ_NEXT(elem, field); \ |
206 | STAILQ_NEXT(listelem, field) = (elem); \ |
207 | } while (0) |
208 | |
209 | #define STAILQ_INSERT_HEAD(head, elem, field) \ |
210 | do { \ |
211 | if ((STAILQ_NEXT(elem, field) = STAILQ_FIRST(head)) == NULL) \ |
212 | (head)->stqh_last = &STAILQ_NEXT(elem, field); \ |
213 | STAILQ_FIRST(head) = (elem); \ |
214 | } while (0) |
215 | |
216 | #define STAILQ_INSERT_TAIL(head, elem, field) \ |
217 | do { \ |
218 | STAILQ_NEXT(elem, field) = NULL; \ |
219 | *(head)->stqh_last = (elem); \ |
220 | (head)->stqh_last = &STAILQ_NEXT(elem, field); \ |
221 | } while (0) |
222 | |
223 | #define STAILQ_REMOVE(head, elem, type, field) \ |
224 | do { \ |
225 | if (STAILQ_FIRST(head) == (elem)) { \ |
226 | STAILQ_REMOVE_HEAD(head, field); \ |
227 | } else { \ |
228 | QUEUE_TYPEOF(type) *cur = STAILQ_FIRST(head); \ |
229 | while (STAILQ_NEXT(cur, field) != (elem)) \ |
230 | cur = STAILQ_NEXT(cur, field); \ |
231 | STAILQ_REMOVE_AFTER(head, cur, field); \ |
232 | } \ |
233 | } while (0) |
234 | |
235 | #define STAILQ_REMOVE_AFTER(head, elem, field) \ |
236 | do { \ |
237 | if ((STAILQ_NEXT(elem, field) = \ |
238 | STAILQ_NEXT(STAILQ_NEXT(elem, field), field)) == NULL) \ |
239 | (head)->stqh_last = &STAILQ_NEXT(elem, field); \ |
240 | } while (0) |
241 | |
242 | #define STAILQ_REMOVE_HEAD(head, field) \ |
243 | do { \ |
244 | if ((STAILQ_FIRST(head) = STAILQ_NEXT(STAILQ_FIRST(head), field)) == NULL) \ |
245 | (head)->stqh_last = &STAILQ_FIRST(head); \ |
246 | } while (0) |
247 | |
248 | #define STAILQ_SWAP(head1, head2, type) \ |
249 | do { \ |
250 | QUEUE_TYPEOF(type) *first = STAILQ_FIRST(head1); \ |
251 | QUEUE_TYPEOF(type) **last = (head1)->stqh_last; \ |
252 | STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ |
253 | (head1)->stqh_last = (head2)->stqh_last; \ |
254 | STAILQ_FIRST(head2) = first; \ |
255 | (head2)->stqh_last = last; \ |
256 | if (STAILQ_EMPTY(head1)) \ |
257 | (head1)->stqh_last = &STAILQ_FIRST(head1); \ |
258 | if (STAILQ_EMPTY(head2)) \ |
259 | (head2)->stqh_last = &STAILQ_FIRST(head2); \ |
260 | } while (0) |
261 | |
262 | #endif // LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H |
263 | |