1
2 #include "bt_common.h"
3 #include "osi/allocator.h"
4 #include "osi/list.h"
5 #include "osi/osi.h"
6
7 struct list_node_t {
8 struct list_node_t *next;
9 void *data;
10 };
11
12 typedef struct list_t {
13 list_node_t *head;
14 list_node_t *tail;
15 size_t length;
16 list_free_cb free_cb;
17 } list_t;
18
19 //static list_node_t *list_free_node_(list_t *list, list_node_t *node);
20
21 // Hidden constructor, only to be used by the hash map for the allocation tracker.
22 // Behaves the same as |list_new|, except you get to specify the allocator.
list_new_internal(list_free_cb callback)23 list_t *list_new_internal(list_free_cb callback)
24 {
25 list_t *list = (list_t *) osi_calloc(sizeof(list_t));
26 if (!list) {
27 return NULL;
28 }
29
30 list->head = list->tail = NULL;
31 list->length = 0;
32 list->free_cb = callback;
33 return list;
34 }
35
list_new(list_free_cb callback)36 list_t *list_new(list_free_cb callback)
37 {
38 return list_new_internal(callback);
39 }
40
list_free(list_t * list)41 void list_free(list_t *list)
42 {
43 if (!list) {
44 return;
45 }
46
47 list_clear(list);
48 osi_free(list);
49 }
50
list_is_empty(const list_t * list)51 bool list_is_empty(const list_t *list)
52 {
53 assert(list != NULL);
54 return (list->length == 0);
55 }
56
list_contains(const list_t * list,const void * data)57 bool list_contains(const list_t *list, const void *data)
58 {
59 assert(list != NULL);
60 assert(data != NULL);
61
62 for (const list_node_t *node = list_begin(list); node != list_end(list); node = list_next(node)) {
63 if (list_node(node) == data) {
64 return true;
65 }
66 }
67
68 return false;
69 }
70
list_get_node(const list_t * list,const void * data)71 list_node_t *list_get_node(const list_t *list, const void *data)
72 {
73 assert(list != NULL);
74 assert(data != NULL);
75 list_node_t *p_node_ret = NULL;
76 for (list_node_t *node = list_begin(list); node != list_end(list); node = list_next(node)) {
77 if (list_node(node) == data) {
78 p_node_ret = node;
79 break;
80 }
81 }
82
83 return p_node_ret;
84 }
85
list_length(const list_t * list)86 size_t list_length(const list_t *list)
87 {
88 assert(list != NULL);
89 return list->length;
90 }
91
list_front(const list_t * list)92 void *list_front(const list_t *list)
93 {
94 assert(list != NULL);
95 assert(!list_is_empty(list));
96
97 return list->head->data;
98 }
99
list_back(const list_t * list)100 void *list_back(const list_t *list) {
101 assert(list != NULL);
102 assert(!list_is_empty(list));
103
104 return list->tail->data;
105 }
106
list_back_node(const list_t * list)107 list_node_t *list_back_node(const list_t *list) {
108 assert(list != NULL);
109 assert(!list_is_empty(list));
110
111 return list->tail;
112 }
113
list_insert_after(list_t * list,list_node_t * prev_node,void * data)114 bool list_insert_after(list_t *list, list_node_t *prev_node, void *data) {
115 assert(list != NULL);
116 assert(prev_node != NULL);
117 assert(data != NULL);
118 list_node_t *node = (list_node_t *)osi_calloc(sizeof(list_node_t));
119 if (!node) {
120 OSI_TRACE_ERROR("%s osi_calloc failed.\n", __FUNCTION__ );
121 return false;
122 }
123 node->next = prev_node->next;
124 node->data = data;
125 prev_node->next = node;
126 if (list->tail == prev_node) {
127 list->tail = node;
128 }
129 ++list->length;
130 return true;
131 }
132
list_prepend(list_t * list,void * data)133 bool list_prepend(list_t *list, void *data)
134 {
135 assert(list != NULL);
136 assert(data != NULL);
137 list_node_t *node = (list_node_t *)osi_calloc(sizeof(list_node_t));
138 if (!node) {
139 OSI_TRACE_ERROR("%s osi_calloc failed.\n", __FUNCTION__ );
140 return false;
141 }
142 node->next = list->head;
143 node->data = data;
144 list->head = node;
145 if (list->tail == NULL) {
146 list->tail = list->head;
147 }
148 ++list->length;
149 return true;
150 }
151
list_append(list_t * list,void * data)152 bool list_append(list_t *list, void *data)
153 {
154 assert(list != NULL);
155 assert(data != NULL);
156 list_node_t *node = (list_node_t *)osi_calloc(sizeof(list_node_t));
157 if (!node) {
158 OSI_TRACE_ERROR("%s osi_calloc failed.\n", __FUNCTION__ );
159 return false;
160 }
161 node->next = NULL;
162 node->data = data;
163 if (list->tail == NULL) {
164 list->head = node;
165 list->tail = node;
166 } else {
167 list->tail->next = node;
168 list->tail = node;
169 }
170 ++list->length;
171 return true;
172 }
173
list_remove(list_t * list,void * data)174 bool list_remove(list_t *list, void *data)
175 {
176 assert(list != NULL);
177 assert(data != NULL);
178
179 if (list_is_empty(list)) {
180 return false;
181 }
182
183 if (list->head->data == data) {
184 list_node_t *next = list_free_node(list, list->head);
185 if (list->tail == list->head) {
186 list->tail = next;
187 }
188 list->head = next;
189 return true;
190 }
191
192 for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
193 if (node->data == data) {
194 prev->next = list_free_node(list, node);
195 if (list->tail == node) {
196 list->tail = prev;
197 }
198 return true;
199 }
200
201 return false;
202 }
203
list_delete(list_t * list,void * data)204 bool list_delete(list_t *list, void *data)
205 {
206 assert(list != NULL);
207 assert(data != NULL);
208
209 if (list_is_empty(list)) {
210 return false;
211 }
212
213 if (list->head->data == data) {
214 list_node_t *next = list_delete_node(list, list->head);
215 if (list->tail == list->head) {
216 list->tail = next;
217 }
218 list->head = next;
219 return true;
220 }
221
222 for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
223 if (node->data == data) {
224 prev->next = list_delete_node(list, node);
225 if (list->tail == node) {
226 list->tail = prev;
227 }
228 return true;
229 }
230
231 return false;
232 }
233
list_clear(list_t * list)234 void list_clear(list_t *list)
235 {
236 assert(list != NULL);
237 for (list_node_t *node = list->head; node; ) {
238 node = list_free_node(list, node);
239 }
240 list->head = NULL;
241 list->tail = NULL;
242 list->length = 0;
243 }
244
list_foreach(const list_t * list,list_iter_cb callback,void * context)245 list_node_t *list_foreach(const list_t *list, list_iter_cb callback, void *context)
246 {
247 assert(list != NULL);
248 assert(callback != NULL);
249
250 for (list_node_t *node = list->head; node; ) {
251 list_node_t *next = node->next;
252 if (!callback(node->data, context)) {
253 return node;
254 }
255 node = next;
256 }
257 return NULL;
258 }
259
list_begin(const list_t * list)260 list_node_t *list_begin(const list_t *list)
261 {
262 assert(list != NULL);
263 return list->head;
264 }
265
list_end(UNUSED_ATTR const list_t * list)266 list_node_t *list_end(UNUSED_ATTR const list_t *list)
267 {
268 assert(list != NULL);
269 return NULL;
270 }
271
list_next(const list_node_t * node)272 list_node_t *list_next(const list_node_t *node)
273 {
274 assert(node != NULL);
275 return node->next;
276 }
277
list_node(const list_node_t * node)278 void *list_node(const list_node_t *node)
279 {
280 assert(node != NULL);
281 return node->data;
282 }
283
list_free_node(list_t * list,list_node_t * node)284 list_node_t *list_free_node(list_t *list, list_node_t *node)
285 {
286 assert(list != NULL);
287 assert(node != NULL);
288
289 list_node_t *next = node->next;
290
291 if (list->free_cb) {
292 list->free_cb(node->data);
293 }
294 osi_free(node);
295 --list->length;
296
297 return next;
298 }
299
300 // remove the element from list but do not free the node data
list_delete_node(list_t * list,list_node_t * node)301 list_node_t *list_delete_node(list_t *list, list_node_t *node)
302 {
303 assert(list != NULL);
304 assert(node != NULL);
305
306 list_node_t *next = node->next;
307
308 osi_free(node);
309 --list->length;
310
311 return next;
312 }
313