chiark / gitweb /
tree-wide: remove Lennart's copyright lines
[elogind.git] / src / basic / list.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 #pragma once
3
4 /* The head of the linked list. Use this in the structure that shall
5  * contain the head of the linked list */
6 #define LIST_HEAD(t,name)                                               \
7         t *name
8
9 /* The pointers in the linked list's items. Use this in the item structure */
10 #define LIST_FIELDS(t,name)                                             \
11         t *name##_next, *name##_prev
12
13 /* Initialize the list's head */
14 #define LIST_HEAD_INIT(head)                                            \
15         do {                                                            \
16                 (head) = NULL; }                                        \
17         while (false)
18
19 /* Initialize a list item */
20 #define LIST_INIT(name,item)                                            \
21         do {                                                            \
22                 typeof(*(item)) *_item = (item);                        \
23                 assert(_item);                                          \
24                 _item->name##_prev = _item->name##_next = NULL;         \
25         } while (false)
26
27 /* Prepend an item to the list */
28 #define LIST_PREPEND(name,head,item)                                    \
29         do {                                                            \
30                 typeof(*(head)) **_head = &(head), *_item = (item);     \
31                 assert(_item);                                          \
32                 if ((_item->name##_next = *_head))                      \
33                         _item->name##_next->name##_prev = _item;        \
34                 _item->name##_prev = NULL;                              \
35                 *_head = _item;                                         \
36         } while (false)
37
38 /* Append an item to the list */
39 #define LIST_APPEND(name,head,item)                                     \
40         do {                                                            \
41                 typeof(*(head)) *_tail;                                 \
42                 LIST_FIND_TAIL(name,head,_tail);                        \
43                 LIST_INSERT_AFTER(name,head,_tail,item);                \
44         } while (false)
45
46 /* Remove an item from the list */
47 #define LIST_REMOVE(name,head,item)                                     \
48         do {                                                            \
49                 typeof(*(head)) **_head = &(head), *_item = (item);     \
50                 assert(_item);                                          \
51                 if (_item->name##_next)                                 \
52                         _item->name##_next->name##_prev = _item->name##_prev; \
53                 if (_item->name##_prev)                                 \
54                         _item->name##_prev->name##_next = _item->name##_next; \
55                 else {                                                  \
56                         assert(*_head == _item);                        \
57                         *_head = _item->name##_next;                    \
58                 }                                                       \
59                 _item->name##_next = _item->name##_prev = NULL;         \
60         } while (false)
61
62 /* Find the head of the list */
63 #define LIST_FIND_HEAD(name,item,head)                                  \
64         do {                                                            \
65                 typeof(*(item)) *_item = (item);                        \
66                 if (!_item)                                             \
67                         (head) = NULL;                                  \
68                 else {                                                  \
69                         while (_item->name##_prev)                      \
70                                 _item = _item->name##_prev;             \
71                         (head) = _item;                                 \
72                 }                                                       \
73         } while (false)
74
75 /* Find the tail of the list */
76 #define LIST_FIND_TAIL(name,item,tail)                                  \
77         do {                                                            \
78                 typeof(*(item)) *_item = (item);                        \
79                 if (!_item)                                             \
80                         (tail) = NULL;                                  \
81                 else {                                                  \
82                         while (_item->name##_next)                      \
83                                 _item = _item->name##_next;             \
84                         (tail) = _item;                                 \
85                 }                                                       \
86         } while (false)
87
88 /* Insert an item after another one (a = where, b = what) */
89 #define LIST_INSERT_AFTER(name,head,a,b)                                \
90         do {                                                            \
91                 typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
92                 assert(_b);                                             \
93                 if (!_a) {                                              \
94                         if ((_b->name##_next = *_head))                 \
95                                 _b->name##_next->name##_prev = _b;      \
96                         _b->name##_prev = NULL;                         \
97                         *_head = _b;                                    \
98                 } else {                                                \
99                         if ((_b->name##_next = _a->name##_next))        \
100                                 _b->name##_next->name##_prev = _b;      \
101                         _b->name##_prev = _a;                           \
102                         _a->name##_next = _b;                           \
103                 }                                                       \
104         } while (false)
105
106 /* Insert an item before another one (a = where, b = what) */
107 #define LIST_INSERT_BEFORE(name,head,a,b)                               \
108         do {                                                            \
109                 typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
110                 assert(_b);                                             \
111                 if (!_a) {                                              \
112                         if (!*_head) {                                  \
113                                 _b->name##_next = NULL;                 \
114                                 _b->name##_prev = NULL;                 \
115                                 *_head = _b;                            \
116                         } else {                                        \
117                                 typeof(*(head)) *_tail = (head);        \
118                                 while (_tail->name##_next)              \
119                                         _tail = _tail->name##_next;     \
120                                 _b->name##_next = NULL;                 \
121                                 _b->name##_prev = _tail;                \
122                                 _tail->name##_next = _b;                \
123                         }                                               \
124                 } else {                                                \
125                         if ((_b->name##_prev = _a->name##_prev))        \
126                                 _b->name##_prev->name##_next = _b;      \
127                         else                                            \
128                                 *_head = _b;                            \
129                         _b->name##_next = _a;                           \
130                         _a->name##_prev = _b;                           \
131                 }                                                       \
132         } while (false)
133
134 #define LIST_JUST_US(name,item)                                         \
135         (!(item)->name##_prev && !(item)->name##_next)                  \
136
137 #define LIST_FOREACH(name,i,head)                                       \
138         for ((i) = (head); (i); (i) = (i)->name##_next)
139
140 #define LIST_FOREACH_SAFE(name,i,n,head)                                \
141         for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
142
143 #define LIST_FOREACH_BEFORE(name,i,p)                                   \
144         for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev)
145
146 #define LIST_FOREACH_AFTER(name,i,p)                                    \
147         for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
148
149 /* Iterate through all the members of the list p is included in, but skip over p */
150 #define LIST_FOREACH_OTHERS(name,i,p)                                   \
151         for (({                                                         \
152                 (i) = (p);                                              \
153                 while ((i) && (i)->name##_prev)                         \
154                         (i) = (i)->name##_prev;                         \
155                 if ((i) == (p))                                         \
156                         (i) = (p)->name##_next;                         \
157              });                                                        \
158              (i);                                                       \
159              (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next)
160
161 /* Loop starting from p->next until p->prev.
162    p can be adjusted meanwhile. */
163 #define LIST_LOOP_BUT_ONE(name,i,head,p)                                \
164         for ((i) = (p)->name##_next ? (p)->name##_next : (head);        \
165              (i) != (p);                                                \
166              (i) = (i)->name##_next ? (i)->name##_next : (head))
167
168 #define LIST_IS_EMPTY(head)                                             \
169         (!(head))