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