]>
Commit | Line | Data |
---|---|---|
663996b3 MS |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
3 | #pragma once | |
4 | ||
5 | /*** | |
6 | This file is part of systemd. | |
7 | ||
8 | Copyright 2010 Lennart Poettering | |
9 | ||
10 | systemd is free software; you can redistribute it and/or modify it | |
11 | under the terms of the GNU Lesser General Public License as published by | |
12 | the Free Software Foundation; either version 2.1 of the License, or | |
13 | (at your option) any later version. | |
14 | ||
15 | systemd is distributed in the hope that it will be useful, but | |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | Lesser General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU Lesser General Public License | |
21 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
22 | ***/ | |
23 | ||
24 | /* The head of the linked list. Use this in the structure that shall | |
25 | * contain the head of the linked list */ | |
26 | #define LIST_HEAD(t,name) \ | |
27 | t *name | |
28 | ||
29 | /* The pointers in the linked list's items. Use this in the item structure */ | |
30 | #define LIST_FIELDS(t,name) \ | |
31 | t *name##_next, *name##_prev | |
32 | ||
33 | /* Initialize the list's head */ | |
60f067b4 | 34 | #define LIST_HEAD_INIT(head) \ |
663996b3 MS |
35 | do { \ |
36 | (head) = NULL; } \ | |
37 | while(false) | |
38 | ||
39 | /* Initialize a list item */ | |
60f067b4 | 40 | #define LIST_INIT(name,item) \ |
663996b3 | 41 | do { \ |
60f067b4 | 42 | typeof(*(item)) *_item = (item); \ |
663996b3 MS |
43 | assert(_item); \ |
44 | _item->name##_prev = _item->name##_next = NULL; \ | |
45 | } while(false) | |
46 | ||
47 | /* Prepend an item to the list */ | |
60f067b4 | 48 | #define LIST_PREPEND(name,head,item) \ |
663996b3 | 49 | do { \ |
60f067b4 | 50 | typeof(*(head)) **_head = &(head), *_item = (item); \ |
663996b3 MS |
51 | assert(_item); \ |
52 | if ((_item->name##_next = *_head)) \ | |
53 | _item->name##_next->name##_prev = _item; \ | |
54 | _item->name##_prev = NULL; \ | |
55 | *_head = _item; \ | |
56 | } while(false) | |
57 | ||
58 | /* Remove an item from the list */ | |
60f067b4 | 59 | #define LIST_REMOVE(name,head,item) \ |
663996b3 | 60 | do { \ |
60f067b4 | 61 | typeof(*(head)) **_head = &(head), *_item = (item); \ |
663996b3 MS |
62 | assert(_item); \ |
63 | if (_item->name##_next) \ | |
64 | _item->name##_next->name##_prev = _item->name##_prev; \ | |
65 | if (_item->name##_prev) \ | |
66 | _item->name##_prev->name##_next = _item->name##_next; \ | |
67 | else { \ | |
68 | assert(*_head == _item); \ | |
69 | *_head = _item->name##_next; \ | |
70 | } \ | |
71 | _item->name##_next = _item->name##_prev = NULL; \ | |
72 | } while(false) | |
73 | ||
74 | /* Find the head of the list */ | |
60f067b4 | 75 | #define LIST_FIND_HEAD(name,item,head) \ |
663996b3 | 76 | do { \ |
60f067b4 JS |
77 | typeof(*(item)) *_item = (item); \ |
78 | if (!_item) \ | |
79 | (head) = NULL; \ | |
80 | else { \ | |
81 | while (_item->name##_prev) \ | |
82 | _item = _item->name##_prev; \ | |
83 | (head) = _item; \ | |
84 | } \ | |
663996b3 MS |
85 | } while (false) |
86 | ||
14228c0d | 87 | /* Find the tail of the list */ |
60f067b4 | 88 | #define LIST_FIND_TAIL(name,item,tail) \ |
663996b3 | 89 | do { \ |
60f067b4 JS |
90 | typeof(*(item)) *_item = (item); \ |
91 | if (!_item) \ | |
92 | (tail) = NULL; \ | |
93 | else { \ | |
94 | while (_item->name##_next) \ | |
95 | _item = _item->name##_next; \ | |
96 | (tail) = _item; \ | |
97 | } \ | |
663996b3 MS |
98 | } while (false) |
99 | ||
100 | /* Insert an item after another one (a = where, b = what) */ | |
60f067b4 | 101 | #define LIST_INSERT_AFTER(name,head,a,b) \ |
663996b3 | 102 | do { \ |
60f067b4 | 103 | typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ |
663996b3 MS |
104 | assert(_b); \ |
105 | if (!_a) { \ | |
106 | if ((_b->name##_next = *_head)) \ | |
107 | _b->name##_next->name##_prev = _b; \ | |
108 | _b->name##_prev = NULL; \ | |
109 | *_head = _b; \ | |
110 | } else { \ | |
111 | if ((_b->name##_next = _a->name##_next)) \ | |
112 | _b->name##_next->name##_prev = _b; \ | |
113 | _b->name##_prev = _a; \ | |
114 | _a->name##_next = _b; \ | |
115 | } \ | |
116 | } while(false) | |
117 | ||
118 | #define LIST_JUST_US(name,item) \ | |
119 | (!(item)->name##_prev && !(item)->name##_next) \ | |
120 | ||
121 | #define LIST_FOREACH(name,i,head) \ | |
122 | for ((i) = (head); (i); (i) = (i)->name##_next) | |
123 | ||
124 | #define LIST_FOREACH_SAFE(name,i,n,head) \ | |
125 | for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n)) | |
126 | ||
127 | #define LIST_FOREACH_BEFORE(name,i,p) \ | |
128 | for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev) | |
129 | ||
130 | #define LIST_FOREACH_AFTER(name,i,p) \ | |
131 | for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next) | |
14228c0d MB |
132 | |
133 | /* Loop starting from p->next until p->prev. | |
134 | p can be adjusted meanwhile. */ | |
135 | #define LIST_LOOP_BUT_ONE(name,i,head,p) \ | |
136 | for ((i) = (p)->name##_next ? (p)->name##_next : (head); \ | |
137 | (i) != (p); \ | |
138 | (i) = (i)->name##_next ? (i)->name##_next : (head)) |