1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4  */
5 
6 #ifndef _HAL_LIST_H_
7 #define _HAL_LIST_H_
8 
9 /***************************** Structure Definition **************************/
10 
11 /** double list struct */
12 struct HAL_LIST_NODE {
13     struct HAL_LIST_NODE *next;
14     struct HAL_LIST_NODE *prev;
15 };
16 
17 typedef struct HAL_LIST_NODE HAL_LIST;
18 
19 /***************************** Function Declare ******************************/
20 /**
21  * @brief cast a member of a structure out to the containing structure
22  * @param ptr:    the pointer to the member.
23  * @param type:   the type of the container struct this is embedded in.
24  * @param member: the name of the member within the struct.
25  */
26 #define HAL_CONTAINER_OF(ptr, type, member) \
27     ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
28 
29 /**
30  * @brief initialize a list object
31  * @param object: object itself.
32  */
33 #define HAL_LIST_OBJECT_INIT(object) { &(object), &(object) }
34 
35 #define HAL_LIST_HEAD_INIT(name) { &(name), &(name) }
36 
37 /**
38  * @brief initialize a list head
39  * @param name: list name..
40  */
41 #define HAL_LIST_HEAD(name) \
42     struct HAL_LIST_NODE name = HAL_LIST_HEAD_INIT(name)
43 
44 /**
45  * @brief initialize a list
46  * @param l: list to be initialized
47  */
HAL_LIST_Init(HAL_LIST * l)48 __STATIC_INLINE void HAL_LIST_Init(HAL_LIST *l)
49 {
50     l->next = l->prev = l;
51 }
52 
53 /**
54  * @brief insert a node after a list
55  * @param l: list to insert it
56  * @param n: new node to be inserted
57  */
HAL_LIST_InsertAfter(HAL_LIST * l,HAL_LIST * n)58 __STATIC_INLINE void HAL_LIST_InsertAfter(HAL_LIST *l, HAL_LIST *n)
59 {
60     l->next->prev = n;
61     n->next = l->next;
62 
63     l->next = n;
64     n->prev = l;
65 }
66 
67 /**
68  * @brief insert a node before a list
69  * @param n: new node to be inserted
70  * @param l: list to insert it
71  */
HAL_LIST_InsertBefore(HAL_LIST * l,HAL_LIST * n)72 __STATIC_INLINE void HAL_LIST_InsertBefore(HAL_LIST *l, HAL_LIST *n)
73 {
74     l->prev->next = n;
75     n->prev = l->prev;
76 
77     l->prev = n;
78     n->next = l;
79 }
80 
81 /**
82  * @brief remove node from list.
83  * @param n: the node to remove from the list.
84  */
HAL_LIST_Remove(HAL_LIST * n)85 __STATIC_INLINE void HAL_LIST_Remove(HAL_LIST *n)
86 {
87     n->next->prev = n->prev;
88     n->prev->next = n->next;
89 
90     n->next = n->prev = n;
91 }
92 
93 /**
94  * @brief tests whether a list is empty
95  * @param l: the list to test.
96  */
HAL_LIST_IsEmpty(const HAL_LIST * l)97 __STATIC_INLINE int HAL_LIST_IsEmpty(const HAL_LIST *l)
98 {
99     return l->next == l;
100 }
101 
102 /**
103  * @brief get the list length
104  * @param l: the list to get.
105  */
HAL_LIST_Len(const HAL_LIST * l)106 __STATIC_INLINE uint32_t HAL_LIST_Len(const HAL_LIST *l)
107 {
108     uint32_t len = 0;
109     const HAL_LIST *p = l;
110 
111     while (p->next != l) {
112         p = p->next;
113         len++;
114     }
115 
116     return len;
117 }
118 
119 /**
120  * @brief get the struct for this entry
121  * @param node: the entry point
122  * @param type: the type of structure
123  * @param member: the name of list in structure
124  */
125 #define HAL_LIST_ENTRY(node, type, member) \
126     HAL_CONTAINER_OF(node, type, member)
127 
128 /**
129  * @brief iterate over a list
130  * @param pos:  the rt_list_t * to use as a loop cursor.
131  * @param head: the head for your list.
132  */
133 #define HAL_LIST_FOR_EACH(pos, head) \
134     for (pos = (head)->next; pos != (head); pos = pos->next)
135 
136 /**
137  * @brief iterate over a list safe against removal of list entry
138  * @param pos:  the rt_list_t * to use as a loop cursor.
139  * @param n:    another rt_list_t * to use as temporary storage
140  * @param head: the head for your list.
141  */
142 #define HAL_LIST_FOR_EACH_SAFE(pos, n, head)               \
143     for (pos = (head)->next, n = pos->next; pos != (head); \
144         pos = n, n = pos->next)
145 
146 /**
147  * @brief   iterate over list of given type
148  * @param   pos:    the type * to use as a loop cursor.
149  * @param   head:   the head for your list.
150  * @param   member: the name of the list_struct within the struct.
151  */
152 #define HAL_LIST_FOR_EACH_ENTRY(pos, head, member)                     \
153     for (pos = HAL_LIST_ENTRY((head)->next, __typeof__(*pos), member); \
154          &pos->member != (head);                                       \
155          pos = HAL_LIST_ENTRY(pos->member.next, __typeof__(*pos), member))
156 
157 /**
158  * @brief   iterate over list of given type safe against removal of list entry
159  * @param   pos:    the type * to use as a loop cursor.
160  * @param   n:      another type * to use as temporary storage
161  * @param   head:   the head for your list.
162  * @param   member: the name of the list_struct within the struct.
163  */
164 #define HAL_LIST_FOR_EACH_ENTRY_SAFE(pos, n, head, member)               \
165     for (pos = HAL_LIST_ENTRY((head)->next, __typeof__(*pos), member),   \
166          n = HAL_LIST_ENTRY(pos->member.next, __typeof__(*pos), member); \
167          &pos->member != (head);                                         \
168          pos = n, n = HAL_LIST_ENTRY(n->member.next, __typeof__(*n), member))
169 
170 /**
171  * @brief   get the first element from a list
172  * @param   ptr:    the list head to take the element from.
173  * @param   type:   the type of the struct this is embedded in.
174  * @param   member: the name of the list_struct within the struct.
175  *
176  * Note, that list is expected to be not empty.
177  */
178 #define HAL_LIST_FIRST_ENTRY(ptr, type, member) \
179     HAL_LIST_ENTRY((ptr)->next, type, member)
180 
181 #endif
182