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