• 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 #include "list.h"
17 
18 #include <stddef.h>
19 #include <stdlib.h>
20 
21 /**
22  * @brief Initialize a double-linked list head
23  *
24  * All other list API should be initialized by this function.\n
25  *
26  * @param head list head, make sure head is valid pointer
27  * @return None
28  */
OH_ListInit(struct ListNode * node)29 void OH_ListInit(struct ListNode *node)
30 {
31     if (node == NULL) {
32         return;
33     }
34     node->next = node;
35     node->prev = node;
36 }
37 
38 /**
39  * @brief Add a node to the end of the list
40  *
41  * @param head list head, make sure head is valid pointer
42  * @param item new node to be added
43  * @return None
44  */
OH_ListAddTail(struct ListNode * head,struct ListNode * item)45 void OH_ListAddTail(struct ListNode *head, struct ListNode *item)
46 {
47     if (head == NULL || item == NULL) {
48         return;
49     }
50     item->next = head;
51     item->prev = head->prev;
52     head->prev->next = item;
53     head->prev = item;
54 }
55 
56 /**
57  * @brief Remove a node from the list
58  *
59  * @param item the node to be removed from the list.
60  *             This function does not free any memory within item.
61  * @return None
62  */
OH_ListRemove(struct ListNode * item)63 void OH_ListRemove(struct ListNode *item)
64 {
65     if (item == NULL) {
66         return;
67     }
68     item->next->prev = item->prev;
69     item->prev->next = item->next;
70 }
71 
72 /**
73  * @brief Add a node to the list with order
74  *
75  * @param head list head, make sure head is valid pointer
76  * @param item new node to be added
77  * @param compareProc comparison function for adding node
78  *      if it is ascending order, this function should return an integer less than,
79  *      equal to, or greater than zero if the first argument is considered to be
80  *      respectively less than, equal to, or greater than the second.
81  * @return None
82  */
OH_ListAddWithOrder(struct ListNode * head,struct ListNode * item,ListCompareProc compareProc)83 void OH_ListAddWithOrder(struct ListNode *head, struct ListNode *item, ListCompareProc compareProc)
84 {
85     ListNode *match;
86 
87     if (head == NULL || item == NULL || compareProc == NULL) {
88         return;
89     }
90 
91     match = head->next;
92     while ((match != NULL) && (match != head)) {
93         if (compareProc(match, item) > 0) {
94             break;
95         }
96         match = match->next;
97     }
98     if (match == NULL) {
99         return;
100     }
101 
102     // Insert
103     item->next = match;
104     item->prev = match->prev;
105     match->prev->next = item;
106     match->prev = item;
107 }
108 
109 /**
110  * @brief Find a node by traversing the list
111  *
112  * @param head list head, make sure head is valid pointer.
113  * @param data comparing data.
114  * @param compareProc comparing function, return 0 if matched.
115  * @return the found node; return NULL if none is found.
116  */
OH_ListFind(const ListNode * head,void * data,ListTraversalProc compareProc)117 ListNode *OH_ListFind(const ListNode *head, void *data, ListTraversalProc compareProc)
118 {
119     ListNode *match;
120     if ((head == NULL) || (compareProc == NULL)) {
121         return NULL;
122     }
123 
124     match = head->next;
125     while ((match != NULL) && (match != head)) {
126         if (compareProc(match, data) == 0) {
127             return match;
128         }
129         match = match->next;
130     }
131 
132     return NULL;
133 }
134 
135 #define IS_REVERSE_ORDER(flags)    (((flags) & TRAVERSE_REVERSE_ORDER) != 0)
136 #define IS_STOP_WHEN_ERROR(flags)  (((flags) & TRAVERSE_STOP_WHEN_ERROR) != 0)
137 
138 /**
139  * @brief Traversal the list with specified function
140  *
141  * @param head list head, make sure head is valid pointer.
142  * @param cookie optional traversing data.
143  * @param traversalProc comparing function, return 0 if matched.
144  * @param flags optional traversing flags:
145  *  TRAVERSE_REVERSE_ORDER: traversing from last node to first node;
146  *                          default behaviour is from first node to last node
147  *  TRAVERSE_STOP_WHEN_ERROR: stop traversing if traversalProc return non-zero
148  *                          default behaviour will ignore traversalProc return values
149  * @return return -1 for invalid input arguments.
150  *         when TRAVERSE_STOP_WHEN_ERROR is specified, it will return errors from traversalProc
151  */
OH_ListTraversal(ListNode * head,void * data,ListTraversalProc traversalProc,unsigned int flags)152 int OH_ListTraversal(ListNode *head, void *data, ListTraversalProc traversalProc, unsigned int flags)
153 {
154     ListNode *match;
155     ListNode *next;
156 
157     if ((head == NULL) || (traversalProc == NULL)) {
158         return -1;
159     }
160 
161     if (IS_REVERSE_ORDER(flags)) {
162         match = head->prev;
163     } else {
164         match = head->next;
165     }
166     while ((match != NULL) && (match != head)) {
167         if (IS_REVERSE_ORDER(flags)) {
168             next = match->prev;
169         } else {
170             next = match->next;
171         }
172         int ret = traversalProc(match, data);
173         if ((ret != 0) && IS_STOP_WHEN_ERROR(flags)) {
174             return ret;
175         }
176         match = next;
177     }
178 
179     return 0;
180 }
181 
listDestroyTraversal(ListNode * node,void * data)182 static int listDestroyTraversal(ListNode *node, void *data)
183 {
184     ListDestroyProc destroyProc = (ListDestroyProc)data;
185 
186     if (destroyProc == NULL) {
187         free((void *)node);
188     } else {
189         destroyProc(node);
190     }
191 
192     return 0;
193 }
194 
195 /**
196  * @brief Find a node by traversing the list
197  *
198  * @param head list head, make sure head is valid pointer.
199  * @param destroyProc destroy function; if NULL, it will free each node by default.
200  * @return None
201  */
OH_ListRemoveAll(ListNode * head,ListDestroyProc destroyProc)202 void OH_ListRemoveAll(ListNode *head, ListDestroyProc destroyProc)
203 {
204     if (head == NULL) {
205         return;
206     }
207 
208     OH_ListTraversal(head, (void *)destroyProc, listDestroyTraversal, 0);
209     OH_ListInit(head);
210 }
211 
212 /**
213  * @brief Get list count
214  *
215  * @param head list head, make sure head is valid pointer.
216  * @return the count of nodes in the list; return 0 if error
217  */
OH_ListGetCnt(const ListNode * head)218 int OH_ListGetCnt(const ListNode *head)
219 {
220     int cnt;
221     ListNode *node;
222 
223     if (head == NULL) {
224         return 0;
225     }
226 
227     cnt = 0;
228     ForEachListEntry(head, node) {
229         cnt++;
230     }
231     return cnt;
232 }
233