• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "osi/include/list.h"
2 
3 #include <bluetooth/log.h>
4 
5 #include "osi/include/allocator.h"
6 
7 using namespace bluetooth;
8 
9 struct list_node_t {
10   struct list_node_t* next;
11   void* data;
12 };
13 
14 typedef struct list_t {
15   list_node_t* head;
16   list_node_t* tail;
17   size_t length;
18   list_free_cb free_cb;
19   const allocator_t* allocator;
20 } list_t;
21 
22 static list_node_t* list_free_node_(list_t* list, list_node_t* node);
23 
24 // Hidden constructor, only to be used by the hash map for the allocation
25 // tracker.
26 // Behaves the same as |list_new|, except you get to specify the allocator.
list_new_internal(list_free_cb callback,const allocator_t * zeroed_allocator)27 static list_t* list_new_internal(list_free_cb callback, const allocator_t* zeroed_allocator) {
28   list_t* list = (list_t*)zeroed_allocator->alloc(sizeof(list_t));
29   if (!list) {
30     return NULL;
31   }
32 
33   list->free_cb = callback;
34   list->allocator = zeroed_allocator;
35   return list;
36 }
37 
list_new(list_free_cb callback)38 list_t* list_new(list_free_cb callback) { return list_new_internal(callback, &allocator_calloc); }
39 
list_free(list_t * list)40 void list_free(list_t* list) {
41   if (!list) {
42     return;
43   }
44 
45   list_clear(list);
46   list->allocator->free(list);
47 }
48 
list_is_empty(const list_t * list)49 bool list_is_empty(const list_t* list) {
50   log::assert_that(list != NULL, "assert failed: list != NULL");
51   return list->length == 0;
52 }
53 
list_contains(const list_t * list,const void * data)54 bool list_contains(const list_t* list, const void* data) {
55   log::assert_that(list != NULL, "assert failed: list != NULL");
56   log::assert_that(data != NULL, "assert failed: data != NULL");
57 
58   for (const list_node_t* node = list_begin(list); node != list_end(list); node = list_next(node)) {
59     if (list_node(node) == data) {
60       return true;
61     }
62   }
63 
64   return false;
65 }
66 
list_length(const list_t * list)67 size_t list_length(const list_t* list) {
68   log::assert_that(list != NULL, "assert failed: list != NULL");
69   return list->length;
70 }
71 
list_front(const list_t * list)72 void* list_front(const list_t* list) {
73   log::assert_that(list != NULL, "assert failed: list != NULL");
74   log::assert_that(!list_is_empty(list), "assert failed: !list_is_empty(list)");
75 
76   return list->head->data;
77 }
78 
list_back(const list_t * list)79 void* list_back(const list_t* list) {
80   log::assert_that(list != NULL, "assert failed: list != NULL");
81   log::assert_that(!list_is_empty(list), "assert failed: !list_is_empty(list)");
82 
83   return list->tail->data;
84 }
85 
list_back_node(const list_t * list)86 list_node_t* list_back_node(const list_t* list) {
87   log::assert_that(list != NULL, "assert failed: list != NULL");
88   log::assert_that(!list_is_empty(list), "assert failed: !list_is_empty(list)");
89 
90   return list->tail;
91 }
92 
list_insert_after(list_t * list,list_node_t * prev_node,void * data)93 bool list_insert_after(list_t* list, list_node_t* prev_node, void* data) {
94   log::assert_that(list != NULL, "assert failed: list != NULL");
95   log::assert_that(prev_node != NULL, "assert failed: prev_node != NULL");
96   log::assert_that(data != NULL, "assert failed: data != NULL");
97 
98   list_node_t* node = (list_node_t*)list->allocator->alloc(sizeof(list_node_t));
99   if (!node) {
100     return false;
101   }
102 
103   node->next = prev_node->next;
104   node->data = data;
105   prev_node->next = node;
106   if (list->tail == prev_node) {
107     list->tail = node;
108   }
109   ++list->length;
110   return true;
111 }
112 
list_prepend(list_t * list,void * data)113 bool list_prepend(list_t* list, void* data) {
114   log::assert_that(list != NULL, "assert failed: list != NULL");
115   log::assert_that(data != NULL, "assert failed: data != NULL");
116 
117   list_node_t* node = (list_node_t*)list->allocator->alloc(sizeof(list_node_t));
118   if (!node) {
119     return false;
120   }
121   node->next = list->head;
122   node->data = data;
123   list->head = node;
124   if (list->tail == NULL) {
125     list->tail = list->head;
126   }
127   ++list->length;
128   return true;
129 }
130 
list_append(list_t * list,void * data)131 bool list_append(list_t* list, void* data) {
132   log::assert_that(list != NULL, "assert failed: list != NULL");
133   log::assert_that(data != NULL, "assert failed: data != NULL");
134 
135   list_node_t* node = (list_node_t*)list->allocator->alloc(sizeof(list_node_t));
136   if (!node) {
137     return false;
138   }
139   node->next = NULL;
140   node->data = data;
141   if (list->tail == NULL) {
142     list->head = node;
143     list->tail = node;
144   } else {
145     list->tail->next = node;
146     list->tail = node;
147   }
148   ++list->length;
149   return true;
150 }
151 
list_remove(list_t * list,void * data)152 bool list_remove(list_t* list, void* data) {
153   log::assert_that(list != NULL, "assert failed: list != NULL");
154   log::assert_that(data != NULL, "assert failed: data != NULL");
155 
156   if (list_is_empty(list)) {
157     return false;
158   }
159 
160   if (list->head->data == data) {
161     list_node_t* next = list_free_node_(list, list->head);
162     if (list->tail == list->head) {
163       list->tail = next;
164     }
165     list->head = next;
166     return true;
167   }
168 
169   for (list_node_t *prev = list->head, *node = list->head->next; node;
170        prev = node, node = node->next) {
171     if (node->data == data) {
172       prev->next = list_free_node_(list, node);
173       if (list->tail == node) {
174         list->tail = prev;
175       }
176       return true;
177     }
178   }
179 
180   return false;
181 }
182 
list_clear(list_t * list)183 void list_clear(list_t* list) {
184   log::assert_that(list != NULL, "assert failed: list != NULL");
185   for (list_node_t* node = list->head; node;) {
186     node = list_free_node_(list, node);
187   }
188   list->head = NULL;
189   list->tail = NULL;
190   list->length = 0;
191 }
192 
list_foreach(const list_t * list,list_iter_cb callback,void * context)193 list_node_t* list_foreach(const list_t* list, list_iter_cb callback, void* context) {
194   log::assert_that(list != NULL, "assert failed: list != NULL");
195   log::assert_that(callback != NULL, "assert failed: callback != NULL");
196 
197   for (list_node_t* node = list->head; node;) {
198     list_node_t* next = node->next;
199     if (!callback(node->data, context)) {
200       return node;
201     }
202     node = next;
203   }
204   return NULL;
205 }
206 
list_begin(const list_t * list)207 list_node_t* list_begin(const list_t* list) {
208   log::assert_that(list != NULL, "assert failed: list != NULL");
209   return list->head;
210 }
211 
list_end(const list_t * list)212 list_node_t* list_end(const list_t* list) {
213   log::assert_that(list != NULL, "assert failed: list != NULL");
214   return NULL;
215 }
216 
list_next(const list_node_t * node)217 list_node_t* list_next(const list_node_t* node) {
218   log::assert_that(node != NULL, "assert failed: node != NULL");
219   return node->next;
220 }
221 
list_node(const list_node_t * node)222 void* list_node(const list_node_t* node) {
223   log::assert_that(node != NULL, "assert failed: node != NULL");
224   return node->data;
225 }
226 
list_free_node_(list_t * list,list_node_t * node)227 static list_node_t* list_free_node_(list_t* list, list_node_t* node) {
228   log::assert_that(list != NULL, "assert failed: list != NULL");
229   log::assert_that(node != NULL, "assert failed: node != NULL");
230 
231   list_node_t* next = node->next;
232 
233   if (list->free_cb) {
234     list->free_cb(node->data);
235   }
236   list->allocator->free(node);
237   --list->length;
238 
239   return next;
240 }
241