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