1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * ilist.h |
4 | * integrated/inline doubly- and singly-linked lists |
5 | * |
6 | * These list types are useful when there are only a predetermined set of |
7 | * lists that an object could be in. List links are embedded directly into |
8 | * the objects, and thus no extra memory management overhead is required. |
9 | * (Of course, if only a small proportion of existing objects are in a list, |
10 | * the link fields in the remainder would be wasted space. But usually, |
11 | * it saves space to not have separately-allocated list nodes.) |
12 | * |
13 | * None of the functions here allocate any memory; they just manipulate |
14 | * externally managed memory. The APIs for singly and doubly linked lists |
15 | * are identical as far as capabilities of both allow. |
16 | * |
17 | * Each list has a list header, which exists even when the list is empty. |
18 | * An empty singly-linked list has a NULL pointer in its header. |
19 | * There are two kinds of empty doubly linked lists: those that have been |
20 | * initialized to NULL, and those that have been initialized to circularity. |
21 | * (If a dlist is modified and then all its elements are deleted, it will be |
22 | * in the circular state.) We prefer circular dlists because there are some |
23 | * operations that can be done without branches (and thus faster) on lists |
24 | * that use circular representation. However, it is often convenient to |
25 | * initialize list headers to zeroes rather than setting them up with an |
26 | * explicit initialization function, so we also allow the other case. |
27 | * |
28 | * EXAMPLES |
29 | * |
30 | * Here's a simple example demonstrating how this can be used. Let's assume |
31 | * we want to store information about the tables contained in a database. |
32 | * |
33 | * #include "lib/ilist.h" |
34 | * |
35 | * // Define struct for the databases including a list header that will be |
36 | * // used to access the nodes in the table list later on. |
37 | * typedef struct my_database |
38 | * { |
39 | * char *datname; |
40 | * dlist_head tables; |
41 | * // ... |
42 | * } my_database; |
43 | * |
44 | * // Define struct for the tables. Note the list_node element which stores |
45 | * // prev/next list links. The list_node element need not be first. |
46 | * typedef struct my_table |
47 | * { |
48 | * char *tablename; |
49 | * dlist_node list_node; |
50 | * perm_t permissions; |
51 | * // ... |
52 | * } my_table; |
53 | * |
54 | * // create a database |
55 | * my_database *db = create_database(); |
56 | * |
57 | * // and add a few tables to its table list |
58 | * dlist_push_head(&db->tables, &create_table(db, "a")->list_node); |
59 | * ... |
60 | * dlist_push_head(&db->tables, &create_table(db, "b")->list_node); |
61 | * |
62 | * |
63 | * To iterate over the table list, we allocate an iterator variable and use |
64 | * a specialized looping construct. Inside a dlist_foreach, the iterator's |
65 | * 'cur' field can be used to access the current element. iter.cur points to |
66 | * a 'dlist_node', but most of the time what we want is the actual table |
67 | * information; dlist_container() gives us that, like so: |
68 | * |
69 | * dlist_iter iter; |
70 | * dlist_foreach(iter, &db->tables) |
71 | * { |
72 | * my_table *tbl = dlist_container(my_table, list_node, iter.cur); |
73 | * printf("we have a table: %s in database %s\n", |
74 | * tbl->tablename, db->datname); |
75 | * } |
76 | * |
77 | * |
78 | * While a simple iteration is useful, we sometimes also want to manipulate |
79 | * the list while iterating. There is a different iterator element and looping |
80 | * construct for that. Suppose we want to delete tables that meet a certain |
81 | * criterion: |
82 | * |
83 | * dlist_mutable_iter miter; |
84 | * dlist_foreach_modify(miter, &db->tables) |
85 | * { |
86 | * my_table *tbl = dlist_container(my_table, list_node, miter.cur); |
87 | * |
88 | * if (!tbl->to_be_deleted) |
89 | * continue; // don't touch this one |
90 | * |
91 | * // unlink the current table from the linked list |
92 | * dlist_delete(miter.cur); |
93 | * // as these lists never manage memory, we can still access the table |
94 | * // after it's been unlinked |
95 | * drop_table(db, tbl); |
96 | * } |
97 | * |
98 | * |
99 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
100 | * Portions Copyright (c) 1994, Regents of the University of California |
101 | * |
102 | * IDENTIFICATION |
103 | * src/include/lib/ilist.h |
104 | *------------------------------------------------------------------------- |
105 | */ |
106 | #ifndef ILIST_H |
107 | #define ILIST_H |
108 | |
109 | /* |
110 | * Enable for extra debugging. This is rather expensive, so it's not enabled by |
111 | * default even when USE_ASSERT_CHECKING. |
112 | */ |
113 | /* #define ILIST_DEBUG */ |
114 | |
115 | /* |
116 | * Node of a doubly linked list. |
117 | * |
118 | * Embed this in structs that need to be part of a doubly linked list. |
119 | */ |
120 | typedef struct dlist_node dlist_node; |
121 | struct dlist_node |
122 | { |
123 | dlist_node *prev; |
124 | dlist_node *next; |
125 | }; |
126 | |
127 | /* |
128 | * Head of a doubly linked list. |
129 | * |
130 | * Non-empty lists are internally circularly linked. Circular lists have the |
131 | * advantage of not needing any branches in the most common list manipulations. |
132 | * An empty list can also be represented as a pair of NULL pointers, making |
133 | * initialization easier. |
134 | */ |
135 | typedef struct dlist_head |
136 | { |
137 | /* |
138 | * head.next either points to the first element of the list; to &head if |
139 | * it's a circular empty list; or to NULL if empty and not circular. |
140 | * |
141 | * head.prev either points to the last element of the list; to &head if |
142 | * it's a circular empty list; or to NULL if empty and not circular. |
143 | */ |
144 | dlist_node head; |
145 | } dlist_head; |
146 | |
147 | |
148 | /* |
149 | * Doubly linked list iterator. |
150 | * |
151 | * Used as state in dlist_foreach() and dlist_reverse_foreach(). To get the |
152 | * current element of the iteration use the 'cur' member. |
153 | * |
154 | * Iterations using this are *not* allowed to change the list while iterating! |
155 | * |
156 | * NB: We use an extra "end" field here to avoid multiple evaluations of |
157 | * arguments in the dlist_foreach() macro. |
158 | */ |
159 | typedef struct dlist_iter |
160 | { |
161 | dlist_node *cur; /* current element */ |
162 | dlist_node *end; /* last node we'll iterate to */ |
163 | } dlist_iter; |
164 | |
165 | /* |
166 | * Doubly linked list iterator allowing some modifications while iterating. |
167 | * |
168 | * Used as state in dlist_foreach_modify(). To get the current element of the |
169 | * iteration use the 'cur' member. |
170 | * |
171 | * Iterations using this are only allowed to change the list at the current |
172 | * point of iteration. It is fine to delete the current node, but it is *not* |
173 | * fine to insert or delete adjacent nodes. |
174 | * |
175 | * NB: We need a separate type for mutable iterations so that we can store |
176 | * the 'next' node of the current node in case it gets deleted or modified. |
177 | */ |
178 | typedef struct dlist_mutable_iter |
179 | { |
180 | dlist_node *cur; /* current element */ |
181 | dlist_node *next; /* next node we'll iterate to */ |
182 | dlist_node *end; /* last node we'll iterate to */ |
183 | } dlist_mutable_iter; |
184 | |
185 | /* |
186 | * Node of a singly linked list. |
187 | * |
188 | * Embed this in structs that need to be part of a singly linked list. |
189 | */ |
190 | typedef struct slist_node slist_node; |
191 | struct slist_node |
192 | { |
193 | slist_node *next; |
194 | }; |
195 | |
196 | /* |
197 | * Head of a singly linked list. |
198 | * |
199 | * Singly linked lists are not circularly linked, in contrast to doubly linked |
200 | * lists; we just set head.next to NULL if empty. This doesn't incur any |
201 | * additional branches in the usual manipulations. |
202 | */ |
203 | typedef struct slist_head |
204 | { |
205 | slist_node head; |
206 | } slist_head; |
207 | |
208 | /* |
209 | * Singly linked list iterator. |
210 | * |
211 | * Used as state in slist_foreach(). To get the current element of the |
212 | * iteration use the 'cur' member. |
213 | * |
214 | * It's allowed to modify the list while iterating, with the exception of |
215 | * deleting the iterator's current node; deletion of that node requires |
216 | * care if the iteration is to be continued afterward. (Doing so and also |
217 | * deleting or inserting adjacent list elements might misbehave; also, if |
218 | * the user frees the current node's storage, continuing the iteration is |
219 | * not safe.) |
220 | * |
221 | * NB: this wouldn't really need to be an extra struct, we could use an |
222 | * slist_node * directly. We prefer a separate type for consistency. |
223 | */ |
224 | typedef struct slist_iter |
225 | { |
226 | slist_node *cur; |
227 | } slist_iter; |
228 | |
229 | /* |
230 | * Singly linked list iterator allowing some modifications while iterating. |
231 | * |
232 | * Used as state in slist_foreach_modify(). To get the current element of the |
233 | * iteration use the 'cur' member. |
234 | * |
235 | * The only list modification allowed while iterating is to remove the current |
236 | * node via slist_delete_current() (*not* slist_delete()). Insertion or |
237 | * deletion of nodes adjacent to the current node would misbehave. |
238 | */ |
239 | typedef struct slist_mutable_iter |
240 | { |
241 | slist_node *cur; /* current element */ |
242 | slist_node *next; /* next node we'll iterate to */ |
243 | slist_node *prev; /* prev node, for deletions */ |
244 | } slist_mutable_iter; |
245 | |
246 | |
247 | /* Static initializers */ |
248 | #define DLIST_STATIC_INIT(name) {{&(name).head, &(name).head}} |
249 | #define SLIST_STATIC_INIT(name) {{NULL}} |
250 | |
251 | |
252 | /* Prototypes for functions too big to be inline */ |
253 | |
254 | /* Caution: this is O(n); consider using slist_delete_current() instead */ |
255 | extern void slist_delete(slist_head *head, slist_node *node); |
256 | |
257 | #ifdef ILIST_DEBUG |
258 | extern void dlist_check(dlist_head *head); |
259 | extern void slist_check(slist_head *head); |
260 | #else |
261 | /* |
262 | * These seemingly useless casts to void are here to keep the compiler quiet |
263 | * about the argument being unused in many functions in a non-debug compile, |
264 | * in which functions the only point of passing the list head pointer is to be |
265 | * able to run these checks. |
266 | */ |
267 | #define dlist_check(head) ((void) (head)) |
268 | #define slist_check(head) ((void) (head)) |
269 | #endif /* ILIST_DEBUG */ |
270 | |
271 | /* doubly linked list implementation */ |
272 | |
273 | /* |
274 | * Initialize a doubly linked list. |
275 | * Previous state will be thrown away without any cleanup. |
276 | */ |
277 | static inline void |
278 | dlist_init(dlist_head *head) |
279 | { |
280 | head->head.next = head->head.prev = &head->head; |
281 | } |
282 | |
283 | /* |
284 | * Is the list empty? |
285 | * |
286 | * An empty list has either its first 'next' pointer set to NULL, or to itself. |
287 | */ |
288 | static inline bool |
289 | dlist_is_empty(dlist_head *head) |
290 | { |
291 | dlist_check(head); |
292 | |
293 | return head->head.next == NULL || head->head.next == &(head->head); |
294 | } |
295 | |
296 | /* |
297 | * Insert a node at the beginning of the list. |
298 | */ |
299 | static inline void |
300 | dlist_push_head(dlist_head *head, dlist_node *node) |
301 | { |
302 | if (head->head.next == NULL) /* convert NULL header to circular */ |
303 | dlist_init(head); |
304 | |
305 | node->next = head->head.next; |
306 | node->prev = &head->head; |
307 | node->next->prev = node; |
308 | head->head.next = node; |
309 | |
310 | dlist_check(head); |
311 | } |
312 | |
313 | /* |
314 | * Insert a node at the end of the list. |
315 | */ |
316 | static inline void |
317 | dlist_push_tail(dlist_head *head, dlist_node *node) |
318 | { |
319 | if (head->head.next == NULL) /* convert NULL header to circular */ |
320 | dlist_init(head); |
321 | |
322 | node->next = &head->head; |
323 | node->prev = head->head.prev; |
324 | node->prev->next = node; |
325 | head->head.prev = node; |
326 | |
327 | dlist_check(head); |
328 | } |
329 | |
330 | /* |
331 | * Insert a node after another *in the same list* |
332 | */ |
333 | static inline void |
334 | dlist_insert_after(dlist_node *after, dlist_node *node) |
335 | { |
336 | node->prev = after; |
337 | node->next = after->next; |
338 | after->next = node; |
339 | node->next->prev = node; |
340 | } |
341 | |
342 | /* |
343 | * Insert a node before another *in the same list* |
344 | */ |
345 | static inline void |
346 | dlist_insert_before(dlist_node *before, dlist_node *node) |
347 | { |
348 | node->prev = before->prev; |
349 | node->next = before; |
350 | before->prev = node; |
351 | node->prev->next = node; |
352 | } |
353 | |
354 | /* |
355 | * Delete 'node' from its list (it must be in one). |
356 | */ |
357 | static inline void |
358 | dlist_delete(dlist_node *node) |
359 | { |
360 | node->prev->next = node->next; |
361 | node->next->prev = node->prev; |
362 | } |
363 | |
364 | /* |
365 | * Remove and return the first node from a list (there must be one). |
366 | */ |
367 | static inline dlist_node * |
368 | dlist_pop_head_node(dlist_head *head) |
369 | { |
370 | dlist_node *node; |
371 | |
372 | Assert(!dlist_is_empty(head)); |
373 | node = head->head.next; |
374 | dlist_delete(node); |
375 | return node; |
376 | } |
377 | |
378 | /* |
379 | * Move element from its current position in the list to the head position in |
380 | * the same list. |
381 | * |
382 | * Undefined behaviour if 'node' is not already part of the list. |
383 | */ |
384 | static inline void |
385 | dlist_move_head(dlist_head *head, dlist_node *node) |
386 | { |
387 | /* fast path if it's already at the head */ |
388 | if (head->head.next == node) |
389 | return; |
390 | |
391 | dlist_delete(node); |
392 | dlist_push_head(head, node); |
393 | |
394 | dlist_check(head); |
395 | } |
396 | |
397 | /* |
398 | * Check whether 'node' has a following node. |
399 | * Caution: unreliable if 'node' is not in the list. |
400 | */ |
401 | static inline bool |
402 | dlist_has_next(dlist_head *head, dlist_node *node) |
403 | { |
404 | return node->next != &head->head; |
405 | } |
406 | |
407 | /* |
408 | * Check whether 'node' has a preceding node. |
409 | * Caution: unreliable if 'node' is not in the list. |
410 | */ |
411 | static inline bool |
412 | dlist_has_prev(dlist_head *head, dlist_node *node) |
413 | { |
414 | return node->prev != &head->head; |
415 | } |
416 | |
417 | /* |
418 | * Return the next node in the list (there must be one). |
419 | */ |
420 | static inline dlist_node * |
421 | dlist_next_node(dlist_head *head, dlist_node *node) |
422 | { |
423 | Assert(dlist_has_next(head, node)); |
424 | return node->next; |
425 | } |
426 | |
427 | /* |
428 | * Return previous node in the list (there must be one). |
429 | */ |
430 | static inline dlist_node * |
431 | dlist_prev_node(dlist_head *head, dlist_node *node) |
432 | { |
433 | Assert(dlist_has_prev(head, node)); |
434 | return node->prev; |
435 | } |
436 | |
437 | /* internal support function to get address of head element's struct */ |
438 | static inline void * |
439 | dlist_head_element_off(dlist_head *head, size_t off) |
440 | { |
441 | Assert(!dlist_is_empty(head)); |
442 | return (char *) head->head.next - off; |
443 | } |
444 | |
445 | /* |
446 | * Return the first node in the list (there must be one). |
447 | */ |
448 | static inline dlist_node * |
449 | dlist_head_node(dlist_head *head) |
450 | { |
451 | return (dlist_node *) dlist_head_element_off(head, 0); |
452 | } |
453 | |
454 | /* internal support function to get address of tail element's struct */ |
455 | static inline void * |
456 | dlist_tail_element_off(dlist_head *head, size_t off) |
457 | { |
458 | Assert(!dlist_is_empty(head)); |
459 | return (char *) head->head.prev - off; |
460 | } |
461 | |
462 | /* |
463 | * Return the last node in the list (there must be one). |
464 | */ |
465 | static inline dlist_node * |
466 | dlist_tail_node(dlist_head *head) |
467 | { |
468 | return (dlist_node *) dlist_tail_element_off(head, 0); |
469 | } |
470 | |
471 | /* |
472 | * Return the containing struct of 'type' where 'membername' is the dlist_node |
473 | * pointed at by 'ptr'. |
474 | * |
475 | * This is used to convert a dlist_node * back to its containing struct. |
476 | */ |
477 | #define dlist_container(type, membername, ptr) \ |
478 | (AssertVariableIsOfTypeMacro(ptr, dlist_node *), \ |
479 | AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \ |
480 | ((type *) ((char *) (ptr) - offsetof(type, membername)))) |
481 | |
482 | /* |
483 | * Return the address of the first element in the list. |
484 | * |
485 | * The list must not be empty. |
486 | */ |
487 | #define dlist_head_element(type, membername, lhead) \ |
488 | (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \ |
489 | (type *) dlist_head_element_off(lhead, offsetof(type, membername))) |
490 | |
491 | /* |
492 | * Return the address of the last element in the list. |
493 | * |
494 | * The list must not be empty. |
495 | */ |
496 | #define dlist_tail_element(type, membername, lhead) \ |
497 | (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \ |
498 | ((type *) dlist_tail_element_off(lhead, offsetof(type, membername)))) |
499 | |
500 | /* |
501 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. |
502 | * |
503 | * Access the current element with iter.cur. |
504 | * |
505 | * It is *not* allowed to manipulate the list during iteration. |
506 | */ |
507 | #define dlist_foreach(iter, lhead) \ |
508 | for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \ |
509 | AssertVariableIsOfTypeMacro(lhead, dlist_head *), \ |
510 | (iter).end = &(lhead)->head, \ |
511 | (iter).cur = (iter).end->next ? (iter).end->next : (iter).end; \ |
512 | (iter).cur != (iter).end; \ |
513 | (iter).cur = (iter).cur->next) |
514 | |
515 | /* |
516 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. |
517 | * |
518 | * Access the current element with iter.cur. |
519 | * |
520 | * Iterations using this are only allowed to change the list at the current |
521 | * point of iteration. It is fine to delete the current node, but it is *not* |
522 | * fine to insert or delete adjacent nodes. |
523 | */ |
524 | #define dlist_foreach_modify(iter, lhead) \ |
525 | for (AssertVariableIsOfTypeMacro(iter, dlist_mutable_iter), \ |
526 | AssertVariableIsOfTypeMacro(lhead, dlist_head *), \ |
527 | (iter).end = &(lhead)->head, \ |
528 | (iter).cur = (iter).end->next ? (iter).end->next : (iter).end, \ |
529 | (iter).next = (iter).cur->next; \ |
530 | (iter).cur != (iter).end; \ |
531 | (iter).cur = (iter).next, (iter).next = (iter).cur->next) |
532 | |
533 | /* |
534 | * Iterate through the list in reverse order. |
535 | * |
536 | * It is *not* allowed to manipulate the list during iteration. |
537 | */ |
538 | #define dlist_reverse_foreach(iter, lhead) \ |
539 | for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \ |
540 | AssertVariableIsOfTypeMacro(lhead, dlist_head *), \ |
541 | (iter).end = &(lhead)->head, \ |
542 | (iter).cur = (iter).end->prev ? (iter).end->prev : (iter).end; \ |
543 | (iter).cur != (iter).end; \ |
544 | (iter).cur = (iter).cur->prev) |
545 | |
546 | |
547 | /* singly linked list implementation */ |
548 | |
549 | /* |
550 | * Initialize a singly linked list. |
551 | * Previous state will be thrown away without any cleanup. |
552 | */ |
553 | static inline void |
554 | slist_init(slist_head *head) |
555 | { |
556 | head->head.next = NULL; |
557 | } |
558 | |
559 | /* |
560 | * Is the list empty? |
561 | */ |
562 | static inline bool |
563 | slist_is_empty(slist_head *head) |
564 | { |
565 | slist_check(head); |
566 | |
567 | return head->head.next == NULL; |
568 | } |
569 | |
570 | /* |
571 | * Insert a node at the beginning of the list. |
572 | */ |
573 | static inline void |
574 | slist_push_head(slist_head *head, slist_node *node) |
575 | { |
576 | node->next = head->head.next; |
577 | head->head.next = node; |
578 | |
579 | slist_check(head); |
580 | } |
581 | |
582 | /* |
583 | * Insert a node after another *in the same list* |
584 | */ |
585 | static inline void |
586 | slist_insert_after(slist_node *after, slist_node *node) |
587 | { |
588 | node->next = after->next; |
589 | after->next = node; |
590 | } |
591 | |
592 | /* |
593 | * Remove and return the first node from a list (there must be one). |
594 | */ |
595 | static inline slist_node * |
596 | slist_pop_head_node(slist_head *head) |
597 | { |
598 | slist_node *node; |
599 | |
600 | Assert(!slist_is_empty(head)); |
601 | node = head->head.next; |
602 | head->head.next = node->next; |
603 | slist_check(head); |
604 | return node; |
605 | } |
606 | |
607 | /* |
608 | * Check whether 'node' has a following node. |
609 | */ |
610 | static inline bool |
611 | slist_has_next(slist_head *head, slist_node *node) |
612 | { |
613 | slist_check(head); |
614 | |
615 | return node->next != NULL; |
616 | } |
617 | |
618 | /* |
619 | * Return the next node in the list (there must be one). |
620 | */ |
621 | static inline slist_node * |
622 | slist_next_node(slist_head *head, slist_node *node) |
623 | { |
624 | Assert(slist_has_next(head, node)); |
625 | return node->next; |
626 | } |
627 | |
628 | /* internal support function to get address of head element's struct */ |
629 | static inline void * |
630 | slist_head_element_off(slist_head *head, size_t off) |
631 | { |
632 | Assert(!slist_is_empty(head)); |
633 | return (char *) head->head.next - off; |
634 | } |
635 | |
636 | /* |
637 | * Return the first node in the list (there must be one). |
638 | */ |
639 | static inline slist_node * |
640 | slist_head_node(slist_head *head) |
641 | { |
642 | return (slist_node *) slist_head_element_off(head, 0); |
643 | } |
644 | |
645 | /* |
646 | * Delete the list element the iterator currently points to. |
647 | * |
648 | * Caution: this modifies iter->cur, so don't use that again in the current |
649 | * loop iteration. |
650 | */ |
651 | static inline void |
652 | slist_delete_current(slist_mutable_iter *iter) |
653 | { |
654 | /* |
655 | * Update previous element's forward link. If the iteration is at the |
656 | * first list element, iter->prev will point to the list header's "head" |
657 | * field, so we don't need a special case for that. |
658 | */ |
659 | iter->prev->next = iter->next; |
660 | |
661 | /* |
662 | * Reset cur to prev, so that prev will continue to point to the prior |
663 | * valid list element after slist_foreach_modify() advances to the next. |
664 | */ |
665 | iter->cur = iter->prev; |
666 | } |
667 | |
668 | /* |
669 | * Return the containing struct of 'type' where 'membername' is the slist_node |
670 | * pointed at by 'ptr'. |
671 | * |
672 | * This is used to convert a slist_node * back to its containing struct. |
673 | */ |
674 | #define slist_container(type, membername, ptr) \ |
675 | (AssertVariableIsOfTypeMacro(ptr, slist_node *), \ |
676 | AssertVariableIsOfTypeMacro(((type *) NULL)->membername, slist_node), \ |
677 | ((type *) ((char *) (ptr) - offsetof(type, membername)))) |
678 | |
679 | /* |
680 | * Return the address of the first element in the list. |
681 | * |
682 | * The list must not be empty. |
683 | */ |
684 | #define slist_head_element(type, membername, lhead) \ |
685 | (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, slist_node), \ |
686 | (type *) slist_head_element_off(lhead, offsetof(type, membername))) |
687 | |
688 | /* |
689 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. |
690 | * |
691 | * Access the current element with iter.cur. |
692 | * |
693 | * It's allowed to modify the list while iterating, with the exception of |
694 | * deleting the iterator's current node; deletion of that node requires |
695 | * care if the iteration is to be continued afterward. (Doing so and also |
696 | * deleting or inserting adjacent list elements might misbehave; also, if |
697 | * the user frees the current node's storage, continuing the iteration is |
698 | * not safe.) |
699 | */ |
700 | #define slist_foreach(iter, lhead) \ |
701 | for (AssertVariableIsOfTypeMacro(iter, slist_iter), \ |
702 | AssertVariableIsOfTypeMacro(lhead, slist_head *), \ |
703 | (iter).cur = (lhead)->head.next; \ |
704 | (iter).cur != NULL; \ |
705 | (iter).cur = (iter).cur->next) |
706 | |
707 | /* |
708 | * Iterate through the list pointed at by 'lhead' storing the state in 'iter'. |
709 | * |
710 | * Access the current element with iter.cur. |
711 | * |
712 | * The only list modification allowed while iterating is to remove the current |
713 | * node via slist_delete_current() (*not* slist_delete()). Insertion or |
714 | * deletion of nodes adjacent to the current node would misbehave. |
715 | */ |
716 | #define slist_foreach_modify(iter, lhead) \ |
717 | for (AssertVariableIsOfTypeMacro(iter, slist_mutable_iter), \ |
718 | AssertVariableIsOfTypeMacro(lhead, slist_head *), \ |
719 | (iter).prev = &(lhead)->head, \ |
720 | (iter).cur = (iter).prev->next, \ |
721 | (iter).next = (iter).cur ? (iter).cur->next : NULL; \ |
722 | (iter).cur != NULL; \ |
723 | (iter).prev = (iter).cur, \ |
724 | (iter).cur = (iter).next, \ |
725 | (iter).next = (iter).next ? (iter).next->next : NULL) |
726 | |
727 | #endif /* ILIST_H */ |
728 | |