1 /*
2 * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * @file list.h
9 * @brief List primitives for libmetal.
10 */
11
12 #ifndef __METAL_LIST__H__
13 #define __METAL_LIST__H__
14
15 #include <stdbool.h>
16 #include <stdlib.h>
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 /** \defgroup list List Primitives
23 * @{
24 */
25
26 struct metal_list {
27 struct metal_list *next, *prev;
28 };
29
30 /*
31 * METAL_INIT_LIST - used for initializing an list element in a static struct
32 * or global
33 */
34 #define METAL_INIT_LIST(name) { .next = &name, .prev = &name }
35 /*
36 * METAL_DECLARE_LIST - used for defining and initializing a global or
37 * static singleton list
38 */
39 #define METAL_DECLARE_LIST(name) \
40 struct metal_list name = METAL_INIT_LIST(name)
41
metal_list_init(struct metal_list * list)42 static inline void metal_list_init(struct metal_list *list)
43 {
44 list->prev = list;
45 list->next = list;
46 }
47
metal_list_add_before(struct metal_list * node,struct metal_list * new_node)48 static inline void metal_list_add_before(struct metal_list *node,
49 struct metal_list *new_node)
50 {
51 new_node->prev = node->prev;
52 new_node->next = node;
53 new_node->next->prev = new_node;
54 new_node->prev->next = new_node;
55 }
56
metal_list_add_after(struct metal_list * node,struct metal_list * new_node)57 static inline void metal_list_add_after(struct metal_list *node,
58 struct metal_list *new_node)
59 {
60 new_node->prev = node;
61 new_node->next = node->next;
62 new_node->next->prev = new_node;
63 new_node->prev->next = new_node;
64 }
65
metal_list_add_head(struct metal_list * list,struct metal_list * node)66 static inline void metal_list_add_head(struct metal_list *list,
67 struct metal_list *node)
68 {
69 metal_list_add_after(list, node);
70 }
71
metal_list_add_tail(struct metal_list * list,struct metal_list * node)72 static inline void metal_list_add_tail(struct metal_list *list,
73 struct metal_list *node)
74 {
75 metal_list_add_before(list, node);
76 }
77
metal_list_is_empty(struct metal_list * list)78 static inline int metal_list_is_empty(struct metal_list *list)
79 {
80 return list->next == list;
81 }
82
metal_list_del(struct metal_list * node)83 static inline void metal_list_del(struct metal_list *node)
84 {
85 node->next->prev = node->prev;
86 node->prev->next = node->next;
87 node->prev = node;
88 node->next = node;
89 }
90
metal_list_first(struct metal_list * list)91 static inline struct metal_list *metal_list_first(struct metal_list *list)
92 {
93 return metal_list_is_empty(list) ? NULL : list->next;
94 }
95
96 /**
97 * @brief Used for iterating over a list
98 *
99 * @param list Pointer to the head node of the list
100 * @param node Pointer to each node in the list during iteration
101 */
102 #define metal_list_for_each(list, node) \
103 for ((node) = (list)->next; \
104 (node) != (list); \
105 (node) = (node)->next)
106
107 /**
108 * @brief Used for iterating over a list safely
109 *
110 * @param list Pointer to the head node of the list
111 * @param temp Pointer to the next node's address during iteration
112 * @param node Pointer to each node in the list during iteration
113 */
114 #define metal_list_for_each_safe(list, temp, node) \
115 for ((node) = (list)->next, (temp) = (node)->next; \
116 (node) != (list); \
117 (node) = (temp), (temp) = (node)->next)
118
metal_list_find_node(struct metal_list * list,struct metal_list * node)119 static inline bool metal_list_find_node(struct metal_list *list,
120 struct metal_list *node)
121 {
122 struct metal_list *n;
123
124 metal_list_for_each(list, n) {
125 if (n == node)
126 return true;
127 }
128 return false;
129 }
130 /** @} */
131
132 #ifdef __cplusplus
133 }
134 #endif
135
136 #endif /* __METAL_LIST__H__ */
137