1 #ifndef AOS_LIST_H
2 #define AOS_LIST_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 /*
9 * Get offset of a member variable.
10 *
11 * @param[in] type the type of the struct this is embedded in.
12 * @param[in] member the name of the variable within the struct.
13 */
14 #define aos_offsetof(type, member) ((size_t)&(((type *)0)->member))
15
16 /*
17 * Get the struct for this entry.
18 *
19 * @param[in] ptr the list head to take the element from.
20 * @param[in] type the type of the struct this is embedded in.
21 * @param[in] member the name of the variable within the struct.
22 */
23 #define aos_container_of(ptr, type, member) \
24 ((type *) ((char *) (ptr) - aos_offsetof(type, member)))
25
26 /* for double link list */
27 typedef struct dlist_s {
28 struct dlist_s *prev;
29 struct dlist_s *next;
30 } dlist_t;
31
__dlist_add(dlist_t * node,dlist_t * prev,dlist_t * next)32 static inline void __dlist_add(dlist_t *node, dlist_t *prev, dlist_t *next)
33 {
34 node->next = next;
35 node->prev = prev;
36
37 prev->next = node;
38 next->prev = node;
39 }
40
41 /*
42 * Get the struct for this entry.
43 *
44 * @param[in] addr the list head to take the element from.
45 * @param[in] type the type of the struct this is embedded in.
46 * @param[in] member the name of the dlist_t within the struct.
47 */
48 #define dlist_entry(addr, type, member) \
49 ((type *)((long)addr - aos_offsetof(type, member)))
50
51
dlist_add(dlist_t * node,dlist_t * queue)52 static inline void dlist_add(dlist_t *node, dlist_t *queue)
53 {
54 __dlist_add(node, queue, queue->next);
55 }
56
dlist_add_tail(dlist_t * node,dlist_t * queue)57 static inline void dlist_add_tail(dlist_t *node, dlist_t *queue)
58 {
59 __dlist_add(node, queue->prev, queue);
60 }
61
dlist_del(dlist_t * node)62 static inline void dlist_del(dlist_t *node)
63 {
64 dlist_t *prev = node->prev;
65 dlist_t *next = node->next;
66
67 prev->next = next;
68 next->prev = prev;
69 }
70
dlist_init(dlist_t * node)71 static inline void dlist_init(dlist_t *node)
72 {
73 node->next = node->prev = node;
74 }
75
INIT_AOS_DLIST_HEAD(dlist_t * list)76 static inline void INIT_AOS_DLIST_HEAD(dlist_t *list)
77 {
78 list->next = list;
79 list->prev = list;
80 }
81
dlist_empty(const dlist_t * head)82 static inline int dlist_empty(const dlist_t *head)
83 {
84 return head->next == head;
85 }
86
87 /*
88 * Initialise the list.
89 *
90 * @param[in] list the list to be inited.
91 */
92 #define AOS_DLIST_INIT(list) {&(list), &(list)}
93
94 /*
95 * Get the first element from a list
96 *
97 * @param[in] ptr the list head to take the element from.
98 * @param[in] type the type of the struct this is embedded in.
99 * @param[in] member the name of the dlist_t within the struct.
100 */
101 #define dlist_first_entry(ptr, type, member) \
102 dlist_entry((ptr)->next, type, member)
103
104 /*
105 * Iterate over a list.
106 *
107 * @param[in] pos the &struct dlist_t to use as a loop cursor.
108 * @param[in] head he head for your list.
109 */
110 #define dlist_for_each(pos, head) \
111 for (pos = (head)->next; pos != (head); pos = pos->next)
112
113 /*
114 * Iterate over a list safe against removal of list entry.
115 *
116 * @param[in] pos the &struct dlist_t to use as a loop cursor.
117 * @param[in] n another &struct dlist_t to use as temporary storage.
118 * @param[in] head he head for your list.
119 */
120 #define dlist_for_each_safe(pos, n, head) \
121 for (pos = (head)->next, n = pos->next; pos != (head); \
122 pos = n, n = pos->next)
123
124 /*
125 * Iterate over list of given type.
126 *
127 * @param[in] queue he head for your list.
128 * @param[in] node the &struct dlist_t to use as a loop cursor.
129 * @param[in] type the type of the struct this is embedded in.
130 * @param[in] member the name of the dlist_t within the struct.
131 */
132 #define dlist_for_each_entry(queue, node, type, member) \
133 for (node = aos_container_of((queue)->next, type, member); \
134 &node->member != (queue); \
135 node = aos_container_of(node->member.next, type, member))
136
137 /*
138 * Iterate over list of given type safe against removal of list entry.
139 *
140 * @param[in] queue the head for your list.
141 * @param[in] n the type * to use as a temp.
142 * @param[in] node the type * to use as a loop cursor.
143 * @param[in] type the type of the struct this is embedded in.
144 * @param[in] member the name of the dlist_t within the struct.
145 */
146 #define dlist_for_each_entry_safe(queue, n, node, type, member) \
147 for (node = aos_container_of((queue)->next, type, member), \
148 n = (queue)->next ? (queue)->next->next : NULL; \
149 &node->member != (queue); \
150 node = aos_container_of(n, type, member), n = n ? n->next : NULL)
151
152 /*
153 * Get the struct for this entry.
154 * @param[in] ptr the list head to take the element from.
155 * @param[in] type the type of the struct this is embedded in.
156 * @param[in] member the name of the variable within the struct.
157 */
158 #define list_entry(ptr, type, member) \
159 aos_container_of(ptr, type, member)
160
161
162 /*
163 * Iterate backwards over list of given type.
164 *
165 * @param[in] pos the type * to use as a loop cursor.
166 * @param[in] head he head for your list.
167 * @param[in] member the name of the dlist_t within the struct.
168 * @param[in] type the type of the struct this is embedded in.
169 */
170 #define dlist_for_each_entry_reverse(pos, head, member, type) \
171 for (pos = list_entry((head)->prev, type, member); \
172 &pos->member != (head); \
173 pos = list_entry(pos->member.prev, type, member))
174
175
176 /*
177 * Get the list length.
178 *
179 * @param[in] queue the head for your list.
180 */
181 int dlist_entry_number(dlist_t *queue);
182
183
184
185 /*
186 * Initialise the list.
187 *
188 * @param[in] name the list to be initialized.
189 */
190 #define AOS_DLIST_HEAD_INIT(name) { &(name), &(name) }
191
192 /*
193 * Initialise the list.
194 *
195 * @param[in] name the list to be initialized.
196 */
197 #define AOS_DLIST_HEAD(name) \
198 dlist_t name = AOS_DLIST_HEAD_INIT(name)
199
200 /* for single link list */
201 typedef struct slist_s {
202 struct slist_s *next;
203 } slist_t;
204
slist_add(slist_t * node,slist_t * head)205 static inline void slist_add(slist_t *node, slist_t *head)
206 {
207 node->next = head->next;
208 head->next = node;
209 }
210
211 void slist_add_tail(slist_t *node, slist_t *head);
212
slist_del(slist_t * node,slist_t * head)213 static inline void slist_del(slist_t *node, slist_t *head)
214 {
215 while (head->next) {
216 if (head->next == node) {
217 head->next = node->next;
218 break;
219 }
220
221 head = head->next;
222 }
223 }
224
slist_empty(const slist_t * head)225 static inline int slist_empty(const slist_t *head)
226 {
227 return !head->next;
228 }
229
slist_init(slist_t * head)230 static inline void slist_init(slist_t *head)
231 {
232 head->next = 0;
233 }
234
slist_remove(slist_t * l,slist_t * n)235 static inline slist_t *slist_remove(slist_t *l, slist_t *n)
236 {
237 /* remove slist head */
238 struct slist_s *node = l;
239 while (node->next && node->next != n) node = node->next;
240
241 /* remove node */
242 if (node->next != (slist_t *)0) node->next = node->next->next;
243
244 return l;
245 }
246
slist_first(slist_t * l)247 static inline slist_t *slist_first(slist_t *l)
248 {
249 return l->next;
250 }
251
slist_tail(slist_t * l)252 static inline slist_t *slist_tail(slist_t *l)
253 {
254 while (l->next) l = l->next;
255
256 return l;
257 }
258
slist_next(slist_t * n)259 static inline slist_t *slist_next(slist_t *n)
260 {
261 return n->next;
262 }
263
264 /*
265 * Iterate over list of given type.
266 *
267 * @param[in] queue he head for your list.
268 * @param[in] node the type * to use as a loop cursor.
269 * @param[in] type the type of the struct this is embedded in.
270 * @param[in] member the name of the slist_t within the struct.
271 */
272 #define slist_for_each_entry(queue, node, type, member) \
273 for (node = (queue)->next? aos_container_of((queue)->next, type, member) : NULL; \
274 node; \
275 node = node->member.next ? aos_container_of(node->member.next, type, member) : NULL)
276
277 /*
278 * Iterate over list of given type safe against removal of list entry.
279 *
280 * @param[in] queue the head for your list.
281 * @param[in] tmp the type * to use as a temp.
282 * @param[in] node the type * to use as a loop cursor.
283 * @param[in] type the type of the struct this is embedded in.
284 * @param[in] member the name of the slist_t within the struct.
285 */
286 #define slist_for_each_entry_safe(queue, tmp, node, type, member) \
287 for (node = (queue)->next? aos_container_of((queue)->next, type, member) : NULL, \
288 tmp = (queue)->next ? (queue)->next->next : NULL; \
289 node; \
290 node = tmp ? aos_container_of(tmp, type, member) : NULL, tmp = tmp ? tmp->next : NULL)
291
292 /*
293 * Initialise the list.
294 *
295 * @param[in] name the list to be initialized.
296 */
297 #define AOS_SLIST_HEAD_INIT(name) {0}
298
299 /*
300 * Initialise the list.
301 *
302 * @param[in] name the list to be initialized.
303 */
304 #define AOS_SLIST_HEAD(name) \
305 slist_t name = AOS_SLIST_HEAD_INIT(name)
306
307 /*
308 * Get the struct for this entry.
309 * @param[in] addr the list head to take the element from.
310 * @param[in] type the type of the struct this is embedded in.
311 * @param[in] member the name of the slist_t within the struct.
312 */
313 #define slist_entry(addr, type, member) ( \
314 addr ? (type *)((long)addr - aos_offsetof(type, member)) : (type *)addr \
315 )
316
317 /*
318 * Get the first element from a list.
319 *
320 * @param[in] ptr the list head to take the element from.
321 * @param[in] type the type of the struct this is embedded in.
322 * @param[in] member the name of the slist_t within the struct.
323 */
324 #define slist_first_entry(ptr, type, member) \
325 slist_entry((ptr)->next, type, member)
326
327 /**
328 * slist_tail_entry - get the tail element from a slist
329 * @ptr: the slist head to take the element from.
330 * @type: the type of the struct this is embedded in.
331 * @member: the name of the slist_struct within the struct.
332 *
333 * Note, that slist is expected to be not empty.
334 */
335 #define slist_tail_entry(ptr, type, member) \
336 slist_entry(slist_tail(ptr), type, member)
337
338 /*
339 * Get the list length.
340 *
341 * @param[in] queue the head for your list.
342 */
343 int slist_entry_number(slist_t *queue);
344
345 #ifdef __cplusplus
346 }
347 #endif
348
349 #endif /* AOS_LIST_H */
350
351