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

source code of libc/include/llvm-libc-macros/sys-queue-macros.h