/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_SYS_LIST_GEN_H_ #define ZEPHYR_INCLUDE_SYS_LIST_GEN_H_ #include #include #include #define Z_GENLIST_FOR_EACH_NODE(__lname, __l, __sn) \ for ((__sn) = sys_ ## __lname ## _peek_head(__l); (__sn) != NULL; \ (__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) != NULL; \ (__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) != NULL ; (__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) != NULL; \ (__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) != NULL; (__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) == NULL); \ } #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 != NULL) ? \ 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) == NULL) { \ 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) == NULL) { \ 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 (head != NULL && tail != NULL) { \ if (sys_ ## __lname ## _peek_tail(list) == NULL) { \ 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, __nname) \ static inline void \ sys_ ## __lname ## _merge_ ## __lname ( \ sys_ ## __lname ## _t *list, \ sys_ ## __lname ## _t *list_to_append) \ { \ sys_ ## __nname ## _t *head, *tail; \ head = sys_ ## __lname ## _peek_head(list_to_append); \ tail = sys_ ## __lname ## _peek_tail(list_to_append); \ sys_ ## __lname ## _append_list(list, head, tail); \ 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 == NULL) { \ sys_ ## __lname ## _prepend(list, node); \ } else if (z_ ## __nname ## _next_peek(prev) == NULL) { \ 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 == NULL) { \ 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; \ } #define Z_GENLIST_FIND(__lname, __nname) \ static inline bool sys_##__lname##_find( \ sys_##__lname##_t *list, sys_##__nname##_t *node, sys_##__nname##_t **prev) \ { \ sys_##__nname##_t *current = NULL; \ sys_##__nname##_t *previous = NULL; \ \ Z_GENLIST_FOR_EACH_NODE(__lname, list, current) { \ if (current == node) { \ if (prev != NULL) { \ *prev = previous; \ } \ return true; \ } \ \ previous = current; \ } \ \ if (prev != NULL) { \ *prev = previous; \ } \ \ return false; \ } #define Z_GENLIST_LEN(__lname, __nname) \ static inline size_t sys_##__lname##_len(sys_##__lname##_t * list) \ { \ size_t len = 0; \ static sys_##__nname##_t * node; \ Z_GENLIST_FOR_EACH_NODE(__lname, list, node) { \ len++; \ } \ return len; \ } #endif /* ZEPHYR_INCLUDE_SYS_LIST_GEN_H_ */