Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef ZEPHYR_MISC_LIST_GEN_H
#define ZEPHYR_MISC_LIST_GEN_H

#include <stddef.h>
#include <stdbool.h>
#include <misc/util.h>

#define Z_GENLIST_FOR_EACH_NODE(__lname, __l, __sn)			\
	for (__sn = sys_ ## __lname ## _peek_head(__l); __sn;		\
	     __sn = sys_ ## __lname ## _peek_next(__sn))


#define Z_GENLIST_ITERATE_FROM_NODE(__lname, __l, __sn)			\
	for (__sn = __sn ? sys_ ## __lname ## _peek_next_no_check(__sn)	\
			 : sys_ ## __lname ## _peek_head(__l);		\
	     __sn;							\
	     __sn = sys_ ## __lname ## _peek_next(__sn))

#define Z_GENLIST_FOR_EACH_NODE_SAFE(__lname, __l, __sn, __sns)		\
	for (__sn = sys_ ## __lname ## _peek_head(__l),			\
		     __sns = sys_ ## __lname ## _peek_next(__sn);	\
	     __sn; __sn = __sns,					\
		     __sns = sys_ ## __lname ## _peek_next(__sn))

#define Z_GENLIST_CONTAINER(__ln, __cn, __n)				\
	((__ln) ? CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL)

#define Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn, __n)		\
	Z_GENLIST_CONTAINER(sys_ ## __lname ## _peek_head(__l), __cn, __n)

#define Z_GENLIST_PEEK_TAIL_CONTAINER(__lname, __l, __cn, __n)		\
	Z_GENLIST_CONTAINER(sys_ ## __lname ## _peek_tail(__l), __cn, __n)

#define Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n)		\
	((__cn) ? Z_GENLIST_CONTAINER(					\
			sys_ ## __lname ## _peek_next(&((__cn)->__n)),	\
			__cn, __n) : NULL)

#define Z_GENLIST_FOR_EACH_CONTAINER(__lname, __l, __cn, __n)		\
	for (__cn = Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn,	\
						  __n);			\
	     __cn;							\
	     __cn = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n))

#define Z_GENLIST_FOR_EACH_CONTAINER_SAFE(__lname, __l, __cn, __cns, __n)     \
	for (__cn = Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn, __n),   \
	     __cns = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n); __cn; \
	     __cn = __cns,						      \
	     __cns = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n))

#define Z_GENLIST_IS_EMPTY(__lname)					\
	static inline bool						\
	sys_ ## __lname ## _is_empty(sys_ ## __lname ## _t *list)	\
	{								\
		return (!sys_ ## __lname ## _peek_head(list));		\
	}

#define Z_GENLIST_PEEK_NEXT_NO_CHECK(__lname, __nname)			    \
	static inline sys_ ## __nname ## _t *				    \
	sys_ ## __lname ## _peek_next_no_check(sys_ ## __nname ## _t *node) \
	{								    \
		return z_ ## __nname ## _next_peek(node);		    \
	}

#define Z_GENLIST_PEEK_NEXT(__lname, __nname)				     \
	static inline sys_ ## __nname ## _t *				     \
	sys_ ## __lname ## _peek_next(sys_ ## __nname ## _t *node)	     \
	{								     \
		return node ? sys_ ## __lname ## _peek_next_no_check(node) : \
			      NULL;					     \
	}

#define Z_GENLIST_PREPEND(__lname, __nname)				      \
	static inline void						      \
	sys_ ## __lname ## _prepend(sys_ ## __lname ## _t *list,	      \
				    sys_ ## __nname ## _t *node)	      \
	{								      \
		z_ ## __nname ## _next_set(node,			      \
					sys_ ## __lname ## _peek_head(list)); \
		z_ ## __lname ## _head_set(list, node);			      \
									      \
		if (!sys_ ## __lname ## _peek_tail(list)) {		      \
			z_ ## __lname ## _tail_set(list,		      \
					sys_ ## __lname ## _peek_head(list)); \
		}							      \
	}

#define Z_GENLIST_APPEND(__lname, __nname)				\
	static inline void						\
	sys_ ## __lname ## _append(sys_ ## __lname ## _t *list,		\
				   sys_ ## __nname ## _t *node)		\
	{								\
		z_ ## __nname ## _next_set(node, NULL);			\
									\
		if (!sys_ ## __lname ## _peek_tail(list)) {		\
			z_ ## __lname ## _tail_set(list, node);		\
			z_ ## __lname ## _head_set(list, node);		\
		} else {						\
			z_ ## __nname ## _next_set(			\
				sys_ ## __lname ## _peek_tail(list),	\
				node);					\
			z_ ## __lname ## _tail_set(list, node);		\
		}							\
	}

