--- a/ucx/list.c Sat Dec 05 10:34:10 2020 +0100 +++ b/ucx/list.c Sat Dec 05 11:54:58 2020 +0100 @@ -28,11 +28,11 @@ #include "ucx/list.h" -UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { +UcxList *ucx_list_clone(const UcxList *l, copy_func fnc, void *data) { return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data); } -UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l, +UcxList *ucx_list_clone_a(UcxAllocator *alloc, const UcxList *l, copy_func fnc, void *data) { UcxList *ret = NULL; while (l) { @@ -172,7 +172,8 @@ return (UcxList*)(index == 0 ? e : NULL); } -ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { +ssize_t ucx_list_find(const UcxList *l, void *elem, + cmp_func fnc, void *cmpdata) { ssize_t index = 0; UCX_FOREACH(e, l) { if (fnc) { @@ -189,7 +190,8 @@ return -1; } -int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { +int ucx_list_contains(const UcxList *l, void *elem, + cmp_func fnc, void *cmpdata) { return ucx_list_find(l, elem, fnc, cmpdata) > -1; } @@ -206,7 +208,7 @@ return s; } -static UcxList *ucx_list_sort_merge(int length, +static UcxList *ucx_list_sort_merge(size_t length, UcxList* ls, UcxList* le, UcxList* re, cmp_func fnc, void* data) { @@ -214,7 +216,7 @@ UcxList *rc, *lc; lc = ls; rc = le; - int n = 0; + size_t n = 0; while (lc && lc != le && rc != re) { if (fnc(lc->data, rc->data, data) <= 0) { sorted[n] = lc; @@ -255,7 +257,7 @@ } UcxList *lc; - int ln = 1; + size_t ln = 1; UcxList *ls = l, *le, *re; @@ -271,7 +273,7 @@ return l; // this list is already sorted :) } else { UcxList *rc; - int rn = 1; + size_t rn = 1; rc = le; // skip already sorted elements while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { @@ -334,3 +336,93 @@ alfree(alloc, e); return l; } + + +static UcxList* ucx_list_setoperation_a(UcxAllocator *allocator, + UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata, + int op) { + + UcxList *res = NULL; + UcxList *cur = NULL; + const UcxList *src = left; + + do { + UCX_FOREACH(node, src) { + void* elem = node->data; + if ( + (op == 0 && !ucx_list_contains(res, elem, cmpfnc, cmpdata)) || + (op == 1 && ucx_list_contains(right, elem, cmpfnc, cmpdata)) || + (op == 2 && !ucx_list_contains(right, elem, cmpfnc, cmpdata))) { + UcxList *nl = almalloc(allocator, sizeof(UcxList)); + nl->prev = cur; + nl->next = NULL; + if (cpfnc) { + nl->data = cpfnc(elem, cpdata); + } else { + nl->data = elem; + } + if (cur != NULL) + cur->next = nl; + cur = nl; + if (res == NULL) + res = cur; + } + } + if (op == 0 && src == left) + src = right; + else + src = NULL; + } while (src != NULL); + + return res; +} + +UcxList* ucx_list_union(UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata) { + return ucx_list_union_a(ucx_default_allocator(), + left, right, cmpfnc, cmpdata, cpfnc, cpdata); +} + +UcxList* ucx_list_union_a(UcxAllocator *allocator, + UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata) { + + return ucx_list_setoperation_a(allocator, left, right, + cmpfnc, cmpdata, cpfnc, cpdata, 0); +} + +UcxList* ucx_list_intersection(UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata) { + return ucx_list_intersection_a(ucx_default_allocator(), left, right, + cmpfnc, cmpdata, cpfnc, cpdata); +} + +UcxList* ucx_list_intersection_a(UcxAllocator *allocator, + UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata) { + + return ucx_list_setoperation_a(allocator, left, right, + cmpfnc, cmpdata, cpfnc, cpdata, 1); +} + +UcxList* ucx_list_difference(UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata) { + return ucx_list_difference_a(ucx_default_allocator(), left, right, + cmpfnc, cmpdata, cpfnc, cpdata); +} + +UcxList* ucx_list_difference_a(UcxAllocator *allocator, + UcxList const *left, UcxList const *right, + cmp_func cmpfnc, void* cmpdata, + copy_func cpfnc, void* cpdata) { + + return ucx_list_setoperation_a(allocator, left, right, + cmpfnc, cmpdata, cpfnc, cpdata, 2); +}