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