NimBLE-Arduino 2.1.2
Loading...
Searching...
No Matches
slist.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
17#ifndef __SLIST_H__
18#define __SLIST_H__
19
20#include <stddef.h>
21#include <stdbool.h>
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27
28struct _snode {
29 struct _snode *next;
30};
31
32typedef struct _snode sys_snode_t;
33
34struct _slist {
35 sys_snode_t *head;
36 sys_snode_t *tail;
37};
38
39typedef struct _slist sys_slist_t;
40
56#define SYS_SLIST_FOR_EACH_NODE(__sl, __sn) \
57 for (__sn = sys_slist_peek_head(__sl); __sn; \
58 __sn = sys_slist_peek_next(__sn))
59
80#define SYS_SLIST_ITERATE_FROM_NODE(__sl, __sn) \
81 for (__sn = __sn ? sys_slist_peek_next_no_check(__sn) \
82 : sys_slist_peek_head(__sl); \
83 __sn; \
84 __sn = sys_slist_peek_next(__sn))
85
102#define SYS_SLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns) \
103 for (__sn = sys_slist_peek_head(__sl), \
104 __sns = sys_slist_peek_next(__sn); \
105 __sn; __sn = __sns, \
106 __sns = sys_slist_peek_next(__sn))
107
108/*
109 * @brief Provide the primitive to resolve the container of a list node
110 * Note: it is safe to use with NULL pointer nodes
111 *
112 * @param __ln A pointer on a sys_node_t to get its container
113 * @param __cn Container struct type pointer
114 * @param __n The field name of sys_node_t within the container struct
115 */
116#define SYS_SLIST_CONTAINER(__ln, __cn, __n) \
117 ((__ln) ? CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL)
118/*
119 * @brief Provide the primitive to peek container of the list head
120 *
121 * @param __sl A pointer on a sys_slist_t to peek
122 * @param __cn Container struct type pointer
123 * @param __n The field name of sys_node_t within the container struct
124 */
125#define SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \
126 SYS_SLIST_CONTAINER(sys_slist_peek_head(__sl), __cn, __n)
127
128/*
129 * @brief Provide the primitive to peek container of the list tail
130 *
131 * @param __sl A pointer on a sys_slist_t to peek
132 * @param __cn Container struct type pointer
133 * @param __n The field name of sys_node_t within the container struct
134 */
135#define SYS_SLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \
136 SYS_SLIST_CONTAINER(sys_slist_peek_tail(__sl), __cn, __n)
137
138/*
139 * @brief Provide the primitive to peek the next container
140 *
141 * @param __cn Container struct type pointer
142 * @param __n The field name of sys_node_t within the container struct
143 */
144
145#define SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n) \
146 ((__cn) ? SYS_SLIST_CONTAINER(sys_slist_peek_next(&((__cn)->__n)), \
147 __cn, __n) : NULL)
148
163#define SYS_SLIST_FOR_EACH_CONTAINER(__sl, __cn, __n) \
164 for (__cn = SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n); __cn; \
165 __cn = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n))
166
182#define SYS_SLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n) \
183 for (__cn = SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n), \
184 __cns = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n); __cn; \
185 __cn = __cns, __cns = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n))
186
192static inline void sys_slist_init(sys_slist_t *list)
193{
194 list->head = NULL;
195 list->tail = NULL;
196}
197
198#define SYS_SLIST_STATIC_INIT(ptr_to_list) {NULL, NULL}
199
207static inline bool sys_slist_is_empty(sys_slist_t *list)
208{
209 return (!list->head);
210}
211
219static inline sys_snode_t *sys_slist_peek_head(sys_slist_t *list)
220{
221 return list->head;
222}
223
231static inline sys_snode_t *sys_slist_peek_tail(sys_slist_t *list)
232{
233 return list->tail;
234}
235
245static inline sys_snode_t *sys_slist_peek_next_no_check(sys_snode_t *node)
246{
247 return node->next;
248}
249
257static inline sys_snode_t *sys_slist_peek_next(sys_snode_t *node)
258{
259 return node ? sys_slist_peek_next_no_check(node) : NULL;
260}
261
270static inline void sys_slist_prepend(sys_slist_t *list,
271 sys_snode_t *node)
272{
273 node->next = list->head;
274 list->head = node;
275
276 if (!list->tail) {
277 list->tail = list->head;
278 }
279}
280
289static inline void sys_slist_append(sys_slist_t *list,
290 sys_snode_t *node)
291{
292 node->next = NULL;
293
294 if (!list->tail) {
295 list->tail = node;
296 list->head = node;
297 } else {
298 list->tail->next = node;
299 list->tail = node;
300 }
301}
302
314static inline void sys_slist_append_list(sys_slist_t *list,
315 void *head, void *tail)
316{
317 if (!list->tail) {
318 list->head = (sys_snode_t *)head;
319 list->tail = (sys_snode_t *)tail;
320 } else {
321 list->tail->next = (sys_snode_t *)head;
322 list->tail = (sys_snode_t *)tail;
323 }
324}
325
335static inline void sys_slist_merge_slist(sys_slist_t *list,
336 sys_slist_t *list_to_append)
337{
338 sys_slist_append_list(list, list_to_append->head,
339 list_to_append->tail);
340 sys_slist_init(list_to_append);
341}
342
352static inline void sys_slist_insert(sys_slist_t *list,
353 sys_snode_t *prev,
354 sys_snode_t *node)
355{
356 if (!prev) {
357 sys_slist_prepend(list, node);
358 } else if (!prev->next) {
359 sys_slist_append(list, node);
360 } else {
361 node->next = prev->next;
362 prev->next = node;
363 }
364}
365
376static inline sys_snode_t *sys_slist_get_not_empty(sys_slist_t *list)
377{
378 sys_snode_t *node = list->head;
379
380 list->head = node->next;
381 if (list->tail == node) {
382 list->tail = list->head;
383 }
384
385 return node;
386}
387
397static inline sys_snode_t *sys_slist_get(sys_slist_t *list)
398{
399 return sys_slist_is_empty(list) ? NULL : sys_slist_get_not_empty(list);
400}
401
412static inline void sys_slist_remove(sys_slist_t *list,
413 sys_snode_t *prev_node,
414 sys_snode_t *node)
415{
416 if (!prev_node) {
417 list->head = node->next;
418
419 /* Was node also the tail? */
420 if (list->tail == node) {
421 list->tail = list->head;
422 }
423 } else {
424 prev_node->next = node->next;
425
426 /* Was node the tail? */
427 if (list->tail == node) {
428 list->tail = prev_node;
429 }
430 }
431
432 node->next = NULL;
433}
434
445static inline bool sys_slist_find_and_remove(sys_slist_t *list,
446 sys_snode_t *node)
447{
448 sys_snode_t *prev = NULL;
449 sys_snode_t *test;
450
451 SYS_SLIST_FOR_EACH_NODE(list, test) {
452 if (test == node) {
453 sys_slist_remove(list, prev, node);
454 return true;
455 }
456
457 prev = test;
458 }
459
460 return false;
461}
462
463
464#ifdef __cplusplus
465}
466#endif
467
468#endif /* __SLIST_H__ */
#define SYS_SLIST_FOR_EACH_NODE(__sl, __sn)
Provide the primitive to iterate on a list Note: the loop is unsafe and thus __sn should not be remov...
Definition slist.h:56