First version
[3rdparty/ote_partner/tlk.git] / include / list.h
1 /*
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 <stddef.h>
27 #include <stdbool.h>
28
29 #define containerof(ptr, type, member) \
30         ((type *)((addr_t)(ptr) - offsetof(type, member)))
31
32 struct list_node {
33         struct list_node *prev;
34         struct list_node *next;
35 };
36
37 #define LIST_INITIAL_VALUE(list) { &(list), &(list) }
38
39 static inline void list_initialize(struct list_node *list)
40 {
41         list->prev = list->next = list;
42 }
43
44 static inline void list_clear_node(struct list_node *item)
45 {
46         item->prev = item->next = 0;
47 }
48
49 static inline bool list_in_list(struct list_node *item)
50 {
51         if (item->prev == 0 && item->next == 0)
52                 return false;
53         else
54                 return true;
55 }
56
57 static inline void list_add_head(struct list_node *list, struct list_node *item)
58 {
59         item->next = list->next;
60         item->prev = list;
61         list->next->prev = item;
62         list->next = item;
63 }
64
65 #define list_add_after(entry, new_entry) list_add_head(entry, new_entry)
66
67 static inline void list_add_tail(struct list_node *list, struct list_node *item)
68 {
69         item->prev = list->prev;
70         item->next = list;
71         list->prev->next = item;
72         list->prev = item;
73 }
74
75 #define list_add_before(entry, new_entry) list_add_tail(entry, new_entry)
76
77 static inline void list_delete(struct list_node *item)
78 {
79         item->next->prev = item->prev;
80         item->prev->next = item->next;
81         item->prev = item->next = 0;
82 }
83
84 static inline struct list_node* list_remove_head(struct list_node *list)
85 {
86         if(list->next != list) {
87                 struct list_node *item = list->next;
88                 list_delete(item);
89                 return item;
90         } else {
91                 return NULL;
92         }
93 }
94
95 #define list_remove_head_type(list, type, element) ({\
96     struct list_node *__nod = list_remove_head(list);\
97     type *__t;\
98     if(__nod)\
99         __t = containerof(__nod, type, element);\
100     else\
101         __t = (type *)0;\
102     __t;\
103 })
104
105 static inline struct list_node* list_remove_tail(struct list_node *list)
106 {
107         if(list->prev != list) {
108                 struct list_node *item = list->prev;
109                 list_delete(item);
110                 return item;
111         } else {
112                 return NULL;
113         }
114 }
115
116 #define list_remove_tail_type(list, type, element) ({\
117     struct list_node *__nod = list_remove_tail(list);\
118     type *__t;\
119     if(__nod)\
120         __t = containerof(__nod, type, element);\
121     else\
122         __t = (type *)0;\
123     __t;\
124 })
125
126 static inline struct list_node* list_peek_head(struct list_node *list)
127 {
128         if(list->next != list) {
129                 return list->next;
130         } else {
131                 return NULL;
132         }       
133 }
134
135 #define list_peek_head_type(list, type, element) ({\
136     struct list_node *__nod = list_peek_head(list);\
137     type *__t;\
138     if(__nod)\
139         __t = containerof(__nod, type, element);\
140     else\
141         __t = (type *)0;\
142     __t;\
143 })
144
145 static inline struct list_node* list_peek_tail(struct list_node *list)
146 {
147         if(list->prev != list) {
148                 return list->prev;
149         } else {
150                 return NULL;
151         }       
152 }
153
154 #define list_peek_tail_type(list, type, element) ({\
155     struct list_node *__nod = list_peek_tail(list);\
156     type *__t;\
157     if(__nod)\
158         __t = containerof(__nod, type, element);\
159     else\
160         __t = (type *)0;\
161     __t;\
162 })
163
164 static inline struct list_node* list_prev(struct list_node *list, struct list_node *item)
165 {
166         if(item->prev != list)
167                 return item->prev;
168         else
169                 return NULL;
170 }
171
172 #define list_prev_type(list, item, type, element) ({\
173     struct list_node *__nod = list_prev(list, item);\
174     type *__t;\
175     if(__nod)\
176         __t = containerof(__nod, type, element);\
177     else\
178         __t = (type *)0;\
179     __t;\
180 })
181
182 static inline struct list_node* list_prev_wrap(struct list_node *list, struct list_node *item)
183 {
184         if(item->prev != list)
185                 return item->prev;
186         else if(item->prev->prev != list)
187                 return item->prev->prev;
188         else
189                 return NULL;
190 }
191
192 #define list_prev_wrap_type(list, item, type, element) ({\
193     struct list_node *__nod = list_prev_wrap(list, item);\
194     type *__t;\
195     if(__nod)\
196         __t = containerof(__nod, type, element);\
197     else\
198         __t = (type *)0;\
199     __t;\
200 })
201
202 static inline struct list_node* list_next(struct list_node *list, struct list_node *item)
203 {
204         if(item->next != list)
205                 return item->next;
206         else
207                 return NULL;
208 }
209
210 #define list_next_type(list, item, type, element) ({\
211     struct list_node *__nod = list_next(list, item);\
212     type *__t;\
213     if(__nod)\
214         __t = containerof(__nod, type, element);\
215     else\
216         __t = (type *)0;\
217     __t;\
218 })
219
220 static inline struct list_node* list_next_wrap(struct list_node *list, struct list_node *item)
221 {
222         if(item->next != list)
223                 return item->next;
224         else if(item->next->next != list)
225                 return item->next->next;
226         else
227                 return NULL;
228 }
229
230 #define list_next_wrap_type(list, item, type, element) ({\
231     struct list_node *__nod = list_next_wrap(list, item);\
232     type *__t;\
233     if(__nod)\
234         __t = containerof(__nod, type, element);\
235     else\
236         __t = (type *)0;\
237     __t;\
238 })
239
240 // iterates over the list, node should be struct list_node*
241 #define list_for_every(list, node) \
242         for(node = (list)->next; node != (list); node = node->next)
243
244 // iterates over the list in a safe way for deletion of current node
245 // node and temp_node should be struct list_node*
246 #define list_for_every_safe(list, node, temp_node) \
247         for(node = (list)->next, temp_node = (node)->next;\
248         node != (list);\
249         node = temp_node, temp_node = (node)->next)
250
251 // iterates over the list, entry should be the container structure type *
252 #define list_for_every_entry(list, entry, type, member) \
253         for((entry) = containerof((list)->next, type, member);\
254                 &(entry)->member != (list);\
255                 (entry) = containerof((entry)->member.next, type, member))
256
257 // iterates over the list in a safe way for deletion of current node
258 // entry and temp_entry should be the container structure type *
259 #define list_for_every_entry_safe(list, entry, temp_entry, type, member) \
260         for(entry = containerof((list)->next, type, member),\
261                 temp_entry = containerof((entry)->member.next, type, member);\
262                 &(entry)->member != (list);\
263                 entry = temp_entry, temp_entry = containerof((temp_entry)->member.next, type, member))
264
265 static inline bool list_is_empty(struct list_node *list)
266 {
267         return (list->next == list) ? true : false;
268 }
269
270 #endif