src/ucx/list.c

changeset 385
a1f4cb076d2f
parent 260
4779a6fb4fbe
child 415
d938228c382e
equal deleted inserted replaced
210:21274e5950af 385:a1f4cb076d2f
1 /* 1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 * 3 *
4 * Copyright 2016 Olaf Wintermann. All rights reserved. 4 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "list.h" 29 #include "ucx/list.h"
30 30
31 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { 31 UcxList *ucx_list_clone(const UcxList *l, copy_func fnc, void *data) {
32 return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data); 32 return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data);
33 } 33 }
34 34
35 UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l, 35 UcxList *ucx_list_clone_a(UcxAllocator *alloc, const UcxList *l,
36 copy_func fnc, void *data) { 36 copy_func fnc, void *data) {
37 UcxList *ret = NULL; 37 UcxList *ret = NULL;
38 while (l) { 38 while (l) {
39 if (fnc) { 39 if (fnc) {
40 ret = ucx_list_append_a(alloc, ret, fnc(l->data, data)); 40 ret = ucx_list_append_a(alloc, ret, fnc(l->data, data));
75 alfree(alloc, f); 75 alfree(alloc, f);
76 } 76 }
77 } 77 }
78 78
79 void ucx_list_free_content(UcxList* list, ucx_destructor destr) { 79 void ucx_list_free_content(UcxList* list, ucx_destructor destr) {
80 if (!destr) destr = free;
80 while (list != NULL) { 81 while (list != NULL) {
81 destr(list->data); 82 destr(list->data);
82 list = list->next; 83 list = list->next;
83 } 84 }
84 } 85 }
169 } 170 }
170 171
171 return (UcxList*)(index == 0 ? e : NULL); 172 return (UcxList*)(index == 0 ? e : NULL);
172 } 173 }
173 174
174 ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { 175 ssize_t ucx_list_find(const UcxList *l, void *elem,
176 cmp_func fnc, void *cmpdata) {
175 ssize_t index = 0; 177 ssize_t index = 0;
176 UCX_FOREACH(e, l) { 178 UCX_FOREACH(e, l) {
177 if (fnc) { 179 if (fnc) {
178 if (fnc(elem, e->data, cmpdata) == 0) { 180 if (fnc(elem, e->data, cmpdata) == 0) {
179 return index; 181 return index;
186 index++; 188 index++;
187 } 189 }
188 return -1; 190 return -1;
189 } 191 }
190 192
191 int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { 193 int ucx_list_contains(const UcxList *l, void *elem,
194 cmp_func fnc, void *cmpdata) {
192 return ucx_list_find(l, elem, fnc, cmpdata) > -1; 195 return ucx_list_find(l, elem, fnc, cmpdata) > -1;
193 } 196 }
194 197
195 size_t ucx_list_size(const UcxList *l) { 198 size_t ucx_list_size(const UcxList *l) {
196 if (l == NULL) return 0; 199 if (l == NULL) return 0;
203 } 206 }
204 207
205 return s; 208 return s;
206 } 209 }
207 210
208 static UcxList *ucx_list_sort_merge(int length, 211 static UcxList *ucx_list_sort_merge(size_t length,
209 UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re, 212 UcxList* ls, UcxList* le, UcxList* re,
210 cmp_func fnc, void* data) { 213 cmp_func fnc, void* data) {
211 214
212 UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length); 215 UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
213 UcxList *rc, *lc; 216 UcxList *rc, *lc;
214 217
215 lc = ls; rc = le; 218 lc = ls; rc = le;
216 int n = 0; 219 size_t n = 0;
217 while (lc && lc != le && rc != re) { 220 while (lc && lc != le && rc != re) {
218 if (fnc(lc->data, rc->data, data) <= 0) { 221 if (fnc(lc->data, rc->data, data) <= 0) {
219 sorted[n] = lc; 222 sorted[n] = lc;
220 lc = lc->next; 223 lc = lc->next;
221 } else { 224 } else {
252 if (l == NULL) { 255 if (l == NULL) {
253 return NULL; 256 return NULL;
254 } 257 }
255 258
256 UcxList *lc; 259 UcxList *lc;
257 int ln = 1; 260 size_t ln = 1;
258 261
259 UcxList *restrict ls = l, *restrict le, *restrict re; 262 UcxList *ls = l, *le, *re;
260 263
261 // check how many elements are already sorted 264 // check how many elements are already sorted
262 lc = ls; 265 lc = ls;
263 while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) { 266 while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
264 lc = lc->next; 267 lc = lc->next;
268 271
269 if (le == NULL) { 272 if (le == NULL) {
270 return l; // this list is already sorted :) 273 return l; // this list is already sorted :)
271 } else { 274 } else {
272 UcxList *rc; 275 UcxList *rc;
273 int rn = 1; 276 size_t rn = 1;
274 rc = le; 277 rc = le;
275 // skip already sorted elements 278 // skip already sorted elements
276 while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { 279 while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
277 rc = rc->next; 280 rc = rc->next;
278 rn++; 281 rn++;
331 } 334 }
332 335
333 alfree(alloc, e); 336 alfree(alloc, e);
334 return l; 337 return l;
335 } 338 }
339
340
341 static UcxList* ucx_list_setoperation_a(UcxAllocator *allocator,
342 UcxList const *left, UcxList const *right,
343 cmp_func cmpfnc, void* cmpdata,
344 copy_func cpfnc, void* cpdata,
345 int op) {
346
347 UcxList *res = NULL;
348 UcxList *cur = NULL;
349 const UcxList *src = left;
350
351 do {
352 UCX_FOREACH(node, src) {
353 void* elem = node->data;
354 if (
355 (op == 0 && !ucx_list_contains(res, elem, cmpfnc, cmpdata)) ||
356 (op == 1 && ucx_list_contains(right, elem, cmpfnc, cmpdata)) ||
357 (op == 2 && !ucx_list_contains(right, elem, cmpfnc, cmpdata))) {
358 UcxList *nl = almalloc(allocator, sizeof(UcxList));
359 nl->prev = cur;
360 nl->next = NULL;
361 if (cpfnc) {
362 nl->data = cpfnc(elem, cpdata);
363 } else {
364 nl->data = elem;
365 }
366 if (cur != NULL)
367 cur->next = nl;
368 cur = nl;
369 if (res == NULL)
370 res = cur;
371 }
372 }
373 if (op == 0 && src == left)
374 src = right;
375 else
376 src = NULL;
377 } while (src != NULL);
378
379 return res;
380 }
381
382 UcxList* ucx_list_union(UcxList const *left, UcxList const *right,
383 cmp_func cmpfnc, void* cmpdata,
384 copy_func cpfnc, void* cpdata) {
385 return ucx_list_union_a(ucx_default_allocator(),
386 left, right, cmpfnc, cmpdata, cpfnc, cpdata);
387 }
388
389 UcxList* ucx_list_union_a(UcxAllocator *allocator,
390 UcxList const *left, UcxList const *right,
391 cmp_func cmpfnc, void* cmpdata,
392 copy_func cpfnc, void* cpdata) {
393
394 return ucx_list_setoperation_a(allocator, left, right,
395 cmpfnc, cmpdata, cpfnc, cpdata, 0);
396 }
397
398 UcxList* ucx_list_intersection(UcxList const *left, UcxList const *right,
399 cmp_func cmpfnc, void* cmpdata,
400 copy_func cpfnc, void* cpdata) {
401 return ucx_list_intersection_a(ucx_default_allocator(), left, right,
402 cmpfnc, cmpdata, cpfnc, cpdata);
403 }
404
405 UcxList* ucx_list_intersection_a(UcxAllocator *allocator,
406 UcxList const *left, UcxList const *right,
407 cmp_func cmpfnc, void* cmpdata,
408 copy_func cpfnc, void* cpdata) {
409
410 return ucx_list_setoperation_a(allocator, left, right,
411 cmpfnc, cmpdata, cpfnc, cpdata, 1);
412 }
413
414 UcxList* ucx_list_difference(UcxList const *left, UcxList const *right,
415 cmp_func cmpfnc, void* cmpdata,
416 copy_func cpfnc, void* cpdata) {
417 return ucx_list_difference_a(ucx_default_allocator(), left, right,
418 cmpfnc, cmpdata, cpfnc, cpdata);
419 }
420
421 UcxList* ucx_list_difference_a(UcxAllocator *allocator,
422 UcxList const *left, UcxList const *right,
423 cmp_func cmpfnc, void* cmpdata,
424 copy_func cpfnc, void* cpdata) {
425
426 return ucx_list_setoperation_a(allocator, left, right,
427 cmpfnc, cmpdata, cpfnc, cpdata, 2);
428 }

mercurial