1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _SHELL_LIST_H
33 #define _SHELL_LIST_H
34
35 #include "sherr.h"
36 #include "stdint.h"
37
38 #ifdef __cplusplus
39 #if __cplusplus
40 extern "C" {
41 #endif /* __cplusplus */
42 #endif /* __cplusplus */
43
44 typedef size_t bool;
45
46 /**
47 * @ingroup shell_list
48 * Structure of a node in a doubly linked list.
49 */
50 typedef struct SH_List {
51 struct SH_List *pstPrev; /**< Current node's pointer to the previous node */
52 struct SH_List *pstNext; /**< Current node's pointer to the next node */
53 } SH_List;
54
55 /**
56 * @ingroup shell_list
57 *
58 * @par Description:
59 * This API is used to initialize a doubly linked list.
60 * @attention
61 * <ul>
62 * <li>The parameter passed in should be ensured to be a legal pointer.</li>
63 * </ul>
64 *
65 * @param list [IN] Node in a doubly linked list.
66 *
67 * @retval None.
68 * @par Dependency:
69 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
70 * @see
71 */
SH_ListInit(SH_List * list)72 static inline void SH_ListInit(SH_List *list)
73 {
74 list->pstNext = list;
75 list->pstPrev = list;
76 }
77
78 /**
79 * @ingroup shell_list
80 * @brief Point to the next node pointed to by the current node.
81 *
82 * @par Description:
83 * <ul>
84 * <li>This API is used to point to the next node pointed to by the current node.</li>
85 * </ul>
86 * @attention
87 * <ul>
88 * <li>None.</li>
89 * </ul>
90 *
91 * @param object [IN] Node in the doubly linked list.
92 *
93 * @retval None.
94 * @par Dependency:
95 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
96 * @see
97 */
98 #define SH_LIST_FIRST(object) ((object)->pstNext)
99
100 /**
101 * @ingroup shell_list
102 * @brief Point to the previous node pointed to by the current node.
103 *
104 * @par Description:
105 * <ul>
106 * <li>This API is used to point to the previous node pointed to by the current node.</li>
107 * </ul>
108 * @attention
109 * <ul>
110 * <li>None.</li>
111 * </ul>
112 *
113 * @param object [IN] Node in the doubly linked list.
114 *
115 * @retval None.
116 * @par Dependency:
117 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
118 * @see
119 */
120 #define SH_LIST_LAST(object) ((object)->pstPrev)
121
122 /**
123 * @ingroup shell_list
124 * @brief Insert a new node to a doubly linked list.
125 *
126 * @par Description:
127 * This API is used to insert a new node to a doubly linked list.
128 * @attention
129 * <ul>
130 * <li>The parameters passed in should be ensured to be legal pointers.</li>
131 * </ul>
132 *
133 * @param list [IN] Doubly linked list where the new node is inserted.
134 * @param node [IN] New node to be inserted.
135 *
136 * @retval None
137 * @par Dependency:
138 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
139 * @see SH_ListDelete
140 */
SH_ListAdd(SH_List * list,SH_List * node)141 static inline void SH_ListAdd(SH_List *list, SH_List *node)
142 {
143 node->pstNext = list->pstNext;
144 node->pstPrev = list;
145 list->pstNext->pstPrev = node;
146 list->pstNext = node;
147 }
148
149 /**
150 * @ingroup shell_list
151 * @brief Insert a node to the tail of a doubly linked list.
152 *
153 * @par Description:
154 * This API is used to insert a new node to the tail of a doubly linked list.
155 * @attention
156 * <ul>
157 * <li>The parameters passed in should be ensured to be legal pointers.</li>
158 * </ul>
159 *
160 * @param list [IN] Doubly linked list where the new node is inserted.
161 * @param node [IN] New node to be inserted.
162 *
163 * @retval None.
164 * @par Dependency:
165 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
166 * @see SH_ListAdd | SH_ListHeadInsert
167 */
SH_ListTailInsert(SH_List * list,SH_List * node)168 static inline void SH_ListTailInsert(SH_List *list, SH_List *node)
169 {
170 if ((list == NULL) || (node == NULL)) {
171 return;
172 }
173
174 SH_ListAdd(list->pstPrev, node);
175 }
176
177 /**
178 * @ingroup shell_list
179 * @brief Insert a node to the head of a doubly linked list.
180 *
181 * @par Description:
182 * This API is used to insert a new node to the head of a doubly linked list.
183 * @attention
184 * <ul>
185 * <li>The parameters passed in should be ensured to be legal pointers.</li>
186 * </ul>
187 *
188 * @param list [IN] Doubly linked list where the new node is inserted.
189 * @param node [IN] New node to be inserted.
190 *
191 * @retval None.
192 * @par Dependency:
193 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
194 * @see SH_ListAdd | SH_ListTailInsert
195 */
SH_ListHeadInsert(SH_List * list,SH_List * node)196 static inline void SH_ListHeadInsert(SH_List *list, SH_List *node)
197 {
198 if ((list == NULL) || (node == NULL)) {
199 return;
200 }
201
202 SH_ListAdd(list, node);
203 }
204
205 /**
206 * @ingroup shell_list
207 *
208 * @par Description:
209 * <ul>
210 * <li>This API is used to delete a specified node from a doubly linked list.</li>
211 * </ul>
212 * @attention
213 * <ul>
214 * <li>The parameter passed in should be ensured to be a legal pointer.</li>
215 * </ul>
216 *
217 * @param node [IN] Node to be deleted.
218 *
219 * @retval None.
220 * @par Dependency:
221 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
222 * @see SH_ListAdd
223 */
SH_ListDelete(SH_List * node)224 static inline void SH_ListDelete(SH_List *node)
225 {
226 node->pstNext->pstPrev = node->pstPrev;
227 node->pstPrev->pstNext = node->pstNext;
228 node->pstNext = NULL;
229 node->pstPrev = NULL;
230 }
231
232 /**
233 * @ingroup shell_list
234 * @brief Identify whether a specified doubly linked list is empty.
235 *
236 * @par Description:
237 * <ul>
238 * <li>This API is used to return whether a doubly linked list is empty.</li>
239 * </ul>
240 * @attention
241 * <ul>
242 * <li>The parameter passed in should be ensured to be a legal pointer.</li>
243 * </ul>
244 *
245 * @param list [IN] Doubly linked list.
246 *
247 * @retval TRUE The doubly linked list is empty.
248 * @retval FALSE The doubly linked list is not empty.
249 * @par Dependency:
250 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
251 * @see
252 */
SH_ListEmpty(SH_List * list)253 static inline bool SH_ListEmpty(SH_List *list)
254 {
255 if (list == NULL) {
256 return FALSE;
257 }
258
259 return (bool)(list->pstNext == list);
260 }
261
262 /**
263 * @ingroup shell_list
264 * @brief Insert a new list to a doubly linked list.
265 *
266 * @par Description:
267 * This API is used to insert a new list to a doubly linked list.
268 * @attention
269 * <ul>
270 * <li>The parameters passed in should be ensured to be legal pointers.</li>
271 * </ul>
272 *
273 * @param oldList [IN] Doubly linked list where the new list is inserted.
274 * @param newList [IN] New list to be inserted.
275 *
276 * @retval None
277 * @par Dependency:
278 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
279 * @see SH_ListDelete
280 */
SH_ListAddList(SH_List * oldList,SH_List * newList)281 static inline void SH_ListAddList(SH_List *oldList, SH_List *newList)
282 {
283 SH_List *oldListHead = oldList->pstNext;
284 SH_List *oldListTail = oldList;
285 SH_List *newListHead = newList;
286 SH_List *newListTail = newList->pstPrev;
287
288 oldListTail->pstNext = newListHead;
289 newListHead->pstPrev = oldListTail;
290 oldListHead->pstPrev = newListTail;
291 newListTail->pstNext = oldListHead;
292 }
293
294 /**
295 * @ingroup shell_list
296 * @brief Insert a doubly list to the tail of a doubly linked list.
297 *
298 * @par Description:
299 * This API is used to insert a new doubly list to the tail of a doubly linked list.
300 * @attention
301 * <ul>
302 * <li>The parameters passed in should be ensured to be legal pointers.</li>
303 * </ul>
304 *
305 * @param oldList [IN] Doubly linked list where the new list is inserted.
306 * @param newList [IN] New list to be inserted.
307 *
308 * @retval None.
309 * @par Dependency:
310 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
311 * @see SH_ListAddList | SH_ListHeadInsertList
312 */
SH_ListTailInsertList(SH_List * oldList,SH_List * newList)313 static inline void SH_ListTailInsertList(SH_List *oldList, SH_List *newList)
314 {
315 SH_ListAddList(oldList->pstPrev, newList);
316 }
317
318 /**
319 * @ingroup shell_list
320 * @brief Insert a doubly list to the head of a doubly linked list.
321 *
322 * @par Description:
323 * This API is used to insert a new doubly list to the head of a doubly linked list.
324 * @attention
325 * <ul>
326 * <li>The parameters passed in should be ensured to be legal pointers.</li>
327 * </ul>
328 *
329 * @param oldList [IN] Doubly linked list where the new list is inserted.
330 * @param newList [IN] New list to be inserted.
331 *
332 * @retval None.
333 * @par Dependency:
334 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
335 * @see SH_ListAddList | SH_ListTailInsertList
336 */
SH_ListHeadInsertList(SH_List * oldList,SH_List * newList)337 static inline void SH_ListHeadInsertList(SH_List *oldList, SH_List *newList)
338 {
339 SH_ListAddList(oldList, newList);
340 }
341
342 /**
343 * @ingroup shell_list
344 * @brief Obtain the offset of a field to a structure address.
345 *
346 * @par Description:
347 * This API is used to obtain the offset of a field to a structure address.
348 * @attention
349 * <ul>
350 * <li>None.</li>
351 * </ul>
352 *
353 * @param type [IN] Structure name.
354 * @param member [IN] Name of the member of which the offset is to be measured.
355 *
356 * @retval Offset of the field to the structure address.
357 * @par Dependency:
358 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
359 * @see
360 */
361 #define LOS_OFF_SET_OF(type, member) ((uintptr_t)&((type *)0)->member)
362
363 /**
364 * @ingroup shell_list
365 * @brief Obtain the pointer to a structure that contains a doubly linked list.
366 *
367 * @par Description:
368 * This API is used to obtain the pointer to a structure that contains a doubly linked list.
369 * <ul>
370 * <li>None.</li>
371 * </ul>
372 * @attention
373 * <ul>
374 * <li>None.</li>
375 * </ul>
376 *
377 * @param item [IN] Current node's pointer to the next node.
378 * @param type [IN] Structure name.
379 * @param member [IN] Member name of the doubly linked list in the structure.
380 *
381 * @retval Pointer to the structure that contains the doubly linked list.
382 * @par Dependency:
383 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
384 * @see
385 */
386 #define SH_LIST_ENTRY(item, type, member) \
387 ((type *)(void *)((char *)(item) - LOS_OFF_SET_OF(type, member)))
388
389 /**
390 * @ingroup shell_list
391 * @brief Iterate over a doubly linked list of given type.
392 *
393 * @par Description:
394 * This API is used to iterate over a doubly linked list of given type.
395 * @attention
396 * <ul>
397 * <li>None.</li>
398 * </ul>
399 *
400 * @param item [IN] Pointer to the structure that contains the doubly linked list that is to be traversed.
401 * @param list [IN] Pointer to the doubly linked list to be traversed.
402 * @param type [IN] Structure name.
403 * @param member [IN] Member name of the doubly linked list in the structure.
404 *
405 * @retval None.
406 * @par Dependency:
407 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
408 * @see
409 */
410 #define SH_LIST_FOR_EACH_ENTRY(item, list, type, member) \
411 for (item = SH_LIST_ENTRY((list)->pstNext, type, member); \
412 &(item)->member != (list); \
413 item = SH_LIST_ENTRY((item)->member.pstNext, type, member))
414
415 /**
416 * @ingroup shell_list
417 * @brief iterate over a doubly linked list safe against removal of list entry.
418 *
419 * @par Description:
420 * This API is used to iterate over a doubly linked list safe against removal of list entry.
421 * @attention
422 * <ul>
423 * <li>None.</li>
424 * </ul>
425 *
426 * @param item [IN] Pointer to the structure that contains the doubly linked list that is to be traversed.
427 * @param next [IN] Save the next node.
428 * @param list [IN] Pointer to the doubly linked list to be traversed.
429 * @param type [IN] Structure name.
430 * @param member [IN] Member name of the doubly linked list in the structure.
431 *
432 * @retval None.
433 * @par Dependency:
434 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
435 * @see
436 */
437 #define SH_LIST_FOR_EACH_ENTRY_SAFE(item, next, list, type, member) \
438 for (item = SH_LIST_ENTRY((list)->pstNext, type, member), \
439 next = SH_LIST_ENTRY((item)->member.pstNext, type, member); \
440 &(item)->member != (list); \
441 item = next, next = SH_LIST_ENTRY((item)->member.pstNext, type, member))
442
443 /**
444 * @ingroup shell_list
445 * @brief Delete initialize a doubly linked list.
446 *
447 * @par Description:
448 * This API is used to delete initialize a doubly linked list.
449 * @attention
450 * <ul>
451 * <li>The parameter passed in should be ensured to be s legal pointer.</li>
452 * </ul>
453 *
454 * @param list [IN] Doubly linked list.
455 *
456 * @retval None.
457 * @par Dependency:
458 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
459 * @see
460 */
SH_ListDelInit(SH_List * list)461 static inline void SH_ListDelInit(SH_List *list)
462 {
463 list->pstNext->pstPrev = list->pstPrev;
464 list->pstPrev->pstNext = list->pstNext;
465 SH_ListInit(list);
466 }
467
468 /**
469 * @ingroup shell_list
470 * @brief iterate over a doubly linked list.
471 *
472 * @par Description:
473 * This API is used to iterate over a doubly linked list.
474 * @attention
475 * <ul>
476 * <li>None.</li>
477 * </ul>
478 *
479 * @param item [IN] Pointer to the structure that contains the doubly linked list that is to be traversed.
480 * @param list [IN] Pointer to the doubly linked list to be traversed.
481 *
482 * @retval None.
483 * @par Dependency:
484 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
485 * @see
486 */
487 #define SH_LIST_FOR_EACH(item, list) \
488 for (item = (list)->pstNext; \
489 (item) != (list); \
490 item = (item)->pstNext)
491
492 /**
493 * @ingroup shell_list
494 * @brief Iterate over a doubly linked list safe against removal of list entry.
495 *
496 * @par Description:
497 * This API is used to iterate over a doubly linked list safe against removal of list entry.
498 * @attention
499 * <ul>
500 * <li>None.</li>
501 * </ul>
502 *
503 * @param item [IN] Pointer to the structure that contains the doubly linked list that is to be traversed.
504 * @param next [IN] Save the next node.
505 * @param list [IN] Pointer to the doubly linked list to be traversed.
506 *
507 * @retval None.
508 * @par Dependency:
509 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
510 * @see
511 */
512 #define SH_LIST_FOR_EACH_SAFE(item, next, list) \
513 for (item = (list)->pstNext, next = (item)->pstNext; \
514 (item) != (list); \
515 item = next, next = (item)->pstNext)
516
517 /**
518 * @ingroup shell_list
519 * @brief Initialize a double linked list.
520 *
521 * @par Description:
522 * This API is used to initialize a double linked list.
523 * @attention
524 * <ul>
525 * <li>None.</li>
526 * </ul>
527 *
528 * @param list [IN] Pointer to the doubly linked list to be traversed.
529 *
530 * @retval None.
531 * @par Dependency:
532 * <ul><li>shell_list.h: the header file that contains the API declaration.</li></ul>
533 * @see
534 */
535 #define SH_LIST_HEAD(list) SH_List list = { &(list), &(list) }
536
537 #define SH_ListPeekHeadType(list, type, element) do { \
538 type *__t; \
539 if ((list)->pstNext == list) { \
540 __t = NULL; \
541 } else { \
542 __t = SH_LIST_ENTRY((list)->pstNext, type, element); \
543 } \
544 __t; \
545 } while (0)
546
547 #define SH_ListRemoveHeadType(list, type, element) do { \
548 type *__t; \
549 if ((list)->pstNext == list) { \
550 __t = NULL; \
551 } else { \
552 __t = SH_LIST_ENTRY((list)->pstNext, type, element); \
553 SH_ListDelete((list)->pstNext); \
554 } \
555 __t; \
556 } while (0)
557
558 #define SH_ListNextType(list, item, type, element) do { \
559 type *__t; \
560 if ((item)->pstNext == list) { \
561 __t = NULL; \
562 } else { \
563 __t = SH_LIST_ENTRY((item)->pstNext, type, element); \
564 } \
565 __t; \
566 } while (0)
567
568 #ifdef __cplusplus
569 #if __cplusplus
570 }
571 #endif /* __cplusplus */
572 #endif /* __cplusplus */
573
574 #endif /* _SHELL_LIST_H */
575