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
21 #ifdef __cplusplus
22 #if __cplusplus
23 extern "C" {
24 #endif
25 #endif
26
27 typedef struct ListNode {
28 struct ListNode *prev; /* Current node's pointer to the previous node */
29 struct ListNode *next; /* Current node's pointer to the next node */
30 } ListNode;
31
32 /* list initialize */
ListInit(ListNode * list)33 __attribute__((always_inline)) static inline void ListInit(ListNode *list)
34 {
35 list->next = list;
36 list->prev = list;
37 }
38
39 /* Get list head node */
40 #define GET_LIST_HEAD(object) ((object)->next)
41
42 /* Get list tail node */
43 #define GET_LIST_TAIL(object) ((object)->prev)
44
45 /* Insert a new node to list. */
ListAdd(ListNode * list,ListNode * node)46 __attribute__((always_inline)) static inline void ListAdd(ListNode *list, ListNode *node)
47 {
48 node->next = list->next;
49 node->prev = list;
50 list->next->prev = node;
51 list->next = node;
52 }
53
54 /* Insert a node to the tail of a list. */
ListTailInsert(ListNode * list,ListNode * node)55 __attribute__((always_inline)) static inline void ListTailInsert(ListNode *list, ListNode *node)
56 {
57 ListAdd(list->prev, node);
58 }
59
60 /* Insert a new node to list. */
ListNodeInsert(ListNode * list,ListNode * node)61 __attribute__((always_inline)) static inline void ListNodeInsert(ListNode *list, ListNode *node)
62 {
63 ListAdd(list, node);
64 }
65
66 /* Delete a specified node from list. */
ListDelete(ListNode * node)67 __attribute__((always_inline)) static inline void ListDelete(ListNode *node)
68 {
69 if (node->next != 0 && node->prev != 0) {
70 node->next->prev = node->prev;
71 node->prev->next = node->next;
72 }
73 node->next = node;
74 node->prev = node;
75 }
76
IsListEmpty(const ListNode * node)77 __attribute__((always_inline)) static inline bool IsListEmpty(const ListNode *node)
78 {
79 return (bool)(node->next == node);
80 }
81
82 /*
83 * @brief Obtain the pointer to a list in a structure
84 *
85 * @param type [IN] Structure name.
86 * @param member [IN] Member name of the list in the structure.
87 */
88 #define OFF_SET_OF(type, member) ((size_t)&(((type *)0)->member))
89
90 #ifndef CONTAINER_OF
91 #define CONTAINER_OF(ptr, type, member) \
92 (type *)((char *)(ptr) - (char *) &((type *)0)->member)
93 #endif
94
95 /*
96 * @brief Obtain the pointer to a structure that contains a list.
97 * @param item [IN] Current node's pointer to the next node.
98 * @param type [IN] Structure name.
99 * @param member [IN] Member name of the list in the structure.
100 */
101 #define LIST_ENTRY(item, type, member) \
102 ((type *)(void *)((char *)(item) - OFF_SET_OF(type, member))) \
103
104 /* Iterate over a list of given type. */
105 #define LIST_FOR_EACH_ENTRY(item, list, type, member) \
106 for ((item) = LIST_ENTRY((list)->next, type, member); \
107 &(item)->member != (list); \
108 (item) = LIST_ENTRY((item)->member.next, type, member))
109
110 /* Iterate over a list safe against removal of list entry. */
111 #define LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, list, type, member) \
112 for ((item) = LIST_ENTRY((list)->next, type, member), \
113 (nextItem) = LIST_ENTRY((item)->member.next, type, member); \
114 &((item)->member) != (list); \
115 (item) = (nextItem), (nextItem) = LIST_ENTRY((item)->member.next, type, member))
116
ListDel(ListNode * prevNode,ListNode * nextNode)117 __attribute__((always_inline)) static inline void ListDel(ListNode *prevNode, ListNode *nextNode)
118 {
119 nextNode->prev = prevNode;
120 prevNode->next = nextNode;
121 }
122
123 /* Delete node and initialize list */
ListDelInit(ListNode * list)124 __attribute__((always_inline)) static inline void ListDelInit(ListNode *list)
125 {
126 ListDel(list->prev, list->next);
127 ListInit(list);
128 }
129
130 /* Iterate over a list. */
131 #define LIST_FOR_EACH(item, list) \
132 for ((item) = (list)->next; (item) != (list); (item) = (item)->next)
133
134 /* Iterate over a list safe against removal of list entry. */
135 #define LIST_FOR_EACH_SAFE(item, nextItem, list) \
136 for ((item) = (list)->next, (nextItem) = (item)->next; (item) != (list); \
137 (item) = (nextItem), (nextItem) = (item)->next)
138
139 /* Initialize a list. */
140 #define LIST_HEAD(list) ListNode list = { &(list), &(list) }
141
142 #ifdef __cplusplus
143 #if __cplusplus
144 }
145 #endif /* __cplusplus */
146 #endif /* __cplusplus */
147
148 #endif /* COMMON_LIST_H */
149