src/list.c

changeset 371
365b24f20f98
parent 335
872ae61c8945
child 390
d345541018fa
     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 +}

mercurial