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