libdatatypes 0.3.2
Abstract datatypes for C.
Loading...
Searching...
No Matches
list.c
Go to the documentation of this file.
1/***************************************************************************
2 begin........: June 2012
3 copyright....: Sebastian Fedrau
4 email........: sebastian.fedrau@gmail.com
5 ***************************************************************************/
6
7/***************************************************************************
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License v3 as published by
10 the Free Software Foundation.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License v3 for more details.
16 ***************************************************************************/
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <assert.h>
26
27#include "list.h"
28
29List *
30list_new(CompareFunc compare, FreeFunc free, Pool *pool)
31{
32 assert(compare != NULL);
33
34 List *list = (List *)malloc(sizeof(List));
35
36 if(!list)
37 {
38 perror("malloc()");
39 abort();
40 }
41
42 list_init(list, compare, free, pool);
43
44 return list;
45}
46
47void
48list_init(List *list, CompareFunc compare, FreeFunc free, Pool *pool)
49{
50 assert(list != NULL);
51 assert(compare != NULL);
52
53 memset(list, 0, sizeof(List));
54 list->compare = compare;
55 list->free = free;
56 list->pool = pool;
57}
58
59static void
60_list_item_free(List *list, ListItem *item)
61{
62 assert(list != NULL);
63 assert(item != NULL);
64
65 if(list->free && item->data)
66 {
67 list->free(item->data);
68 }
69
70 if(list->pool)
71 {
72 list->pool->free(list->pool, item);
73 }
74 else
75 {
76 free(item);
77 }
78}
79
80void
82{
83 assert(list != NULL);
84
85 ListItem *iter = list->head;
86
87 while(iter)
88 {
89 ListItem *item = iter;
90
91 iter = iter->next;
92
93 _list_item_free(list, item);
94 }
95}
96
97void
99{
100 assert(list != NULL);
101
102 list_free(list);
103 free(list);
104}
105
106static ListItem *
107_list_item_new(Pool *pool, void *data)
108{
109 ListItem *item = NULL;
110
111 if(pool)
112 {
113 item = (ListItem *)pool->alloc(pool);
114 }
115 else
116 {
117 item = (ListItem *)malloc(sizeof(ListItem));
118
119 if(!item)
120 {
121 perror("malloc()");
122 abort();
123 }
124 }
125
126 memset(item, 0, sizeof(ListItem));
127 item->data = data;
128
129 return item;
130}
131
132ListItem *
133list_append(List *list, void *data)
134{
135 assert(list != NULL);
136 assert(list->count != SIZE_MAX);
137
138 ListItem *item = NULL;
139
140 if(list->count < SIZE_MAX)
141 {
142 item = _list_item_new(list->pool, data);
143
144 if(list->head)
145 {
146 list->tail->next = item;
147 item->prev = list->tail;
148 }
149 else
150 {
151 list->head = item;
152 }
153
154 list->tail = item;
155
156 ++list->count;
157 }
158
159 return item;
160}
161
162ListItem *
163list_prepend(List *list, void *data)
164{
165 assert(list != NULL);
166 assert(list->count != SIZE_MAX);
167
168 ListItem *item = NULL;
169
170 if(list->count < SIZE_MAX)
171 {
172 item = _list_item_new(list->pool, data);
173
174 item->next = list->head;
175
176 if(list->head)
177 {
178 list->head->prev = item;
179 }
180 else
181 {
182 list->tail = item;
183 }
184
185 list->head = item;
186
187 ++list->count;
188 }
189
190 return item;
191}
192
193static ListItem *
194_list_prepend_new_sorted(List *list, void *data)
195{
196 assert(list != NULL);
197 assert(list->compare != NULL);
198 assert(list->count != SIZE_MAX);
199
200 ListItem *item = _list_item_new(list->pool, data);
201 ListItem **ptr = &list->head;
202 bool inserted = false;
203
204 while(*ptr && !inserted)
205 {
206 if(list->compare((*ptr)->data, data) >= 0)
207 {
208 inserted = true;
209
210 item->next = *ptr;
211 item->prev = (*ptr)->prev;
212 (*ptr)->prev = item;
213
214 *ptr = item;
215 }
216 else
217 {
218 ptr = &(*ptr)->prev->next;
219 }
220 }
221
222 ++list->count;
223
224 return item;
225}
226
227ListItem *
228list_insert_sorted(List *list, void *data)
229{
230 assert(list != NULL);
231 assert(list->compare != NULL);
232 assert(list->count != SIZE_MAX);
233
234 ListItem *item = NULL;
235
236 if(list->count < SIZE_MAX)
237 {
238 if(list->count)
239 {
240 if(list->compare(list->tail->data, data) <= 0)
241 {
242 item = list_append(list, data);
243 }
244 else
245 {
246 item = _list_prepend_new_sorted(list, data);
247 }
248 }
249 else
250 {
251 item = _list_item_new(list->pool, data);
252
253 list->head = item;
254 list->tail = item;
255 list->count = 1;
256 }
257 }
258
259 return item;
260}
261
262static void
263_list_detach(List *list, ListItem *item)
264{
265 assert(list != NULL);
266 assert(item != NULL);
267
268 ListItem **offset = &list->head;
269 ListItem **next = &list->tail;
270
271 if(item->prev)
272 {
273 offset = &item->prev->next;
274 }
275
276 if(item->next)
277 {
278 next = &item->next->prev;
279 }
280
281 *offset = item->next;
282 *next = item->prev;
283}
284void
286{
287 assert(list != NULL);
288 assert(list->head != NULL);
289 assert(item != NULL);
290
291 _list_detach(list, item);
292 _list_item_free(list, item);
293
294 --list->count;
295}
296
297void
298list_remove_by_data(List *list, void *data, bool remove_all)
299{
300 assert(list != NULL);
301 assert(list->compare != NULL);
302
303 ListItem *iter = list->head;
304 bool completed = false;
305
306 while(iter && !completed)
307 {
308 ListItem *next = iter->next;
309
310 if(!list->compare(iter->data, data))
311 {
312 completed = !remove_all;
313
314 list_remove(list, iter);
315 }
316
317 iter = next;
318 }
319}
320
321void *
323{
324 assert(list != NULL);
325
326 ListItem *item = list->head;
327 void *data = NULL;
328
329 if(item)
330 {
331 list->head = item->next;
332
333 if(list->head)
334 {
335 list->head->prev = NULL;
336 }
337 else
338 {
339 list->tail = NULL;
340 }
341
342 data = item->data;
343
344 if(list->pool)
345 {
346 list->pool->free(list->pool, item);
347 }
348 else
349 {
350 free(item);
351 }
352
353 --list->count;
354 }
355
356 return data;
357}
358
359static ListItem *
360_list_find(const List *list, ListItem *offset, void const *data)
361{
362 assert(list != NULL);
363
364 ListItem *begin = offset ? offset : list->head;
365 ListItem *end = list->tail;
366
367 while(begin)
368 {
369 if(!list->compare(begin->data, data))
370 {
371 return begin;
372 }
373
374 if(!list->compare(end->data, data))
375 {
376 return end;
377 }
378
379 begin = begin->next;
380
381 if(begin == end)
382 {
383 return NULL;
384 }
385
386 end = end->prev;
387 }
388
389 return NULL;
390}
391
392bool
393list_contains(const List *list, const void *data)
394{
395 assert(list != NULL);
396 assert(list->compare != NULL);
397
398 return _list_find(list, NULL, data) != NULL;
399}
400
401void
403{
404 assert(list != NULL);
405
406 list_free(list);
407
408 list->count = 0;
409 list->head = NULL;
410 list->tail = NULL;
411}
412
413ListItem *
414list_find(const List *list, ListItem *offset, void const *data)
415{
416 assert(list != NULL);
417
418 return _list_find(list, offset, data);
419}
420
421ListItem *
422list_head(const List *list)
423{
424 assert(list != NULL);
425
426 return list->head;
427}
428
429ListItem *
430list_tail(const List *list)
431{
432 assert(list != NULL);
433
434 return list->tail;
435}
436
437size_t
438list_count(const List *list)
439{
440 assert(list != NULL);
441
442 return list->count;
443}
444
445bool
446list_empty(const List *list)
447{
448 assert(list != NULL);
449
450 return list->head == NULL;
451}
452
453void
455{
456 assert(list != NULL);
457 assert(item != NULL);
458
459 if(list->free && item->data)
460 {
461 list->free(item->data);
462 }
463
464 item->data = NULL;
465}
466
int32_t(* CompareFunc)(const void *a, const void *b)
Definition compare.h:30
void(* FreeFunc)(void *p)
Definition datatypes.h:33
List * list_new(CompareFunc compare, FreeFunc free, Pool *pool)
Definition list.c:30
bool list_empty(const List *list)
Definition list.c:446
void list_init(List *list, CompareFunc compare, FreeFunc free, Pool *pool)
Definition list.c:48
ListItem * list_find(const List *list, ListItem *offset, void const *data)
Definition list.c:414
ListItem * list_prepend(List *list, void *data)
Definition list.c:163
ListItem * list_tail(const List *list)
Definition list.c:430
ListItem * list_insert_sorted(List *list, void *data)
Definition list.c:228
void list_remove_by_data(List *list, void *data, bool remove_all)
Definition list.c:298
void list_remove(List *list, ListItem *item)
Definition list.c:285
void list_clear(List *list)
Definition list.c:402
size_t list_count(const List *list)
Definition list.c:438
void list_item_free_data(const List *list, ListItem *item)
Definition list.c:454
ListItem * list_append(List *list, void *data)
Definition list.c:133
void list_free(List *list)
Definition list.c:81
void list_destroy(List *list)
Definition list.c:98
void * list_pop(List *list)
Definition list.c:322
bool list_contains(const List *list, const void *data)
Definition list.c:393
ListItem * list_head(const List *list)
Definition list.c:422
Doubly-linked list.
struct _ListItem * prev
Definition list.h:42
Pool * pool
Definition list.h:62
ListItem * tail
Definition list.h:54
FreeFunc free
Definition list.h:60
void * data
Definition list.h:38
size_t count
Definition list.h:56
ListItem * head
Definition list.h:52
CompareFunc compare
Definition list.h:58
struct _ListItem * next
Definition list.h:40
Doubly-linked list.
Definition list.h:50
Structure holding a list item.
Definition list.h:36
Allocate groups of equal-sized chunks of memory.
Definition pool.h:33
void(* free)(struct _Pool *pool, void *ptr)
Definition pool.h:37
void *(* alloc)(struct _Pool *pool)
Definition pool.h:35