1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_SYS_LIST_GEN_H_
8 #define ZEPHYR_INCLUDE_SYS_LIST_GEN_H_
9 
10 #include <stddef.h>
11 #include <stdbool.h>
12 #include <zephyr/sys/util.h>
13 
14 #define Z_GENLIST_FOR_EACH_NODE(__lname, __l, __sn)			\
15 	for (__sn = sys_ ## __lname ## _peek_head(__l); __sn != NULL;	\
16 	     __sn = sys_ ## __lname ## _peek_next(__sn))
17 
18 
19 #define Z_GENLIST_ITERATE_FROM_NODE(__lname, __l, __sn)			\
20 	for (__sn = __sn ? sys_ ## __lname ## _peek_next_no_check(__sn)	\
21 			 : sys_ ## __lname ## _peek_head(__l);		\
22 	     __sn != NULL;						\
23 	     __sn = sys_ ## __lname ## _peek_next(__sn))
24 
25 #define Z_GENLIST_FOR_EACH_NODE_SAFE(__lname, __l, __sn, __sns)		\
26 	for (__sn = sys_ ## __lname ## _peek_head(__l),			\
27 		     __sns = sys_ ## __lname ## _peek_next(__sn);	\
28 	     __sn != NULL ; __sn = __sns,				\
29 		     __sns = sys_ ## __lname ## _peek_next(__sn))
30 
31 #define Z_GENLIST_CONTAINER(__ln, __cn, __n)				\
32 	((__ln) ? CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL)
33 
34 #define Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn, __n)		\
35 	Z_GENLIST_CONTAINER(sys_ ## __lname ## _peek_head(__l), __cn, __n)
36 
37 #define Z_GENLIST_PEEK_TAIL_CONTAINER(__lname, __l, __cn, __n)		\
38 	Z_GENLIST_CONTAINER(sys_ ## __lname ## _peek_tail(__l), __cn, __n)
39 
40 #define Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n)		\
41 	((__cn) ? Z_GENLIST_CONTAINER(					\
42 			sys_ ## __lname ## _peek_next(&((__cn)->__n)),	\
43 			__cn, __n) : NULL)
44 
45 #define Z_GENLIST_FOR_EACH_CONTAINER(__lname, __l, __cn, __n)		\
46 	for (__cn = Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn,	\
47 						  __n);			\
48 	     __cn != NULL;						\
49 	     __cn = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n))
50 
51 #define Z_GENLIST_FOR_EACH_CONTAINER_SAFE(__lname, __l, __cn, __cns, __n)     \
52 	for (__cn = Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn, __n),   \
53 	     __cns = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n); \
54 	     __cn != NULL; __cn = __cns,				\
55 	     __cns = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n))
56 
57 #define Z_GENLIST_IS_EMPTY(__lname)					\
58 	static inline bool						\
59 	sys_ ## __lname ## _is_empty(sys_ ## __lname ## _t *list)	\
60 	{								\
61 		return (sys_ ## __lname ## _peek_head(list) == NULL);	\
62 	}
63 
64 #define Z_GENLIST_PEEK_NEXT_NO_CHECK(__lname, __nname)			    \
65 	static inline sys_ ## __nname ## _t *				    \
66 	sys_ ## __lname ## _peek_next_no_check(sys_ ## __nname ## _t *node) \
67 	{								    \
68 		return z_ ## __nname ## _next_peek(node);		    \
69 	}
70 
71 #define Z_GENLIST_PEEK_NEXT(__lname, __nname)				     \
72 	static inline sys_ ## __nname ## _t *				     \
73 	sys_ ## __lname ## _peek_next(sys_ ## __nname ## _t *node)	     \
74 	{								     \
75 		return node != NULL ?                                        \
76 			sys_ ## __lname ## _peek_next_no_check(node) :       \
77 			      NULL;					     \
78 	}
79 
80 #define Z_GENLIST_PREPEND(__lname, __nname)				      \
81 	static inline void						      \
82 	sys_ ## __lname ## _prepend(sys_ ## __lname ## _t *list,	      \
83 				    sys_ ## __nname ## _t *node)	      \
84 	{								      \
85 		z_ ## __nname ## _next_set(node,			      \
86 					sys_ ## __lname ## _peek_head(list)); \
87 		z_ ## __lname ## _head_set(list, node);			      \
88 									      \
89 		if (sys_ ## __lname ## _peek_tail(list) == NULL) {	      \
90 			z_ ## __lname ## _tail_set(list,		      \
91 					sys_ ## __lname ## _peek_head(list)); \
92 		}							      \
93 	}
94 
95 #define Z_GENLIST_APPEND(__lname, __nname)				\
96 	static inline void						\
97 	sys_ ## __lname ## _append(sys_ ## __lname ## _t *list,		\
98 				   sys_ ## __nname ## _t *node)		\
99 	{								\
100 		z_ ## __nname ## _next_set(node, NULL);			\
101 									\
102 		if (sys_ ## __lname ## _peek_tail(list) == NULL) {	\
103 			z_ ## __lname ## _tail_set(list, node);		\
104 			z_ ## __lname ## _head_set(list, node);		\
105 		} else {						\
106 			z_ ## __nname ## _next_set(			\
107 				sys_ ## __lname ## _peek_tail(list),	\
108 				node);					\
109 			z_ ## __lname ## _tail_set(list, node);		\
110 		}							\
111 	}
112 
113 #define Z_GENLIST_APPEND_LIST(__lname, __nname)				\
114 	static inline void						\
115 	sys_ ## __lname ## _append_list(sys_ ## __lname ## _t *list,	\
116 					void *head, void *tail)		\
117 {									\
118 	if (head != NULL && tail != NULL) {				\
119 		if (sys_ ## __lname ## _peek_tail(list) == NULL) {	\
120 			z_ ## __lname ## _head_set(list,		\
121 				(sys_ ## __nname ## _t *)head);		\
122 		} else {						\
123 			z_ ## __nname ## _next_set(			\
124 				sys_ ## __lname ## _peek_tail(list),	\
125 				(sys_ ## __nname ## _t *)head);		\
126 		}							\
127 		z_ ## __lname ## _tail_set(list,			\
128 			(sys_ ## __nname ## _t *)tail);			\
129 	}								\
130 }
131 
132 #define Z_GENLIST_MERGE_LIST(__lname, __nname)				\
133 	static inline void						\
134 	sys_ ## __lname ## _merge_ ## __lname (				\
135 				sys_ ## __lname ## _t *list,		\
136 				sys_ ## __lname ## _t *list_to_append)	\
137 	{								\
138 		sys_ ## __nname ## _t *head, *tail;			\
139 		head = sys_ ## __lname ## _peek_head(list_to_append);	\
140 		tail = sys_ ## __lname ## _peek_tail(list_to_append);	\
141 		sys_ ## __lname ## _append_list(list, head, tail);	\
142 		sys_ ## __lname ## _init(list_to_append);		\
143 	}
144 
145 #define Z_GENLIST_INSERT(__lname, __nname)				\
146 	static inline void						\
147 	sys_ ## __lname ## _insert(sys_ ## __lname ## _t *list,		\
148 				   sys_ ## __nname ## _t *prev,		\
149 				   sys_ ## __nname ## _t *node)		\
150 	{								\
151 		if (prev == NULL) {					\
152 			sys_ ## __lname ## _prepend(list, node);	\
153 		} else if (z_ ## __nname ## _next_peek(prev) == NULL) {	\
154 			sys_ ## __lname ## _append(list, node);		\
155 		} else {						\
156 			z_ ## __nname ## _next_set(node,		\
157 				z_ ## __nname ## _next_peek(prev));	\
158 			z_ ## __nname ## _next_set(prev, node);		\
159 		}							\
160 	}
161 
162 #define Z_GENLIST_GET_NOT_EMPTY(__lname, __nname)			\
163 	static inline sys_ ## __nname ## _t *				\
164 	sys_ ## __lname ## _get_not_empty(sys_ ## __lname ## _t *list)	\
165 	{								\
166 		sys_ ## __nname ## _t *node =				\
167 				sys_ ## __lname ## _peek_head(list);	\
168 									\
169 		z_ ## __lname ## _head_set(list,			\
170 				z_ ## __nname ## _next_peek(node));	\
171 		if (sys_ ## __lname ## _peek_tail(list) == node) {	\
172 			z_ ## __lname ## _tail_set(list,		\
173 				sys_ ## __lname ## _peek_head(list));	\
174 		}							\
175 									\
176 		return node;						\
177 	}
178 
179 #define Z_GENLIST_GET(__lname, __nname)					\
180 	static inline sys_ ## __nname ## _t *				\
181 	sys_ ## __lname ## _get(sys_ ## __lname ## _t *list)		\
182 	{								\
183 		return sys_ ## __lname ## _is_empty(list) ? NULL :	\
184 			sys_ ## __lname ## _get_not_empty(list);	\
185 	}
186 
187 #define Z_GENLIST_REMOVE(__lname, __nname)				      \
188 	static inline void						      \
189 	sys_ ## __lname ## _remove(sys_ ## __lname ## _t *list,		      \
190 				   sys_ ## __nname ## _t *prev_node,	      \
191 				   sys_ ## __nname ## _t *node)		      \
192 	{								      \
193 		if (prev_node == NULL) {				      \
194 			z_ ## __lname ## _head_set(list,		      \
195 				z_ ## __nname ## _next_peek(node));	      \
196 									      \
197 			/* Was node also the tail? */			      \
198 			if (sys_ ## __lname ## _peek_tail(list) == node) {    \
199 				z_ ## __lname ## _tail_set(list,	      \
200 					sys_ ## __lname ## _peek_head(list)); \
201 			}						      \
202 		} else {						      \
203 			z_ ## __nname ## _next_set(prev_node,		      \
204 				z_ ## __nname ## _next_peek(node));	      \
205 									      \
206 			/* Was node the tail? */			      \
207 			if (sys_ ## __lname ## _peek_tail(list) == node) {    \
208 				z_ ## __lname ## _tail_set(list,	      \
209 							     prev_node);      \
210 			}						      \
211 		}							      \
212 									      \
213 		z_ ## __nname ## _next_set(node, NULL);			      \
214 	}
215 
216 #define Z_GENLIST_FIND_AND_REMOVE(__lname, __nname)			 \
217 	static inline bool						 \
218 	sys_ ## __lname ## _find_and_remove(sys_ ## __lname ## _t *list, \
219 					    sys_ ## __nname ## _t *node) \
220 	{								 \
221 		sys_ ## __nname ## _t *prev = NULL;			 \
222 		sys_ ## __nname ## _t *test;				 \
223 									 \
224 		Z_GENLIST_FOR_EACH_NODE(__lname, list, test) {		 \
225 			if (test == node) {				 \
226 				sys_ ## __lname ## _remove(list, prev,	 \
227 							   node);	 \
228 				return true;				 \
229 			}						 \
230 									 \
231 			prev = test;					 \
232 		}							 \
233 									 \
234 		return false;						 \
235 	}
236 
237 #endif /* ZEPHYR_INCLUDE_SYS_LIST_GEN_H_ */
238