1 /*
2 * Copyright (C) 2021-2022 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 #include "platform/include/list.h"
17 #include <stdlib.h>
18 #include "platform/include/dl_list.h"
19 #include "platform/include/platform_def.h"
20
21 typedef struct ListNode {
22 DL_LIST node;
23 List *list; // Used in func ListGetNextNode, might de deleted in future version.
24 void *data;
25 } ListNodeInternal;
26
27 typedef struct List {
28 DL_LIST dlList;
29 int len;
30 FreeDataCb cb;
31 } ListInternal;
32
ListGetFirstNodeInt(const List * list)33 static ListNode *ListGetFirstNodeInt(const List *list)
34 {
35 ASSERT(list);
36 if (list->len == 0) {
37 return NULL;
38 }
39
40 return DL_LIST_ENTRY(list->dlList.pstNext, ListNode, node);
41 }
42
ListCreate(FreeDataCb cb)43 List *ListCreate(FreeDataCb cb)
44 {
45 List *newList = (List *)calloc(1, (sizeof(List)));
46 if (newList != NULL) {
47 DL_ListInit(&newList->dlList);
48 newList->cb = cb;
49 }
50 return newList;
51 }
52
ListFreeNode(List * list,ListNode * node)53 NO_SANITIZE("cfi") static ListNode *ListFreeNode(List *list, ListNode *node)
54 {
55 ASSERT(list);
56 ASSERT(node);
57 ListNode *next = ListGetNextNode(node);
58 DL_ListDelete(&node->node);
59 if (list->cb) {
60 list->cb(node->data);
61 }
62 free(node);
63 list->len--;
64
65 return next;
66 }
67
ListClear(List * list)68 void ListClear(List *list)
69 {
70 ASSERT(list);
71 if (list->len > 0) {
72 for (ListNode *node = ListGetFirstNode(list); node;) {
73 node = ListFreeNode(list, node);
74 }
75 }
76 list->len = 0;
77 }
78
ListDelete(List * list)79 void ListDelete(List *list)
80 {
81 if (list == NULL) {
82 return;
83 }
84
85 ListClear(list);
86 free(list);
87 }
88
ListGetSize(const List * list)89 int32_t ListGetSize(const List *list)
90 {
91 ASSERT(list);
92 return list->len;
93 }
94
ListAddFirst(List * list,void * data)95 void ListAddFirst(List *list, void *data)
96 {
97 ASSERT(list);
98 ASSERT(data);
99 ListNode *node = (ListNode *)calloc(1, sizeof(ListNode));
100 if (node != NULL) {
101 node->data = data;
102 node->list = list;
103 DL_ListHeadInsert(&list->dlList, &node->node);
104 list->len++;
105 }
106 }
107
ListAddLast(List * list,void * data)108 void ListAddLast(List *list, void *data)
109 {
110 ASSERT(list);
111 ASSERT(data);
112 ListNode *node = (ListNode *)calloc(1, sizeof(ListNode));
113 if (node != NULL) {
114 node->data = data;
115 node->list = list;
116 DL_ListTailInsert(&list->dlList, &node->node);
117 list->len++;
118 }
119 }
120
ListForEachData(const List * list,const ListCmpFunc cmp,void * parameter)121 void *ListForEachData(const List *list, const ListCmpFunc cmp, void *parameter)
122 {
123 ASSERT(list);
124 ASSERT(cmp);
125 if (list->len == 0) {
126 return NULL;
127 }
128
129 for (ListNode *node = ListGetFirstNodeInt(list); node;) {
130 ListNode *next = ListGetNextNode(node);
131 if (cmp(node->data, parameter)) {
132 return node->data;
133 }
134 node = next;
135 }
136 return NULL;
137 }
138
ListGetFirstNode(const List * list)139 ListNode *ListGetFirstNode(const List *list)
140 {
141 ASSERT(list);
142 if (list->len == 0) {
143 return NULL;
144 }
145
146 return DL_LIST_ENTRY(list->dlList.pstNext, ListNode, node);
147 }
148
ListGetLastNode(const List * list)149 ListNode *ListGetLastNode(const List *list)
150 {
151 ASSERT(list);
152 if (list->len == 0) {
153 return NULL;
154 }
155 return DL_LIST_ENTRY(list->dlList.pstPrev, ListNode, node);
156 }
157
ListGetNextNode(const ListNode * listNode)158 ListNode *ListGetNextNode(const ListNode *listNode)
159 {
160 ASSERT(listNode);
161 if (listNode == ListGetLastNode(listNode->list)) {
162 return NULL;
163 }
164 return DL_LIST_ENTRY(listNode->node.pstNext, ListNode, node);
165 }
166
ListGetNodeData(const ListNode * node)167 void *ListGetNodeData(const ListNode *node)
168 {
169 ASSERT(node);
170 return node->data;
171 }
172
ListRemoveNode(List * list,void * data)173 bool ListRemoveNode(List *list, void *data)
174 {
175 ASSERT(list);
176 ASSERT(data);
177 if (list->len == 0) {
178 return false;
179 }
180 for (ListNode *node = ListGetFirstNode(list); node; node = ListGetNextNode(node)) {
181 if (node->data == data) {
182 ListFreeNode(list, node);
183 return true;
184 }
185 }
186 return false;
187 }
188
ListRemoveFirst(List * list)189 bool ListRemoveFirst(List *list)
190 {
191 ASSERT(list);
192 if (list->len == 0) {
193 return false;
194 }
195
196 ListNode *first = ListGetFirstNode(list);
197 if (!ListRemoveNode(list, first->data)) {
198 return false;
199 }
200 return true;
201 }
202
ListRemoveLast(List * list)203 bool ListRemoveLast(List *list)
204 {
205 ASSERT(list);
206 if (list->len == 0) {
207 return false;
208 }
209
210 ListNode *last = ListGetLastNode(list);
211 if (!ListRemoveNode(list, last->data)) {
212 return false;
213 }
214 return true;
215 }
216
ListIsEmpty(const List * list)217 bool ListIsEmpty(const List* list)
218 {
219 ASSERT(list);
220 return (list->len == 0);
221 }
222