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