Line |
Branch |
Exec |
Source |
1 |
|
|
#include <stdlib.h> |
2 |
|
|
#include <stddef.h> |
3 |
|
|
#include <stdint.h> |
4 |
|
|
#include <stdbool.h> |
5 |
|
|
#include <stdio.h> |
6 |
|
|
#include <errno.h> |
7 |
|
|
|
8 |
|
|
#include "global.h" |
9 |
|
|
#include "list.h" |
10 |
|
|
#include "l_internal.h" |
11 |
|
|
#include "type.h" |
12 |
|
|
|
13 |
|
|
/** |
14 |
|
|
* @brief Allocates and sets up list |
15 |
|
|
* |
16 |
|
|
* @param type The type of structures contained in the list |
17 |
|
|
* @param connect_destroy when the object is destroyed, should the data be |
18 |
|
|
* @return list_t* The set up list. |
19 |
|
|
* |
20 |
|
|
* @warning If returns NULL, allocation failed |
21 |
|
|
*/ |
22 |
|
82 |
list_t* list_create(const type_t* type, bool connect_destroy) { |
23 |
|
82 |
list_t* self = (list_t*)malloc(sizeof(*_self)); |
24 |
|
82 |
_type = type; |
25 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 81 times.
|
82 |
if (_type == NULL) |
26 |
|
1 |
_type = ptr_type; |
27 |
|
82 |
_head.next = &_tail; |
28 |
|
82 |
_head.prev = NULL; |
29 |
|
82 |
_head.data = NULL; |
30 |
|
82 |
_tail.prev = &_head; |
31 |
|
82 |
_tail.next = NULL; |
32 |
|
82 |
_tail.data = NULL; |
33 |
|
82 |
_iter = &_head; |
34 |
|
82 |
_index = -1; |
35 |
|
82 |
_size = 0; |
36 |
|
82 |
_connect_destroy = connect_destroy; |
37 |
|
82 |
_ordered = false; |
38 |
|
82 |
_reversed = false; |
39 |
|
82 |
return (list_t*)_self; |
40 |
|
|
} |
41 |
|
|
|
42 |
|
|
/** |
43 |
|
|
* @brief Takes down and frees list |
44 |
|
|
* |
45 |
|
|
* @param self The list |
46 |
|
|
* @return uint8_t Status code |
47 |
|
|
* [EXIT_SUCCESS] |
48 |
|
|
*/ |
49 |
|
82 |
void list_destroy(list_t* self) { |
50 |
|
82 |
list_clear(self); |
51 |
|
82 |
free(_self); |
52 |
|
82 |
} |
53 |
|
|
|
54 |
|
|
/** |
55 |
|
|
* @brief Creates a copy of this list |
56 |
|
|
* |
57 |
|
|
* @param self The list |
58 |
|
|
* @return list_t* The copy |
59 |
|
|
*/ |
60 |
|
3 |
list_t* list_copy(const list_t* self) { |
61 |
|
3 |
list_t* other = list_create(_type, _connect_destroy); |
62 |
|
3 |
__list_node_t* n = &_head; |
63 |
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 3 times.
|
33 |
while ((n = n->next) != &_tail) |
64 |
|
30 |
list_append(other, type_copy(_type, n->data)); |
65 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 |
if (_reversed) |
66 |
|
1 |
list_reverse(other); |
67 |
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 |
if (_ordered) |
68 |
|
2 |
list_order(other); |
69 |
|
3 |
return other; |
70 |
|
|
} |
71 |
|
|
|
72 |
|
|
/** |
73 |
|
|
* @brief The number of items are in the list |
74 |
|
|
* |
75 |
|
|
* @param self The list |
76 |
|
|
* @return size_t The number of items in the list |
77 |
|
|
*/ |
78 |
|
37 |
size_t list_size(const list_t* self) { |
79 |
|
37 |
return _size; |
80 |
|
|
} |
81 |
|
|
|
82 |
|
|
/** |
83 |
|
|
* @brief Moves the list iterator to the head |
84 |
|
|
* |
85 |
|
|
* @param self The list |
86 |
|
|
* @return uint8_t Status code |
87 |
|
|
* [EXIT_SUCCESS] |
88 |
|
|
*/ |
89 |
|
235 |
uint8_t list_head(list_t* self) { |
90 |
|
235 |
_iter = &_head; |
91 |
|
235 |
_index = -1; |
92 |
|
235 |
return EXIT_SUCCESS; |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
/** |
96 |
|
|
* @brief Moves the list iterator to the tail |
97 |
|
|
* |
98 |
|
|
* @param self The list |
99 |
|
|
* @return uint8_t Status code |
100 |
|
|
* [EXIT_SUCCESS] |
101 |
|
|
*/ |
102 |
|
1711 |
uint8_t list_tail(list_t* self) { |
103 |
|
1711 |
_iter = &_tail; |
104 |
|
1711 |
_index = _size; |
105 |
|
1711 |
return EXIT_SUCCESS; |
106 |
|
|
} |
107 |
|
|
|
108 |
|
|
/** |
109 |
|
|
* @brief Moves the list iterator to the specified index |
110 |
|
|
* |
111 |
|
|
* @param self The list |
112 |
|
|
* @param index The index to go to |
113 |
|
|
* @return uint8_t Status code |
114 |
|
|
* [EXIT_SUCCESS, ERANGE] |
115 |
|
|
*/ |
116 |
|
1928 |
uint8_t list_goto(list_t* self, size_t index) { |
117 |
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 1843 times.
|
1928 |
if (index >= _size) |
118 |
|
85 |
return ERANGE; |
119 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1842 times.
|
1843 |
if (_iter == &_head) |
120 |
|
1 |
list_next(self, NULL); |
121 |
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1843 times.
|
1890 |
while (_index < index) { |
122 |
|
47 |
list_next(self, NULL); |
123 |
|
|
} |
124 |
2/2
✓ Branch 0 taken 1706 times.
✓ Branch 1 taken 1843 times.
|
3549 |
while (_index > index) { |
125 |
|
1706 |
list_prev(self, NULL); |
126 |
|
|
} |
127 |
|
1843 |
return EXIT_SUCCESS; |
128 |
|
|
} |
129 |
|
|
|
130 |
|
|
/** |
131 |
|
|
* @brief Retrieves the item from the list at specified index and |
132 |
|
|
* |
133 |
|
|
* @param self The list |
134 |
|
|
* @param item Out pointer for the item retrieved |
135 |
|
|
* @param index The index of item to retrieve |
136 |
|
|
* @return uint8_t Status code |
137 |
|
|
* [EXIT_SUCCESS, ERANGE] |
138 |
|
|
*/ |
139 |
|
35 |
uint8_t list_at(const list_t* self, list_item_t** item, size_t index) { |
140 |
|
35 |
__list_node_t* n = _head.next; |
141 |
|
35 |
size_t index2 = 0; |
142 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
|
35 |
if (index >= _size) |
143 |
|
1 |
return ERANGE; |
144 |
|
|
|
145 |
|
|
// If the iterator is closer jump there. |
146 |
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9 times.
|
34 |
if (_index <= index) { |
147 |
|
25 |
n = _iter; |
148 |
|
25 |
index2 = _index; |
149 |
|
|
} |
150 |
|
|
|
151 |
|
|
// Move forward to the item |
152 |
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 34 times.
|
70 |
while (index2++ < index) |
153 |
|
36 |
n = n->next; |
154 |
|
34 |
*item = n->data; |
155 |
|
34 |
return EXIT_SUCCESS; |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
/** |
159 |
|
|
* @brief Retrieves the next item from the list and |
160 |
|
|
* @brief increments the list iterator |
161 |
|
|
* |
162 |
|
|
* @param self The list |
163 |
|
|
* @param item Out pointer for the item retrieved |
164 |
|
|
* @return uint8_t Status code |
165 |
|
|
* [EXIT_SUCCESS, ERANGE] |
166 |
|
|
*/ |
167 |
|
2277 |
uint8_t list_next(list_t* self, list_item_t** item) { |
168 |
2/2
✓ Branch 1 taken 125 times.
✓ Branch 2 taken 2152 times.
|
2277 |
if (!list_has_next(self)) |
169 |
|
125 |
return ERANGE; |
170 |
|
2152 |
_iter = _iter->next; |
171 |
|
2152 |
_index++; |
172 |
2/2
✓ Branch 0 taken 2042 times.
✓ Branch 1 taken 110 times.
|
2152 |
if (item != NULL) |
173 |
|
2042 |
*item = _iter->data; |
174 |
|
2152 |
return EXIT_SUCCESS; |
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
/** |
178 |
|
|
* @brief Retrieves the previous item from the list and |
179 |
|
|
* @brief decrements the list iterator |
180 |
|
|
* |
181 |
|
|
* @param self The list |
182 |
|
|
* @param item Out pointer for the item retrieved |
183 |
|
|
* @return uint8_t Status code |
184 |
|
|
* [EXIT_SUCCESS, ERANGE] |
185 |
|
|
*/ |
186 |
|
1718 |
uint8_t list_prev(list_t* self, list_item_t** item) { |
187 |
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1717 times.
|
1718 |
if (!list_has_prev(self)) |
188 |
|
1 |
return ERANGE; |
189 |
|
1717 |
_iter = _iter->prev; |
190 |
|
1717 |
_index--; |
191 |
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1707 times.
|
1717 |
if (item != NULL) |
192 |
|
10 |
*item = _iter->data; |
193 |
|
1717 |
return EXIT_SUCCESS; |
194 |
|
|
} |
195 |
|
|
|
196 |
|
|
/** |
197 |
|
|
* @brief If list has next item retrievable |
198 |
|
|
* |
199 |
|
|
* @param self The list |
200 |
|
|
* @return true |
201 |
|
|
* @return false |
202 |
|
|
*/ |
203 |
|
2292 |
bool list_has_next(const list_t* self) { |
204 |
4/4
✓ Branch 0 taken 2287 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2160 times.
✓ Branch 3 taken 127 times.
|
2292 |
return _iter != &_tail && _iter->next != &_tail; |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
/** |
208 |
|
|
* @brief If list has next item retrievable |
209 |
|
|
* |
210 |
|
|
* @param self The list |
211 |
|
|
* @return true |
212 |
|
|
* @return false |
213 |
|
|
*/ |
214 |
|
1721 |
bool list_has_prev(const list_t* self) { |
215 |
4/4
✓ Branch 0 taken 1718 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1717 times.
✓ Branch 3 taken 1 times.
|
1721 |
return _iter != &_head && _iter->prev != &_head; |
216 |
|
|
} |
217 |
|
|
|
218 |
|
|
/** |
219 |
|
|
* @brief Append an item to the end of the list |
220 |
|
|
* |
221 |
|
|
* @param self The list |
222 |
|
|
* @param item The item to append |
223 |
|
|
* @return uint8_t Status code |
224 |
|
|
* [EXIT_SUCCESS, ENOMEM, ENOTSUP, *ERANGE] |
225 |
|
|
* @warning Append is not allowed for ordered lists, instead use insert |
226 |
|
|
*/ |
227 |
|
1591 |
uint8_t list_append(list_t* self, list_item_t* item) { |
228 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1590 times.
|
1591 |
if (_ordered) |
229 |
|
1 |
return ENOTSUP; |
230 |
|
1590 |
return list_place(self, item, _size); |
231 |
|
|
} |
232 |
|
|
|
233 |
|
|
/** |
234 |
|
|
* @brief Places an item at specified index of the list |
235 |
|
|
* |
236 |
|
|
* @param self The list |
237 |
|
|
* @param item The item to place |
238 |
|
|
* @param index The index to place item at |
239 |
|
|
* @return uint8_t Status code |
240 |
|
|
* [EXIT_SUCCESS, ENOMEM, ENOTSUP, ERANGE] |
241 |
|
|
* @warning Place is not allowed for ordered lists, instead use insert |
242 |
|
|
*/ |
243 |
|
1612 |
uint8_t list_place(list_t* self, list_item_t* item, size_t index) { |
244 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1611 times.
|
1612 |
if (_ordered) |
245 |
|
1 |
return ENOTSUP; |
246 |
|
|
uint8_t err; |
247 |
2/2
✓ Branch 0 taken 1600 times.
✓ Branch 1 taken 11 times.
|
1611 |
if (index == _size) { |
248 |
|
1600 |
list_tail(self); |
249 |
|
|
} else { |
250 |
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
|
11 |
if ((err = list_goto(self, index))) |
251 |
|
1 |
return err; |
252 |
|
|
} |
253 |
|
1610 |
return __list_node_insert(self, item); |
254 |
|
|
} |
255 |
|
|
|
256 |
|
|
/** |
257 |
|
|
* @brief Inserts an item into the list |
258 |
|
|
* @note For unordered lists item is placed at iterator |
259 |
|
|
* |
260 |
|
|
* @param self The list |
261 |
|
|
* @param item The item to insert |
262 |
|
|
* @return uint8_t Status code |
263 |
|
|
* [EXIT_SUCCESS, ERANGE, ENOMEM] |
264 |
|
|
*/ |
265 |
|
217 |
uint8_t list_insert(list_t* self, list_item_t* item) { |
266 |
4/4
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 177 times.
✓ Branch 3 taken 20 times.
|
217 |
if (_ordered && _size > 0) { |
267 |
|
177 |
list_item_t* item2 = NULL; |
268 |
|
177 |
list_head(self); |
269 |
|
177 |
list_next(self, &item2); |
270 |
|
177 |
while ( |
271 |
4/4
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 143 times.
✓ Branch 3 taken 438 times.
✓ Branch 4 taken 23 times.
|
604 |
(!_reversed && type_cmp(_type, item, item2) > 0) || |
272 |
4/4
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 67 times.
|
166 |
(_reversed && type_cmp(_type, item, item2) < 0) |
273 |
|
|
) { |
274 |
2/2
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 427 times.
|
514 |
if (list_next(self, &item2)) { |
275 |
|
87 |
list_tail(self); |
276 |
|
87 |
break; |
277 |
|
|
} |
278 |
|
|
} |
279 |
|
|
} |
280 |
|
217 |
return __list_node_insert(self, item); |
281 |
|
|
} |
282 |
|
|
|
283 |
|
|
/** |
284 |
|
|
* @brief Deletes all items from the list |
285 |
|
|
* |
286 |
|
|
* @param self The list |
287 |
|
|
* @return uint8_t Status code |
288 |
|
|
* [EXIT_SUCCESS, *ERANGE] |
289 |
|
|
*/ |
290 |
|
84 |
uint8_t list_clear(list_t* self) { |
291 |
2/2
✓ Branch 1 taken 1804 times.
✓ Branch 2 taken 84 times.
|
1888 |
while (!list_delete(self, 0)); |
292 |
|
84 |
return EXIT_SUCCESS; |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
/** |
296 |
|
|
* @brief Delete item a specified index from the list |
297 |
|
|
* |
298 |
|
|
* @param self The list |
299 |
|
|
* @param index The index of the item to delete |
300 |
|
|
* @return uint8_t Status code |
301 |
|
|
* [EXIT_SUCCESS, ERANGE] |
302 |
|
|
*/ |
303 |
|
1898 |
uint8_t list_delete(list_t* self, size_t index) { |
304 |
|
|
uint8_t err; |
305 |
2/2
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 1814 times.
|
1898 |
if ((err = list_goto(self, index))) |
306 |
|
84 |
return err; |
307 |
|
1814 |
return __list_node_delete(self, _iter); |
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
/** |
311 |
|
|
* @brief Removes first instance of item from the list |
312 |
|
|
* |
313 |
|
|
* @param self The list |
314 |
|
|
* @param item The item to remove from the list |
315 |
|
|
* @return uint8_t Status code |
316 |
|
|
* [EXIT_SUCCESS, ENOENT, *ERANGE] |
317 |
|
|
*/ |
318 |
|
6 |
uint8_t list_remove(list_t* self, const list_item_t* item) { |
319 |
|
|
list_item_t* item2; |
320 |
|
6 |
list_head(self); |
321 |
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 1 times.
|
46 |
while (!list_next(self, &item2)) { |
322 |
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 36 times.
|
39 |
if (!type_cmp(_type, item, item2)) { |
323 |
|
3 |
__list_node_delete(self, _iter); |
324 |
|
3 |
return EXIT_SUCCESS; |
325 |
|
36 |
} else if ( |
326 |
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 21 times.
|
36 |
_ordered && |
327 |
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 17 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
|
21 |
((!_reversed && type_cmp(_type, item, item2) < 0) || |
328 |
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 1 times.
|
20 |
(_reversed && type_cmp(_type, item, item2) > 0)) |
329 |
|
|
) { |
330 |
|
|
break; |
331 |
|
|
} |
332 |
|
|
} |
333 |
|
3 |
return ENOENT; |
334 |
|
|
} |
335 |
|
|
|
336 |
|
|
/** |
337 |
|
|
* @brief Removes all instances of item from the list |
338 |
|
|
* |
339 |
|
|
* @param self The list |
340 |
|
|
* @param item The item to remove from the list |
341 |
|
|
* @return uint8_t Status code |
342 |
|
|
* [EXIT_SUCCESS, ENOENT, *ERANGE] |
343 |
|
|
*/ |
344 |
|
7 |
uint8_t list_purge(list_t* self, const list_item_t* item) { |
345 |
|
7 |
bool found = false; |
346 |
|
7 |
list_head(self); |
347 |
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 4 times.
|
56 |
while (!list_next(self, NULL)) { |
348 |
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 50 times.
|
62 |
while (_iter != &_tail && !type_cmp(_type, item, _iter->data)) { |
349 |
|
10 |
__list_node_delete(self, _iter); |
350 |
|
10 |
found = true; |
351 |
|
|
} |
352 |
|
52 |
if ( |
353 |
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 20 times.
|
52 |
_ordered && |
354 |
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 15 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 2 times.
|
32 |
((!_reversed && type_cmp(_type, item, _iter->data) < 0) || |
355 |
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 1 times.
|
30 |
(_reversed && type_cmp(_type, item, _iter->data) > 0)) |
356 |
|
|
) { |
357 |
|
|
break; |
358 |
|
|
} |
359 |
|
|
} |
360 |
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
7 |
if (!found) |
361 |
|
2 |
return ENOENT; |
362 |
|
5 |
return EXIT_SUCCESS; |
363 |
|
|
} |
364 |
|
|
|
365 |
|
|
/** |
366 |
|
|
* @brief Reverses the order of the items in the list |
367 |
|
|
* |
368 |
|
|
* @param self The list |
369 |
|
|
* @return uint8_t Status code |
370 |
|
|
* [EXIT_SUCCESS] |
371 |
|
|
*/ |
372 |
|
11 |
uint8_t list_reverse(list_t* self) { |
373 |
|
11 |
__list_node_t* n1 = &_head; |
374 |
|
11 |
__list_node_t* n2 = &_tail; |
375 |
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 10 times.
|
36 |
while (n1 != n2 && n2->next != n1) { |
376 |
|
|
list_item_t* temp; |
377 |
|
25 |
temp = n1->data; |
378 |
|
25 |
n1->data = n2->data; |
379 |
|
25 |
n2->data = temp; |
380 |
|
25 |
n1 = n1->next; |
381 |
|
25 |
n2 = n2->prev; |
382 |
|
|
} |
383 |
|
11 |
_reversed = !_reversed; |
384 |
|
11 |
return EXIT_SUCCESS; |
385 |
|
|
} |
386 |
|
|
|
387 |
|
|
/** |
388 |
|
|
* @brief Orders the items of the list and redefines the list as ordered |
389 |
|
|
* |
390 |
|
|
* @param self The list |
391 |
|
|
* @return uint8_t Status code |
392 |
|
|
* [EXIT_SUCCESS] |
393 |
|
|
*/ |
394 |
|
25 |
uint8_t list_order(list_t* self) { |
395 |
|
25 |
_ordered = true; |
396 |
|
25 |
__list_node_t* n = &_head; |
397 |
4/4
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 137 times.
✓ Branch 3 taken 3 times.
|
162 |
while ((n = n->next) != &_tail && n->next != &_tail) { |
398 |
|
137 |
if ( |
399 |
4/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 56 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 45 times.
|
137 |
(_reversed && type_cmp(_type, n->data, n->next->data) < 0) || |
400 |
4/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 36 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 35 times.
|
92 |
(!_reversed && type_cmp(_type, n->data, n->next->data) > 0) |
401 |
|
|
) { |
402 |
|
66 |
void* tmp = n->data; |
403 |
|
66 |
n->data = n->next->data; |
404 |
|
66 |
n->next->data = tmp; |
405 |
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 11 times.
|
66 |
if (n->prev != &_head) |
406 |
|
55 |
n = n->prev->prev; |
407 |
|
|
} |
408 |
|
|
} |
409 |
|
25 |
return EXIT_SUCCESS; |
410 |
|
|
} |
411 |
|
|
|
412 |
|
|
/** |
413 |
|
|
* @brief Redefine the current list as unordered |
414 |
|
|
* |
415 |
|
|
* @param self The list |
416 |
|
|
* @return uint8_t Status code |
417 |
|
|
* [EXIT_SUCCESS] |
418 |
|
|
*/ |
419 |
|
1 |
uint8_t list_unorder(list_t* self) { |
420 |
|
1 |
_ordered = false; |
421 |
|
1 |
return EXIT_SUCCESS; |
422 |
|
|
} |
423 |
|
|
|
424 |
|
|
/** |
425 |
|
|
* @brief Finds the index of the first instance of specified item in the list |
426 |
|
|
* |
427 |
|
|
* @param self The list |
428 |
|
|
* @param index Out pointer for the index |
429 |
|
|
* @param item the item to find |
430 |
|
|
* @return uint8_t Status code |
431 |
|
|
* [EXIT_SUCCESS, ENOENT] |
432 |
|
|
*/ |
433 |
|
41 |
uint8_t list_indexof( |
434 |
|
|
const list_t* self, |
435 |
|
|
size_t* index, |
436 |
|
|
const list_item_t* item |
437 |
|
|
) { |
438 |
|
41 |
__list_node_t* n = &_head; |
439 |
|
41 |
size_t index2 = 0; |
440 |
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 3 times.
|
222 |
while ((n = n->next) != &_tail) { |
441 |
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 183 times.
|
219 |
if (!type_cmp(_type, item, n->data)) { |
442 |
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9 times.
|
36 |
if (index != NULL) |
443 |
|
27 |
*index = index2; |
444 |
|
36 |
return EXIT_SUCCESS; |
445 |
|
183 |
} else if ( |
446 |
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 9 times.
|
183 |
_ordered && |
447 |
4/4
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 50 times.
✓ Branch 3 taken 123 times.
✓ Branch 4 taken 1 times.
|
174 |
((!_reversed && type_cmp(_type, item, n->data) < 0) || |
448 |
4/4
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 123 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 1 times.
|
173 |
(_reversed && type_cmp(_type, item, n->data) > 0)) |
449 |
|
|
) { |
450 |
|
|
break; |
451 |
|
|
} |
452 |
|
181 |
index2++; |
453 |
|
|
} |
454 |
|
5 |
return ENOENT; |
455 |
|
|
} |
456 |
|
|
|
457 |
|
|
/** |
458 |
|
|
* @brief If the list contains the specified item |
459 |
|
|
* |
460 |
|
|
* @param self The list |
461 |
|
|
* @param item The item to check for |
462 |
|
|
* @return true |
463 |
|
|
* @return false |
464 |
|
|
*/ |
465 |
|
10 |
bool list_contains(const list_t* self, const list_item_t* item) { |
466 |
|
10 |
return list_indexof(self, NULL, item) == EXIT_SUCCESS; |
467 |
|
|
} |
468 |
|
|
|
469 |
|
|
/** |
470 |
|
|
* @brief Compares two lists |
471 |
|
|
* |
472 |
|
|
* @param self The list |
473 |
|
|
* @param other The list to compare to |
474 |
|
|
* @return int |
475 |
|
|
* >0: self > other |
476 |
|
|
* <0: self < other |
477 |
|
|
* =0: self = other |
478 |
|
|
*/ |
479 |
|
9 |
int list_cmp(const list_t* self, const list_t* other) { |
480 |
|
9 |
__list_node_t* n1 = &_head; |
481 |
|
9 |
__list_node_t* n2 = &(((__list_t*)other)->head); |
482 |
|
9 |
int cmp = 0; |
483 |
|
9 |
const type_t* type = _type; |
484 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
|
9 |
if (type != (((__list_t*)other)->type)) |
485 |
|
1 |
type = ptr_type; |
486 |
|
9 |
while ( |
487 |
|
117 |
(n1 = n1->next) != &_tail && |
488 |
6/6
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 51 times.
✓ Branch 5 taken 5 times.
|
116 |
(n2 = n2->next) != &(((__list_t*)other)->tail) && |
489 |
|
56 |
!(cmp = type_cmp(type, n1->data, n2->data)) |
490 |
|
|
); |
491 |
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
|
9 |
if (n1 == &_tail && n2->next != &(((__list_t*)other)->tail)) |
492 |
|
1 |
cmp = -1; |
493 |
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 |
else if (n2 == &(((__list_t*)other)->tail)) |
494 |
|
1 |
cmp = 1; |
495 |
|
9 |
return cmp; |
496 |
|
|
} |
497 |
|
|
|
498 |
|
|
/** |
499 |
|
|
* @brief Returns the type with this list |
500 |
|
|
* |
501 |
|
|
* @param self The list |
502 |
|
|
* @return const type_t* The type with this list |
503 |
|
|
*/ |
504 |
|
2 |
const type_t* list_typeof(const list_t* self) { |
505 |
|
2 |
return _type; |
506 |
|
|
} |
507 |
|
|
|
508 |
|
|
/** |
509 |
|
|
* @brief Inserts item node at the current iterator location |
510 |
|
|
* |
511 |
|
|
* @param self The list |
512 |
|
|
* @param item The item to insert |
513 |
|
|
* @return uint8_t Status code |
514 |
|
|
* [EXIT_SUCCESS, ENOMEM] |
515 |
|
|
*/ |
516 |
|
1827 |
uint8_t __list_node_insert(list_t* self, list_item_t* item) { |
517 |
|
1827 |
__list_node_t* n = (__list_node_t*)malloc(sizeof(*n)); |
518 |
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1797 times.
|
1827 |
if (_iter == &_head) { |
519 |
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 21 times.
|
30 |
if (_size > 0) |
520 |
|
9 |
list_next(self, NULL); |
521 |
|
|
else |
522 |
|
21 |
list_tail(self); |
523 |
|
|
} |
524 |
|
1827 |
n->data = item; |
525 |
|
1827 |
n->next = _iter; |
526 |
|
1827 |
n->prev = _iter->prev; |
527 |
|
1827 |
n->next->prev = n; |
528 |
|
1827 |
n->prev->next = n; |
529 |
|
1827 |
_iter = n; |
530 |
|
1827 |
_size++; |
531 |
|
1827 |
return EXIT_SUCCESS; |
532 |
|
|
} |
533 |
|
|
|
534 |
|
|
/** |
535 |
|
|
* @brief Deletes specified node from the list |
536 |
|
|
* |
537 |
|
|
* @param self The list |
538 |
|
|
* @param n The node to delete |
539 |
|
|
* @return uint8_t Status code |
540 |
|
|
* [EXIT_SUCCESS] |
541 |
|
|
*/ |
542 |
|
1827 |
uint8_t __list_node_delete(list_t* self, __list_node_t* n) { |
543 |
|
1827 |
n->prev->next = n->next; |
544 |
|
1827 |
n->next->prev = n->prev; |
545 |
|
1827 |
_size--; |
546 |
|
1827 |
_iter = n->next; |
547 |
2/2
✓ Branch 0 taken 1611 times.
✓ Branch 1 taken 216 times.
|
1827 |
if (_connect_destroy) |
548 |
|
1611 |
type_destroy(_type, n->data); |
549 |
|
1827 |
free(n); |
550 |
|
1827 |
return EXIT_SUCCESS; |
551 |
|
|
} |
552 |
|
|
|
553 |
|
|
/** |
554 |
|
|
* @brief Prints the list to stdout |
555 |
|
|
* |
556 |
|
|
* @param f The file to write to |
557 |
|
|
* @param self The list |
558 |
|
|
*/ |
559 |
|
1 |
void __list_print(FILE* f, const list_t* self) { |
560 |
|
1 |
rope_t* rope = type_repr(list_type, self); |
561 |
|
1 |
char* str = rope_str(rope); |
562 |
|
1 |
fprintf(f, "%s\n", str); |
563 |
|
1 |
free(str); |
564 |
|
1 |
rope_destroy(rope); |
565 |
|
1 |
} |
566 |
|
|
|