#define Z_GENLIST_APPEND_LIST(__lname, __nname)				\
	static inline void						\
	sys_ ## __lname ## _append_list(sys_ ## __lname ## _t *list,	\
					void *head, void *tail)		\
{									\
	if (!sys_ ## __lname ## _peek_tail(list)) {			\
		z_ ## __lname ## _head_set(list,			\
					(sys_ ## __nname ## _t *)head); \
	} else {							\
		z_ ## __nname ## _next_set(				\
			sys_ ## __lname ## _peek_tail(list),		\
			(sys_ ## __nname ## _t *)head);			\
	}								\
	z_ ## __lname ## _tail_set(list,				\
				     (sys_ ## __nname ## _t *)tail);	\
}

#define Z_GENLIST_MERGE_LIST(__lname)					\
	static inline void						\
	sys_ ## __lname ## _merge_ ## __lname (				\
				sys_ ## __lname ## _t *list,		\
				sys_ ## __lname ## _t *list_to_append)	\
	{								\
		sys_ ## __lname ## _append_list(list,			\
			sys_ ## __lname ## _peek_head(list_to_append),	\
			sys_ ## __lname ## _peek_tail(list_to_append));	\
		sys_ ## __lname ## _init(list_to_append);		\
	}

#define Z_GENLIST_INSERT(__lname, __nname)				\
	static inline void						\
	sys_ ## __lname ## _insert(sys_ ## __lname ## _t *list,		\
				   sys_ ## __nname ## _t *prev,		\
				   sys_ ## __nname ## _t *node)		\
	{								\
		if (!prev) {						\
			sys_ ## __lname ## _prepend(list, node);	\
		} else if (!z_ ## __nname ## _next_peek(prev)) {	\
			sys_ ## __lname ## _append(list, node);		\
		} else {						\
			z_ ## __nname ## _next_set(node,		\
				z_ ## __nname ## _next_peek(prev));	\
			z_ ## __nname ## _next_set(prev, node);		\
		}							\
	}

#define Z_GENLIST_GET_NOT_EMPTY(__lname, __nname)			\
	static inline sys_ ## __nname ## _t *				\
	sys_ ## __lname ## _get_not_empty(sys_ ## __lname ## _t *list)	\
	{								\
		sys_ ## __nname ## _t *node =				\
				sys_ ## __lname ## _peek_head(list);	\
									\
		z_ ## __lname ## _head_set(list,			\
				z_ ## __nname ## _next_peek(node));	\
		if (sys_ ## __lname ## _peek_tail(list) == node) {	\
			z_ ## __lname ## _tail_set(list,		\
				sys_ ## __lname ## _peek_head(list));	\
		}							\
									\
		return node;						\
	}

#define Z_GENLIST_GET(__lname, __nname)					\
	static inline sys_ ## __nname ## _t *				\
	sys_ ## __lname ## _get(sys_ ## __lname ## _t *list)		\
	{								\
		return sys_ ## __lname ## _is_empty(list) ? NULL :	\
			sys_ ## __lname ## _get_not_empty(list);	\
	}

#define Z_GENLIST_REMOVE(__lname, __nname)				      \
	static inline void						      \
	sys_ ## __lname ## _remove(sys_ ## __lname ## _t *list,		      \
				   sys_ ## __nname ## _t *prev_node,	      \
				   sys_ ## __nname ## _t *node)		      \
	{								      \
		if (!prev_node) {					      \
			z_ ## __lname ## _head_set(list,		      \
				z_ ## __nname ## _next_peek(node));	      \
									      \
			/* Was node also the tail? */			      \
			if (sys_ ## __lname ## _peek_tail(list) == node) {    \
				z_ ## __lname ## _tail_set(list,	      \
					sys_ ## __lname ## _peek_head(list)); \
			}						      \
		} else {						      \
			z_ ## __nname ## _next_set(prev_node,		      \
				z_ ## __nname ## _next_peek(node));	      \
									      \
			/* Was node the tail? */			      \
			if (sys_ ## __lname ## _peek_tail(list) == node) {    \
				z_ ## __lname ## _tail_set(list,	      \
							     prev_node);      \
			}						      \
		}							      \
									      \
		z_ ## __nname ## _next_set(node, NULL);			      \
	}

#define Z_GENLIST_FIND_AND_REMOVE(__lname, __nname)			 \
	static inline bool						 \
	sys_ ## __lname ## _find_and_remove(sys_ ## __lname ## _t *list, \
					    sys_ ## __nname ## _t *node) \
	{								 \
		sys_ ## __nname ## _t *prev = NULL;			 \
		sys_ ## __nname ## _t *test;				 \
									 \
		Z_GENLIST_FOR_EACH_NODE(__lname, list, test) {		 \
			if (test == node) {				 \
				sys_ ## __lname ## _remove(list, prev,	 \
							   node);	 \
				return true;				 \
			}						 \
									 \
			prev = test;					 \
		}							 \
									 \
		return false;						 \
	}

#endif /* ZEPHYR_MISC_LIST_GEN_H */