src/ucx/list.c

branch
webdav
changeset 260
4779a6fb4fbe
parent 254
4784c14aa639
child 415
d938228c382e
--- a/src/ucx/list.c	Tue Aug 25 12:07:56 2020 +0200
+++ b/src/ucx/list.c	Sat Oct 24 17:34:32 2020 +0200
@@ -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);
+}

mercurial