• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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