blob: 96cd0d4381b0164f91bfb399c684d597738c4112 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#ifndef __LIST_H
24#define __LIST_H
25
26#include <sys/types.h>
27
28#define containerof(ptr, type, member) \
29 ((type *)((addr_t)(ptr) - offsetof(type, member)))
30
31struct list_node {
32 struct list_node *prev;
33 struct list_node *next;
34};
35
36#define LIST_INITIAL_VALUE(list) { &(list), &(list) }
37
38static inline void list_initialize(struct list_node *list)
39{
40 list->prev = list->next = list;
41}
42
43static inline void list_clear_node(struct list_node *item)
44{
45 item->prev = item->next = 0;
46}
47
48static inline bool list_in_list(struct list_node *item)
49{
50 if (item->prev == 0 && item->next == 0)
51 return false;
52 else
53 return true;
54}
55
56static inline void list_add_head(struct list_node *list, struct list_node *item)
57{
58 item->next = list->next;
59 item->prev = list;
60 list->next->prev = item;
61 list->next = item;
62}
63
64#define list_add_after(entry, new_entry) list_add_head(entry, new_entry)
65
66static inline void list_add_tail(struct list_node *list, struct list_node *item)
67{
68 item->prev = list->prev;
69 item->next = list;
70 list->prev->next = item;
71 list->prev = item;
72}
73
74#define list_add_before(entry, new_entry) list_add_tail(entry, new_entry)
75
76static inline void list_delete(struct list_node *item)
77{
78 item->next->prev = item->prev;
79 item->prev->next = item->next;
80 item->prev = item->next = 0;
81}
82
83static inline struct list_node* list_remove_head(struct list_node *list)
84{
85 if(list->next != list) {
86 struct list_node *item = list->next;
87 list_delete(item);
88 return item;
89 } else {
90 return NULL;
91 }
92}
93
94#define list_remove_head_type(list, type, element) ({\
95 struct list_node *__nod = list_remove_head(list);\
96 type *__t;\
97 if(__nod)\
98 __t = containerof(__nod, type, element);\
99 else\
100 __t = (type *)0;\
101 __t;\
102})
103
104static inline struct list_node* list_remove_tail(struct list_node *list)
105{
106 if(list->prev != list) {
107 struct list_node *item = list->prev;
108 list_delete(item);
109 return item;
110 } else {
111 return NULL;
112 }
113}
114
115#define list_remove_tail_type(list, type, element) ({\
116 struct list_node *__nod = list_remove_tail(list);\
117 type *__t;\
118 if(__nod)\
119 __t = containerof(__nod, type, element);\
120 else\
121 __t = (type *)0;\
122 __t;\
123})
124
125static inline struct list_node* list_peek_head(struct list_node *list)
126{
127 if(list->next != list) {
128 return list->next;
129 } else {
130 return NULL;
131 }
132}
133
134#define list_peek_head_type(list, type, element) ({\
135 struct list_node *__nod = list_peek_head(list);\
136 type *__t;\
137 if(__nod)\
138 __t = containerof(__nod, type, element);\
139 else\
140 __t = (type *)0;\
141 __t;\
142})
143
144static inline struct list_node* list_peek_tail(struct list_node *list)
145{
146 if(list->prev != list) {
147 return list->prev;
148 } else {
149 return NULL;
150 }
151}
152
153#define list_peek_tail_type(list, type, element) ({\
154 struct list_node *__nod = list_peek_tail(list);\
155 type *__t;\
156 if(__nod)\
157 __t = containerof(__nod, type, element);\
158 else\
159 __t = (type *)0;\
160 __t;\
161})
162
163static inline struct list_node* list_prev(struct list_node *list, struct list_node *item)
164{
165 if(item->prev != list)
166 return item->prev;
167 else
168 return NULL;
169}
170
171#define list_prev_type(list, item, type, element) ({\
172 struct list_node *__nod = list_prev(list, item);\
173 type *__t;\
174 if(__nod)\
175 __t = containerof(__nod, type, element);\
176 else\
177 __t = (type *)0;\
178 __t;\
179})
180
181static inline struct list_node* list_prev_wrap(struct list_node *list, struct list_node *item)
182{
183 if(item->prev != list)
184 return item->prev;
185 else if(item->prev->prev != list)
186 return item->prev->prev;
187 else
188 return NULL;
189}
190
191#define list_prev_wrap_type(list, item, type, element) ({\
192 struct list_node *__nod = list_prev_wrap(list, item);\
193 type *__t;\
194 if(__nod)\
195 __t = containerof(__nod, type, element);\
196 else\
197 __t = (type *)0;\
198 __t;\
199})
200
201static inline struct list_node* list_next(struct list_node *list, struct list_node *item)
202{
203 if(item->next != list)
204 return item->next;
205 else
206 return NULL;
207}
208
209#define list_next_type(list, item, type, element) ({\
210 struct list_node *__nod = list_next(list, item);\
211 type *__t;\
212 if(__nod)\
213 __t = containerof(__nod, type, element);\
214 else\
215 __t = (type *)0;\
216 __t;\
217})
218
219static inline struct list_node* list_next_wrap(struct list_node *list, struct list_node *item)
220{
221 if(item->next != list)
222 return item->next;
223 else if(item->next->next != list)
224 return item->next->next;
225 else
226 return NULL;
227}
228
229#define list_next_wrap_type(list, item, type, element) ({\
230 struct list_node *__nod = list_next_wrap(list, item);\
231 type *__t;\
232 if(__nod)\
233 __t = containerof(__nod, type, element);\
234 else\
235 __t = (type *)0;\
236 __t;\
237})
238
239// iterates over the list, node should be struct list_node*
240#define list_for_every(list, node) \
241 for(node = (list)->next; node != (list); node = node->next)
242
243// iterates over the list in a safe way for deletion of current node
244// node and temp_node should be struct list_node*
245#define list_for_every_safe(list, node, temp_node) \
246 for(node = (list)->next, temp_node = (node)->next;\
247 node != (list);\
248 node = temp_node, temp_node = (node)->next)
249
250// iterates over the list, entry should be the container structure type *
251#define list_for_every_entry(list, entry, type, member) \
252 for((entry) = containerof((list)->next, type, member);\
253 &(entry)->member != (list);\
254 (entry) = containerof((entry)->member.next, type, member))
255
256// iterates over the list in a safe way for deletion of current node
257// entry and temp_entry should be the container structure type *
258#define list_for_every_entry_safe(list, entry, temp_entry, type, member) \
259 for(entry = containerof((list)->next, type, member),\
260 temp_entry = containerof((entry)->member.next, type, member);\
261 &(entry)->member != (list);\
262 entry = temp_entry, temp_entry = containerof((temp_entry)->member.next, type, member))
263
264static inline bool list_is_empty(struct list_node *list)
265{
266 return (list->next == list) ? true : false;
267}
268
269#endif