1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
|
#pragma once
/*
* Circular Intrusive Double Linked List Collection in ISO-C11
*
* This implements a generic circular double linked list. List entries must
* embed the CList object, which provides pointers to the next and previous
* element. Insertion and removal can be done in O(1) due to the double links.
* Furthermore, the list is circular, thus allows access to front/tail in O(1)
* as well, even if you only have a single head pointer (which is not how the
* list is usually operated, though).
*
* Note that you are free to use the list implementation without a head
* pointer. However, usual operation uses a single CList object as head, which
* is itself linked in the list and as such must be identified as list head.
* This allows very simply list operations and avoids a lot of special cases.
* Most importantly, you can unlink entries without requiring a head pointer.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
typedef struct CList CList;
/**
* struct CList - Entry of a circular double linked list
* @next: next entry
* @prev: previous entry
*
* Each entry in a list must embed a CList object. This object contains
* pointers to its next and previous elements, which can be freely accessed by
* the API user at any time. Note that the list is circular, and the list head
* is linked in the list as well.
*
* The list head must be initialized via C_LIST_INIT before use. There is no
* reason to initialize entry objects before linking them. However, if you need
* a boolean state that tells you whether the entry is linked or not, you should
* initialize the entry via C_LIST_INIT as well.
*/
struct CList {
CList *next;
CList *prev;
};
#define C_LIST_INIT(_var) { .next = &(_var), .prev = &(_var) }
/**
* c_list_init() - initialize list entry
* @what: list entry to initialize
*/
static inline void c_list_init(CList *what) {
*what = (CList)C_LIST_INIT(*what);
}
/**
* c_list_entry() - get parent container of list entry
* @_what: list entry, or NULL
* @_t: type of parent container
* @_m: member name of list entry in @_t
*
* If the list entry @_what is embedded into a surrounding structure, this will
* turn the list entry pointer @_what into a pointer to the parent container
* (using offsetof(3), or sometimes called container_of(3)).
*
* If @_what is NULL, this will also return NULL.
*
* Return: Pointer to parent container, or NULL.
*/
#define c_list_entry(_what, _t, _m) \
((_t *)(void *)(((unsigned long)(void *)(_what) ?: \
offsetof(_t, _m)) - offsetof(_t, _m)))
/**
* c_list_is_linked() - check whether an entry is linked
* @what: entry to check, or NULL
*
* Return: True if @what is linked in a list, false if not.
*/
static inline _Bool c_list_is_linked(const CList *what) {
return what && what->next != what;
}
/**
* c_list_is_empty() - check whether a list is empty
* @list: list to check, or NULL
*
* This is the same as !c_list_is_linked().
*
* Return: True if @list is empty, false if not.
*/
static inline _Bool c_list_is_empty(const CList *list) {
return !c_list_is_linked(list);
}
/**
* c_list_link_before() - link entry into list
* @where: linked list entry used as anchor
* @what: entry to link
*
* This links @what directly in front of @where. @where can either be a list
* head or any entry in the list.
*
* If @where points to the list head, this effectively links @what as new tail
* element. Hence, the macro c_list_link_tail() is an alias to this.
*
* @what is not inspected prior to being linked. Hence, it better not be linked
* into another list, or the other list will be corrupted.
*/
static inline void c_list_link_before(CList *where, CList *what) {
CList *prev = where->prev, *next = where;
next->prev = what;
what->next = next;
what->prev = prev;
prev->next = what;
}
#define c_list_link_tail(_list, _what) c_list_link_before((_list), (_what))
/**
* c_list_link_after() - link entry into list
* @where: linked list entry used as anchor
* @what: entry to link
*
* This links @what directly after @where. @where can either be a list head or
* any entry in the list.
*
* If @where points to the list head, this effectively links @what as new front
* element. Hence, the macro c_list_link_front() is an alias to this.
*
* @what is not inspected prior to being linked. Hence, it better not be linked
* into another list, or the other list will be corrupted.
*/
static inline void c_list_link_after(CList *where, CList *what) {
CList *prev = where, *next = where->next;
next->prev = what;
what->next = next;
what->prev = prev;
prev->next = what;
}
#define c_list_link_front(_list, _what) c_list_link_after((_list), (_what))
/**
* c_list_unlink_stale() - unlink element from list
* @what: element to unlink
*
* This unlinks @what. If @what was initialized via C_LIST_INIT(), it has no
* effect. If @what was never linked, nor initialized, behavior is undefined.
*
* Note that this does not modify @what. It just modifies the previous and next
* elements in the list to no longer reference @what. If you want to make sure
* @what is re-initialized after removal, use c_list_unlink().
*/
static inline void c_list_unlink_stale(CList *what) {
CList *prev = what->prev, *next = what->next;
next->prev = prev;
prev->next = next;
}
/**
* c_list_unlink() - unlink element from list and re-initialize
* @what: element to unlink
*
* This is like c_list_unlink_stale() but re-initializes @what after removal.
*/
static inline void c_list_unlink(CList *what) {
/* condition is not needed, but avoids STOREs in fast-path */
if (c_list_is_linked(what)) {
c_list_unlink_stale(what);
*what = (CList)C_LIST_INIT(*what);
}
}
/**
* c_list_swap() - exchange the contents of two lists
* @list1: the list to operate on
* @list2: the list to operate on
*
* This replaces the contents of the list @list1 with the contents
* of @list2, and vice versa.
*/
static inline void c_list_swap(CList *list1, CList *list2) {
CList t;
/* make neighbors of list1 point to list2, and vice versa */
t = *list1;
t.next->prev = list2;
t.prev->next = list2;
t = *list2;
t.next->prev = list1;
t.prev->next = list1;
/* swap list1 and list2 now that their neighbors were fixed up */
t = *list1;
*list1 = *list2;
*list2 = t;
}
/**
* c_list_splice() - splice one list into another
* @target: the list to splice into
* @source: the list to splice
*
* This removes all the entries from @source and splice them into @target.
* The order of the two lists is preserved and the source is appended
* to the end of target.
*
* On return, the source list will be empty.
*/
static inline void c_list_splice(CList *target, CList *source) {
if (!c_list_is_empty(source)) {
/* attach the front of @source to the tail of @target */
source->next->prev = target->prev;
target->prev->next = source->next;
/* attach the tail of @source to the front of @target */
source->prev->next = target;
target->prev = source->prev;
/* clear source */
*source = (CList)C_LIST_INIT(*source);
}
}
/**
* c_list_first() - return pointer to first element, or NULL if empty
* @list: list to operate on, or NULL
*
* This returns a pointer to the first element, or NULL if empty. This never
* returns a pointer to the list head.
*
* Return: Pointer to first list element, or NULL if empty.
*/
static inline CList *c_list_first(CList *list) {
return c_list_is_empty(list) ? NULL : list->next;
}
/**
* c_list_last() - return pointer to last element, or NULL if empty
* @list: list to operate on, or NULL
*
* This returns a pointer to the last element, or NULL if empty. This never
* returns a pointer to the list head.
*
* Return: Pointer to last list element, or NULL if empty.
*/
static inline CList *c_list_last(CList *list) {
return c_list_is_empty(list) ? NULL : list->prev;
}
/**
* c_list_first_entry() - return pointer to first entry, or NULL if empty
* @_list: list to operate on, or NULL
* @_t: type of list entries
* @_m: name of CList member in @_t
*
* This is like c_list_first(), but also applies c_list_entry() on the result.
*
* Return: Pointer to first list entry, or NULL if empty.
*/
#define c_list_first_entry(_list, _t, _m) \
c_list_entry(c_list_first(_list), _t, _m)
/**
* c_list_last_entry() - return pointer to last entry, or NULL if empty
* @_list: list to operate on, or NULL
* @_t: type of list entries
* @_m: name of CList member in @_t
*
* This is like c_list_last(), but also applies c_list_entry() on the result.
*
* Return: Pointer to last list entry, or NULL if empty.
*/
#define c_list_last_entry(_list, _t, _m) \
c_list_entry(c_list_last(_list), _t, _m)
/**
* c_list_for_each*() - iterators
*
* The c_list_for_each*() macros provide simple for-loop wrappers to iterate
* a linked list. They come in a set of flavours:
*
* - "entry": This combines c_list_entry() with the loop iterator, so the
* iterator always has the type of the surrounding object, rather
* than CList.
*
* - "safe": The loop iterator always keeps track of the next element to
* visit. This means, you can safely modify the current element,
* while retaining loop-integrity.
* You still must not touch any other entry of the list. Otherwise,
* the loop-iterator will be corrupted.
*
* - "continue": Rather than starting the iteration at the front of the list,
* use the current value of the iterator as starting position.
* Note that the first loop iteration will be the following
* element, not the given element.
*
* - "unlink": This unlinks the current element from the list before the loop
* code is run. Note that this only does a partial unlink, since
* it assumes the entire list will be unlinked. You must not
* break out of the loop, or the list will be in an inconsistent
* state.
*/
#define c_list_for_each(_iter, _list) \
for (_iter = (_list)->next; \
(_iter) != (_list); \
_iter = (_iter)->next)
#define c_list_for_each_entry(_iter, _list, _m) \
for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m); \
&(_iter)->_m != (_list); \
_iter = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m))
#define c_list_for_each_safe(_iter, _safe, _list) \
for (_iter = (_list)->next, _safe = (_iter)->next; \
(_iter) != (_list); \
_iter = (_safe), _safe = (_safe)->next)
#define c_list_for_each_entry_safe(_iter, _safe, _list, _m) \
for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m), \
_safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \
&(_iter)->_m != (_list); \
_iter = (_safe), \
_safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m)) \
#define c_list_for_each_continue(_iter, _list) \
for (_iter = (_iter) ? (_iter)->next : (_list)->next; \
(_iter) != (_list); \
_iter = (_iter)->next)
#define c_list_for_each_entry_continue(_iter, _list, _m) \
for (_iter = c_list_entry((_iter) ? (_iter)->_m.next : (_list)->next, \
__typeof__(*_iter), \
_m); \
&(_iter)->_m != (_list); \
_iter = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m))
#define c_list_for_each_safe_continue(_iter, _safe, _list) \
for (_iter = (_iter) ? (_iter)->next : (_list)->next, \
_safe = (_iter)->next; \
(_iter) != (_list); \
_iter = (_safe), _safe = (_safe)->next)
#define c_list_for_each_entry_safe_continue(_iter, _safe, _list, _m) \
for (_iter = c_list_entry((_iter) ? (_iter)->_m.next : (_list)->next, \
__typeof__(*_iter), \
_m), \
_safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \
&(_iter)->_m != (_list); \
_iter = (_safe), \
_safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m)) \
#define c_list_for_each_safe_unlink(_iter, _safe, _list) \
for (_iter = (_list)->next, _safe = (_iter)->next; \
((*_iter = (CList)C_LIST_INIT(*_iter)), (_iter) != (_list)); \
_iter = (_safe), _safe = (_safe)->next)
#define c_list_for_each_entry_safe_unlink(_iter, _safe, _list, _m) \
for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m), \
_safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \
(((_iter)->_m = (CList)C_LIST_INIT((_iter)->_m)), \
&(_iter)->_m != (_list)); \
_iter = (_safe), \
_safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m)) \
/**
* c_list_flush() - flush all entries from a list
* @list: list to flush
*
* This unlinks all entries from the given list @list and reinitializes their
* link-nodes via C_LIST_INIT().
*
* Note that the entries are not modified in any other way, nor is their memory
* released. This function just unlinks them and resets all the list nodes. It
* is particularly useful with temporary lists on the stack in combination with
* the GCC-extension __attribute__((__cleanup__(arg))).
*/
static inline void c_list_flush(CList *list) {
CList *iter, *safe;
c_list_for_each_safe_unlink(iter, safe, list)
/* empty */ ;
}
/**
* c_list_length() - return number of linked entries, excluding the head
* @list: list to operate on
*
* Returns the number of entries in the list, excluding the list head @list.
* That is, for a list that is empty according to c_list_is_empty(), the
* returned length is 0. This requires to iterate the list and has thus O(n)
* runtime.
*
* Note that this function is meant for debugging purposes only. If you need
* the list size during normal operation, you should maintain a counter
* separately.
*
* Return: Number of items in @list.
*/
static inline unsigned long c_list_length(const CList *list) {
unsigned long n = 0;
const CList *iter;
c_list_for_each(iter, list)
++n;
return n;
}
/**
* c_list_contains() - check whether an entry is linked in a certain list
* @list: list to operate on
* @what: entry to look for
*
* This checks whether @what is linked into @list. This requires a linear
* search through the list, as such runs in O(n). Note that the list-head is
* considered part of the list, and hence this returns true if @what equals
* @list.
*
* Note that this function is meant for debugging purposes, and consistency
* checks. You should always be aware whether your objects are linked in a
* specific list.
*
* Return: True if @what is in @list, false otherwise.
*/
static inline _Bool c_list_contains(const CList *list, const CList *what) {
const CList *iter;
c_list_for_each(iter, list)
if (what == iter)
return 1;
return what == list;
}
#ifdef __cplusplus
}
#endif
|