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