1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef COMMON_LIST_H
17 #define COMMON_LIST_H
18
19 #include <stdbool.h>
20 #include <stddef.h>
21
22 #ifdef __cplusplus
23 #if __cplusplus
24 extern "C" {
25 #endif
26 #endif
27
28 typedef struct ListNode {
29 struct ListNode *prev; /* Current node's pointer to the previous node */
30 struct ListNode *next; /* Current node's pointer to the next node */
31 } ListNode;
32
33 /* list initialize */
ListInit(ListNode * list)34 __attribute__((always_inline)) static inline void ListInit(ListNode *list)
35 {
36 list->next = list;
37 list->prev = list;
38 }
39
40 /* Get list head node */
41 #define GET_LIST_HEAD(object) ((object)->next)
42
43 /* Get list tail node */
44 #define GET_LIST_TAIL(object) ((object)->prev)
45
46 /* Insert a new node to list. */
ListAdd(ListNode * list,ListNode * node)47 __attribute__((always_inline)) static inline void ListAdd(ListNode *list, ListNode *node)
48 {
49 node->next = list->next;
50 node->prev = list;
51 list->next->prev = node;
52 list->next = node;
53 }
54
55 /* Insert a node to the tail of a list. */
ListTailInsert(ListNode * list,ListNode * node)56 __attribute__((always_inline)) static inline void ListTailInsert(ListNode *list, ListNode *node)
57 {
58 ListAdd(list->prev, node);
59 }
60
61 /* Insert a new node to list. */
ListNodeInsert(ListNode * list,ListNode * node)62 __attribute__((always_inline)) static inline void ListNodeInsert(ListNode *list, ListNode *node)
63 {
64 ListAdd(list, node);
65 }
66
67 /* Delete a specified node from list. */
ListDelete(ListNode * node)68 __attribute__((always_inline)) static inline void ListDelete(ListNode *node)
69 {
70 if (node->next != 0 && node->prev != 0) {
71 node->next->prev = node->prev;
72 node->prev->next = node->next;
73 }
74 node->next = node;
75 node->prev = node;
76 }
77
IsListEmpty(const ListNode * node)78 __attribute__((always_inline)) static inline bool IsListEmpty(const ListNode *node)
79 {
80 return (bool)(node->next == node);
81 }
82
83 /*
84 * @brief Obtain the pointer to a list in a structure
85 *
86 * @param type [IN] Structure name.
87 * @param member [IN] Member name of the list in the structure.
88 */
89 #define OFF_SET_OF(type, member) ((size_t)&(((type *)0)->member))
90
91 #ifndef CONTAINER_OF
92 #define CONTAINER_OF(ptr, type, member) \
93 (type *)((char *)(ptr) - (char *) &((type *)0)->member)
94 #endif
95
96 /*
97 * @brief Obtain the pointer to a structure that contains a list.
98 * @param item [IN] Current node's pointer to the next node.
99 * @param type [IN] Structure name.
100 * @param member [IN] Member name of the list in the structure.
101 */
102 #define LIST_ENTRY(item, type, member) \
103 ((type *)(void *)((char *)(item) - OFF_SET_OF(type, member))) \
104
105 /* Iterate over a list of given type. */
106 #define LIST_FOR_EACH_ENTRY(item, list, type, member) \
107 for ((item) = LIST_ENTRY((list)->next, type, member); \
108 ((item) != NULL) && (&(item)->member != (list)); \
109 (item) = LIST_ENTRY((item)->member.next, type, member))
110
111 /* Iterate over a list safe against removal of list entry. */
112 #define LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, list, type, member) \
113 for ((item) = LIST_ENTRY((list)->next, type, member), \
114 (nextItem) = LIST_ENTRY((item)->member.next, type, member); \
115 &((item)->member) != (list); \
116 (item) = (nextItem), (nextItem) = LIST_ENTRY((item)->member.next, type, member))
117
ListDel(ListNode * prevNode,ListNode * nextNode)118 __attribute__((always_inline)) static inline void ListDel(ListNode *prevNode, ListNode *nextNode)
119 {
120 nextNode->prev = prevNode;
121 prevNode->next = nextNode;
122 }
123
124 /* Delete node and initialize list */
ListDelInit(ListNode * list)125 __attribute__((always_inline)) static inline void ListDelInit(ListNode *list)
126 {
127 ListDel(list->prev, list->next);
128 ListInit(list);
129 }
130
131 /* Iterate over a list. */
132 #define LIST_FOR_EACH(item, list) \
133 for ((item) = (list)->next; (item) != (list); (item) = (item)->next)
134
135 /* Iterate over a list safe against removal of list entry. */
136 #define LIST_FOR_EACH_SAFE(item, nextItem, list) \
137 for ((item) = (list)->next, (nextItem) = (item)->next; (item) != (list); \
138 (item) = (nextItem), (nextItem) = (item)->next)
139
140 /* Initialize a list. */
141 #define LIST_HEAD(list) ListNode list = { &(list), &(list) }
142
143 #ifdef __cplusplus
144 #if __cplusplus
145 }
146 #endif /* __cplusplus */
147 #endif /* __cplusplus */
148
149 #endif /* COMMON_LIST_H */
150