libdatatypes 0.3.2
Abstract datatypes for C.
Loading...
Searching...
No Matches
slist.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 "slist.h"
28
29SList *
30slist_new(CompareFunc compare, FreeFunc free, Pool *pool)
31{
32 assert(compare != NULL);
33
34 SList *list = (SList *)malloc(sizeof(SList));
35
36 if(!list)
37 {
38 perror("malloc()");
39 abort();
40 }
41
42 slist_init(list, compare, free, pool);
43
44 return list;
45}
46
47void
48slist_init(SList *list, CompareFunc compare, FreeFunc free, Pool *pool)
49{
50 assert(list != NULL);
51 assert(compare != NULL);
52
53 memset(list, 0, sizeof(SList));
54 list->compare = compare;
55 list->free = free;
56 list->pool = pool;
57}
58
59static void
60_slist_item_free(SList *list, SListItem *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 SListItem *iter = list->head;
86
87 while(iter)
88 {
89 SListItem *item = iter;
90
91 iter = iter->next;
92
93 _slist_item_free(list, item);
94 }
95}
96
97void
99{
100 assert(list != NULL);
101
102 slist_free(list);
103 free(list);
104}
105
106static SListItem *
107_slist_item_new(Pool *pool, void *data)
108{
109 SListItem *item = NULL;
110
111 if(pool)
112 {
113 item = (SListItem *)pool->alloc(pool);
114 }
115 else
116 {
117 item = (SListItem *)malloc(sizeof(SListItem));
118
119 if(!item)
120 {
121 perror("malloc()");
122 abort();
123 }
124 }
125
126 memset(item, 0, sizeof(SListItem));
127 item->data = data;
128
129 return item;
130}
131
132SListItem *
133slist_append(SList *list, void *data)
134{
135 assert(list != NULL);
136 assert(list->count != SIZE_MAX);
137
138 SListItem *item = NULL;
139
140 if(list->count < SIZE_MAX)
141 {
142 item = _slist_item_new(list->pool, data);
143
144 if(list->head)
145 {
146 list->tail->next = item;
147 }
148 else
149 {
150 list->head = item;
151 }
152
153 list->tail = item;
154
155 ++list->count;
156 }
157
158 return item;
159}
160
161SListItem *
162slist_prepend(SList *list, void *data)
163{
164 assert(list != NULL);
165 assert(list->count != SIZE_MAX);
166
167 SListItem *item = NULL;
168
169 if(list->count < SIZE_MAX)
170 {
171 item = _slist_item_new(list->pool, data);
172
173 if(!list->tail)
174 {
175 list->tail = item;
176 }
177
178 item->next = list->head;
179 list->head = item;
180
181 ++list->count;
182 }
183
184 return item;
185}
186
187static SListItem *
188_slist_prepend_new_sorted(SList *list, void *data)
189{
190 assert(list != NULL);
191 assert(list->compare != NULL);
192 assert(list->count != SIZE_MAX);
193
194 SListItem *item = _slist_item_new(list->pool, data);
195 SListItem **ptr = &list->head;
196 bool inserted = false;
197
198 while(*ptr && !inserted)
199 {
200 if(list->compare((*ptr)->data, data) >= 0)
201 {
202 inserted = true;
203
204 item->next = *ptr;
205 *ptr = item;
206 }
207 else
208 {
209 ptr = &(*ptr)->next;
210 }
211 }
212
213 ++list->count;
214
215 return item;
216}
217
218SListItem *
219slist_insert_sorted(SList *list, void *data)
220{
221 assert(list != NULL);
222 assert(list->compare != NULL);
223 assert(list->count != SIZE_MAX);
224
225 SListItem *item = NULL;
226
227 if(list->count < SIZE_MAX)
228 {
229 if(list->count)
230 {
231 if(list->compare(list->tail->data, data) <= 0)
232 {
233 item = slist_append(list, data);
234 }
235 else
236 {
237 item = _slist_prepend_new_sorted(list, data);
238 }
239 }
240 else
241 {
242 item = _slist_item_new(list->pool, data);
243
244 list->head = item;
245 list->tail = item;
246 list->count = 1;
247 }
248 }
249
250 return item;
251}
252
253void
255{
256 assert(list != NULL);
257 assert(list->head != NULL);
258 assert(item != NULL);
259
260 SListItem **ptr = &list->head;
261 SListItem *tail = NULL;
262 bool found = false;
263
264 while(*ptr && !found)
265 {
266 if(*ptr == item)
267 {
268 found = true;
269
270 if(!item->next)
271 {
272 list->tail = tail;
273 }
274
275 *ptr = item->next;
276 _slist_item_free(list, item);
277
278 --list->count;
279 }
280 else
281 {
282 tail = *ptr;
283 ptr = &(*ptr)->next;
284 }
285 }
286}
287
288void
289slist_remove_by_data(SList *list, void *data, bool remove_all)
290{
291 assert(list != NULL);
292 assert(list->compare != NULL);
293
294 SListItem **ptr = &list->head;
295 SListItem *tail = NULL;
296 bool completed = false;
297
298 while(*ptr && !completed)
299 {
300 if(!list->compare((*ptr)->data, data))
301 {
302 completed = !remove_all;
303
304 SListItem *next = (*ptr)->next;
305
306 if(!next)
307 {
308 list->tail = tail;
309 }
310
311 _slist_item_free(list, *ptr);
312 *ptr = next;
313
314 --list->count;
315 }
316 else
317 {
318 tail = *ptr;
319 ptr = &(*ptr)->next;
320 }
321 }
322}
323
324void *
326{
327 assert(list != NULL);
328
329 void *data = NULL;
330 SListItem *item = list->head;
331
332 if(item)
333 {
334 list->head = item->next;
335
336 if(!list->head)
337 {
338 list->tail = NULL;
339 }
340
341 data = item->data;
342
343 if(list->pool)
344 {
345 list->pool->free(list->pool, item);
346 }
347 else
348 {
349 free(item);
350 }
351
352 --list->count;
353 }
354
355 return data;
356}
357
358static SListItem *
359_slist_find(const SList *list, SListItem *offset, void const *data)
360{
361 assert(list != NULL);
362 assert(list->compare != NULL);
363
364 SListItem *iter = offset ? offset : list->head;
365 SListItem *found = NULL;
366
367 while(iter && !found)
368 {
369 if(!list->compare(iter->data, data))
370 {
371 found = iter;
372 }
373
374 iter = iter->next;
375 }
376
377 return found;
378}
379
380bool
381slist_contains(const SList *list, const void *data)
382{
383 assert(list != NULL);
384 assert(list->compare != NULL);
385
386 return _slist_find(list, NULL, data) != NULL;
387}
388
389void
391{
392 assert(list != NULL);
393
394 slist_free(list);
395
396 list->count = 0;
397 list->head = NULL;
398 list->tail = NULL;
399}
400
401SListItem *
402slist_find(const SList *list, SListItem *offset, void const *data)
403{
404 assert(list != NULL);
405
406 return _slist_find(list, offset, data);
407}
408
409size_t
410slist_count(const SList *list)
411{
412 assert(list != NULL);
413
414 return list->count;
415}
416
417SListItem *
418slist_head(const SList *list)
419{
420 assert(list != NULL);
421
422 return list->head;
423}
424
425bool
426slist_empty(const SList *list)
427{
428 assert(list != NULL);
429
430 return list->head == NULL;
431}
432
433void
435{
436 assert(list != NULL);
437 assert(item != NULL);
438
439 if(list->free && item->data)
440 {
441 list->free(item->data);
442 }
443
444 item->data = NULL;
445}
446
int32_t(* CompareFunc)(const void *a, const void *b)
Definition compare.h:30
void(* FreeFunc)(void *p)
Definition datatypes.h:33
void slist_destroy(SList *list)
Definition slist.c:98
void slist_init(SList *list, CompareFunc compare, FreeFunc free, Pool *pool)
Definition slist.c:48
SListItem * slist_find(const SList *list, SListItem *offset, void const *data)
Definition slist.c:402
SListItem * slist_append(SList *list, void *data)
Definition slist.c:133
void slist_remove_by_data(SList *list, void *data, bool remove_all)
Definition slist.c:289
size_t slist_count(const SList *list)
Definition slist.c:410
SListItem * slist_insert_sorted(SList *list, void *data)
Definition slist.c:219
SList * slist_new(CompareFunc compare, FreeFunc free, Pool *pool)
Definition slist.c:30
void slist_clear(SList *list)
Definition slist.c:390
bool slist_contains(const SList *list, const void *data)
Definition slist.c:381
void slist_item_free_data(const SList *list, SListItem *item)
Definition slist.c:434
void slist_remove(SList *list, SListItem *item)
Definition slist.c:254
SListItem * slist_prepend(SList *list, void *data)
Definition slist.c:162
SListItem * slist_head(const SList *list)
Definition slist.c:418
bool slist_empty(const SList *list)
Definition slist.c:426
void slist_free(SList *list)
Definition slist.c:81
void * slist_pop(SList *list)
Definition slist.c:325
Singly-linked list.
size_t count
Definition slist.h:55
void * data
Definition slist.h:39
SListItem * head
Definition slist.h:51
FreeFunc free
Definition slist.h:59
struct _SListItem * next
Definition slist.h:41
Pool * pool
Definition slist.h:61
CompareFunc compare
Definition slist.h:57
SListItem * tail
Definition slist.h:53
Singly-linked list.
Definition slist.h:49
Structure holding a list item.
Definition slist.h:37
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