1 /*
2 * Copyright (C) 2024-2025 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 OHOS_IPC_DOUBLY_LINKED_LIST_H
17 #define OHOS_IPC_DOUBLY_LINKED_LIST_H
18
19 #include <stdbool.h>
20 #include <stddef.h>
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif /* __cplusplus */
25
26 typedef struct DL_LIST {
27 struct DL_LIST *pstPrev; /* < Current node's pointer to the previous node */
28 struct DL_LIST *pstNext; /* < Current node's pointer to the next node */
29 } DL_LIST;
30
31 /* List initialize */
DLListInit(DL_LIST * list)32 static inline void DLListInit(DL_LIST *list)
33 {
34 list->pstNext = list;
35 list->pstPrev = list;
36 }
37
38 /* Get list head node */
39 #define DL_GET_LIST_HEAD(object) ((object)->pstNext)
40
41 /* Get list tail node */
42 #define DL_GET_LIST_TAIL(object) ((object)->pstPrev)
43
44 /* Insert a new node to list. */
DLListAdd(DL_LIST * list,DL_LIST * node)45 static inline void DLListAdd(DL_LIST *list, DL_LIST *node)
46 {
47 node->pstNext = list->pstNext;
48 node->pstPrev = list;
49 list->pstNext->pstPrev = node;
50 list->pstNext = node;
51 }
52
53 /* Insert a node to the tail of a list. */
DLListTailInsert(DL_LIST * list,DL_LIST * node)54 static inline void DLListTailInsert(DL_LIST *list, DL_LIST *node)
55 {
56 DLListAdd(list->pstPrev, node);
57 }
58
59 /* Insert a new node to list. */
DLListInsert(DL_LIST * list,DL_LIST * node)60 static inline void DLListInsert(DL_LIST *list, DL_LIST *node)
61 {
62 DLListAdd(list, node);
63 }
64
65 /* Delete a specified node from list. */
DLListDelete(DL_LIST * node)66 static inline void DLListDelete(DL_LIST *node)
67 {
68 node->pstNext->pstPrev = node->pstPrev;
69 node->pstPrev->pstNext = node->pstNext;
70 node->pstNext = NULL;
71 node->pstPrev = NULL;
72 }
73
74 /* Check list is empty. */
DLListEmpty(DL_LIST * list)75 static inline bool DLListEmpty(DL_LIST *list)
76 {
77 return (bool)(list->pstNext == list);
78 }
79
80 /* Obtain the pointer to a list in a structure. */
81 #define DL_OFF_SET_OF(type, member) ((size_t)&((type *)0)->member)
82
83 /* Obtain the pointer to a structure that contains a list. */
84 #define DL_LIST_ENTRY(item, type, member) \
85 ((type *)(void *)((char *)(item) - DL_OFF_SET_OF(type, member)))
86
87 /* Iterate over a list of given type. */
88 #define DL_LIST_FOR_EACH_ENTRY(item, list, type, member) \
89 for ((item) = DL_LIST_ENTRY((list)->pstNext, type, member); \
90 ((item) != NULL) && (&(item)->member != (list)); \
91 (item) = DL_LIST_ENTRY((item)->member.pstNext, type, member))
92
93 /* Iterate over a list safe against removal of list entry. */
94 #define DL_LIST_FOR_EACH_ENTRY_SAFE(item, next, list, type, member) \
95 for ((item) = DL_LIST_ENTRY((list)->pstNext, type, member), \
96 (next) = DL_LIST_ENTRY((item)->member.pstNext, type, member); \
97 &(item)->member != (list); \
98 (item) = (next), (next) = DL_LIST_ENTRY((item)->member.pstNext, type, member))
99
100
DLListDel(DL_LIST * prevNode,DL_LIST * nextNode)101 static inline void DLListDel(DL_LIST *prevNode, DL_LIST *nextNode)
102 {
103 nextNode->pstPrev = prevNode;
104 prevNode->pstNext = nextNode;
105 }
106
107 /* Delete node and initialize list */
ListDeInit(DL_LIST * list)108 static inline void ListDeInit(DL_LIST *list)
109 {
110 DLListDel(list->pstPrev, list->pstNext);
111 DLListInit(list);
112 }
113
114 /* Iterate over a list. */
115 #define DL_LIST_FOR_EACH(item, list) \
116 for ((item) = (list)->pstNext; \
117 (item) != (list); \
118 (item) = (item)->pstNext)
119
120 /* Iterate over a list safe against removal of list entry. */
121 #define DL_LIST_FOR_EACH_SAFE(item, next, list) \
122 for ((item) = (list)->pstNext, (next) = (item)->pstNext; \
123 (item) != (list); \
124 (item) = (next), (next) = (item)->pstNext)
125
126 /* Initialize a list. */
127 #define DL_LIST_HEAD(list) DL_LIST list = { &(list), &(list) }
128
129 #ifdef __cplusplus
130 }
131 #endif /* __cplusplus */
132 #endif /* OHOS_IPC_DOUBLY_LINKED_LIST_H */