26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 #include "ucx/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)); |
332 } |
334 } |
333 |
335 |
334 alfree(alloc, e); |
336 alfree(alloc, e); |
335 return l; |
337 return l; |
336 } |
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 } |