1.1 --- a/src/list.c Thu Nov 07 10:43:31 2019 +0100 1.2 +++ b/src/list.c Sun Nov 24 17:57:25 2019 +0100 1.3 @@ -28,11 +28,11 @@ 1.4 1.5 #include "ucx/list.h" 1.6 1.7 -UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { 1.8 +UcxList *ucx_list_clone(const UcxList *l, copy_func fnc, void *data) { 1.9 return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data); 1.10 } 1.11 1.12 -UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l, 1.13 +UcxList *ucx_list_clone_a(UcxAllocator *alloc, const UcxList *l, 1.14 copy_func fnc, void *data) { 1.15 UcxList *ret = NULL; 1.16 while (l) { 1.17 @@ -172,7 +172,8 @@ 1.18 return (UcxList*)(index == 0 ? e : NULL); 1.19 } 1.20 1.21 -ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { 1.22 +ssize_t ucx_list_find(const UcxList *l, void *elem, 1.23 + cmp_func fnc, void *cmpdata) { 1.24 ssize_t index = 0; 1.25 UCX_FOREACH(e, l) { 1.26 if (fnc) { 1.27 @@ -189,7 +190,8 @@ 1.28 return -1; 1.29 } 1.30 1.31 -int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { 1.32 +int ucx_list_contains(const UcxList *l, void *elem, 1.33 + cmp_func fnc, void *cmpdata) { 1.34 return ucx_list_find(l, elem, fnc, cmpdata) > -1; 1.35 } 1.36 1.37 @@ -334,3 +336,93 @@ 1.38 alfree(alloc, e); 1.39 return l; 1.40 } 1.41 + 1.42 + 1.43 +static UcxList* ucx_list_setoperation_a(UcxAllocator *allocator, 1.44 + UcxList const *left, UcxList const *right, 1.45 + cmp_func cmpfnc, void* cmpdata, 1.46 + copy_func cpfnc, void* cpdata, 1.47 + int op) { 1.48 + 1.49 + UcxList *res = NULL; 1.50 + UcxList *cur = NULL; 1.51 + const UcxList *src = left; 1.52 + 1.53 + do { 1.54 + UCX_FOREACH(node, src) { 1.55 + void* elem = node->data; 1.56 + if ( 1.57 + (op == 0 && !ucx_list_contains(res, elem, cmpfnc, cmpdata)) || 1.58 + (op == 1 && ucx_list_contains(right, elem, cmpfnc, cmpdata)) || 1.59 + (op == 2 && !ucx_list_contains(right, elem, cmpfnc, cmpdata))) { 1.60 + UcxList *nl = almalloc(allocator, sizeof(UcxList)); 1.61 + nl->prev = cur; 1.62 + nl->next = NULL; 1.63 + if (cpfnc) { 1.64 + nl->data = cpfnc(elem, cpdata); 1.65 + } else { 1.66 + nl->data = elem; 1.67 + } 1.68 + if (cur != NULL) 1.69 + cur->next = nl; 1.70 + cur = nl; 1.71 + if (res == NULL) 1.72 + res = cur; 1.73 + } 1.74 + } 1.75 + if (op == 0 && src == left) 1.76 + src = right; 1.77 + else 1.78 + src = NULL; 1.79 + } while (src != NULL); 1.80 + 1.81 + return res; 1.82 +} 1.83 + 1.84 +UcxList* ucx_list_union(UcxList const *left, UcxList const *right, 1.85 + cmp_func cmpfnc, void* cmpdata, 1.86 + copy_func cpfnc, void* cpdata) { 1.87 + return ucx_list_union_a(ucx_default_allocator(), 1.88 + left, right, cmpfnc, cmpdata, cpfnc, cpdata); 1.89 +} 1.90 + 1.91 +UcxList* ucx_list_union_a(UcxAllocator *allocator, 1.92 + UcxList const *left, UcxList const *right, 1.93 + cmp_func cmpfnc, void* cmpdata, 1.94 + copy_func cpfnc, void* cpdata) { 1.95 + 1.96 + return ucx_list_setoperation_a(allocator, left, right, 1.97 + cmpfnc, cmpdata, cpfnc, cpdata, 0); 1.98 +} 1.99 + 1.100 +UcxList* ucx_list_intersection(UcxList const *left, UcxList const *right, 1.101 + cmp_func cmpfnc, void* cmpdata, 1.102 + copy_func cpfnc, void* cpdata) { 1.103 + return ucx_list_intersection_a(ucx_default_allocator(), left, right, 1.104 + cmpfnc, cmpdata, cpfnc, cpdata); 1.105 +} 1.106 + 1.107 +UcxList* ucx_list_intersection_a(UcxAllocator *allocator, 1.108 + UcxList const *left, UcxList const *right, 1.109 + cmp_func cmpfnc, void* cmpdata, 1.110 + copy_func cpfnc, void* cpdata) { 1.111 + 1.112 + return ucx_list_setoperation_a(allocator, left, right, 1.113 + cmpfnc, cmpdata, cpfnc, cpdata, 1); 1.114 +} 1.115 + 1.116 +UcxList* ucx_list_difference(UcxList const *left, UcxList const *right, 1.117 + cmp_func cmpfnc, void* cmpdata, 1.118 + copy_func cpfnc, void* cpdata) { 1.119 + return ucx_list_difference_a(ucx_default_allocator(), left, right, 1.120 + cmpfnc, cmpdata, cpfnc, cpdata); 1.121 +} 1.122 + 1.123 +UcxList* ucx_list_difference_a(UcxAllocator *allocator, 1.124 + UcxList const *left, UcxList const *right, 1.125 + cmp_func cmpfnc, void* cmpdata, 1.126 + copy_func cpfnc, void* cpdata) { 1.127 + 1.128 + return ucx_list_setoperation_a(allocator, left, right, 1.129 + cmpfnc, cmpdata, cpfnc, cpdata, 2); 1.130 +}