diff -r 07ac32b385e4 -r 365b24f20f98 src/list.c --- a/src/list.c Thu Nov 07 10:43:31 2019 +0100 +++ b/src/list.c Sun Nov 24 17:57:25 2019 +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; } @@ -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); +}