ucx/list.c

branch
newapi
changeset 172
706080c30af6
parent 171
5065d0d52680
child 173
809581724cc7
--- a/ucx/list.c	Sat Apr 15 15:42:31 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,428 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "ucx/list.h"
-
-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, const UcxList *l,
-        copy_func fnc, void *data) {
-    UcxList *ret = NULL;
-    while (l) {
-        if (fnc) {
-            ret = ucx_list_append_a(alloc, ret, fnc(l->data, data));
-        } else {
-            ret = ucx_list_append_a(alloc, ret, l->data);
-        }
-        l = l->next;
-    }
-    return ret;
-}
-
-int ucx_list_equals(const UcxList *l1, const UcxList *l2,
-        cmp_func fnc, void* data) {
-    if (l1 == l2) return 1;
-    
-    while (l1 != NULL && l2 != NULL) {
-        if (fnc == NULL) {
-            if (l1->data != l2->data) return 0;
-        } else {
-            if (fnc(l1->data, l2->data, data) != 0) return 0;
-        }
-        l1 = l1->next;
-        l2 = l2->next;
-    }
-    
-    return (l1 == NULL && l2 == NULL);
-}
-
-void ucx_list_free(UcxList *l) {
-    ucx_list_free_a(ucx_default_allocator(), l);
-}
-
-void ucx_list_free_a(UcxAllocator *alloc, UcxList *l) {
-    UcxList *e = l, *f;
-    while (e != NULL) {
-        f = e;
-        e = e->next;
-        alfree(alloc, f);
-    }
-}
-
-void ucx_list_free_content(UcxList* list, ucx_destructor destr) {
-    if (!destr) destr = free;
-    while (list != NULL) {
-        destr(list->data);
-        list = list->next;
-    }
-}
-
-UcxList *ucx_list_append(UcxList *l, void *data)  {
-    return ucx_list_append_a(ucx_default_allocator(), l, data);
-}
-
-UcxList *ucx_list_append_a(UcxAllocator *alloc, UcxList *l, void *data)  {
-    UcxList *nl = (UcxList*) almalloc(alloc, sizeof(UcxList));
-    if (!nl) {
-        return NULL;
-    }
-    
-    nl->data = data;
-    nl->next = NULL;
-    if (l) {
-        UcxList *t = ucx_list_last(l);
-        t->next = nl;
-        nl->prev = t;
-        return l;
-    } else {
-        nl->prev = NULL;
-        return nl;
-    }
-}
-
-UcxList *ucx_list_prepend(UcxList *l, void *data) {
-    return ucx_list_prepend_a(ucx_default_allocator(), l, data);
-}
-
-UcxList *ucx_list_prepend_a(UcxAllocator *alloc, UcxList *l, void *data) {
-    UcxList *nl = ucx_list_append_a(alloc, NULL, data);
-    if (!nl) {
-        return NULL;
-    }
-    l = ucx_list_first(l);
-    
-    if (l) {
-        nl->next = l;
-        l->prev = nl;
-    }
-    return nl;
-}
-
-UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
-    if (l1) {
-        UcxList *last = ucx_list_last(l1);
-        last->next = l2;
-        if (l2) {
-            l2->prev = last;
-        }
-        return l1;
-    } else {
-        return l2;
-    }
-}
-
-UcxList *ucx_list_last(const UcxList *l) {
-    if (l == NULL) return NULL;
-    
-    const UcxList *e = l;
-    while (e->next != NULL) {
-        e = e->next;
-    }
-    return (UcxList*)e;
-}
-
-ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) {
-    ssize_t index = 0;
-    while (list) {
-        if (list == elem) {
-            return index;
-        }
-        list = list->next;
-        index++;
-    }
-    return -1;
-}
-
-UcxList *ucx_list_get(const UcxList *l, size_t index) {
-    if (l == NULL) return NULL;
-
-    const UcxList *e = l;
-    while (e->next && index > 0) {
-        e = e->next;
-        index--;
-    }
-    
-    return (UcxList*)(index == 0 ? e : NULL);
-}
-
-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) {
-            if (fnc(elem, e->data, cmpdata) == 0) {
-                return index;
-            }
-        } else {
-            if (elem == e->data) {
-                return index;
-            }
-        }
-        index++;
-    }
-    return -1;
-}
-
-int ucx_list_contains(const UcxList *l, void *elem,
-        cmp_func fnc, void *cmpdata) {
-    return ucx_list_find(l, elem, fnc, cmpdata) > -1;
-}
-
-size_t ucx_list_size(const UcxList *l) {
-    if (l == NULL) return 0;
-    
-    const UcxList *e = l;
-    size_t s = 1;
-    while (e->next != NULL) {
-        e = e->next;
-        s++;
-    }
-
-    return s;
-}
-
-static UcxList *ucx_list_sort_merge(size_t length,
-        UcxList* ls, UcxList* le, UcxList* re,
-        cmp_func fnc, void* data) {
-
-    UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
-    UcxList *rc, *lc;
-
-    lc = ls; rc = le;
-    size_t n = 0;
-    while (lc && lc != le && rc != re) {
-        if (fnc(lc->data, rc->data, data) <= 0) {
-            sorted[n] = lc;
-            lc = lc->next;
-        } else {
-            sorted[n] = rc;
-            rc = rc->next;
-        }
-        n++;
-    }
-    while (lc && lc != le) {
-        sorted[n] = lc;
-        lc = lc->next;
-        n++;
-    }
-    while (rc && rc != re) {
-        sorted[n] = rc;
-        rc = rc->next;
-        n++;
-    }
-
-    // Update pointer
-    sorted[0]->prev = NULL;
-    for (int i = 0 ; i < length-1 ; i++) {
-        sorted[i]->next = sorted[i+1];
-        sorted[i+1]->prev = sorted[i];
-    }
-    sorted[length-1]->next = NULL;
-
-    UcxList *ret = sorted[0];
-    free(sorted);
-    return ret;
-}
-
-UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
-    if (l == NULL) {
-        return NULL;
-    }
-
-    UcxList *lc;
-    size_t ln = 1;
-
-    UcxList *ls = l, *le, *re;
-    
-    // check how many elements are already sorted
-    lc = ls;
-    while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
-        lc = lc->next;
-        ln++;
-    }
-    le = lc->next;
-
-    if (le == NULL) {
-        return l; // this list is already sorted :)
-    } else {
-        UcxList *rc;
-        size_t rn = 1;
-        rc = le;
-        // skip already sorted elements
-        while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
-            rc = rc->next;
-            rn++;
-        }
-        re = rc->next;
-
-        // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
-        UcxList *sorted = ucx_list_sort_merge(ln+rn,
-                ls, le, re,
-                fnc, data);
-        
-        // Something left? Sort it!
-        size_t remainder_length = ucx_list_size(re);
-        if (remainder_length > 0) {
-            UcxList *remainder = ucx_list_sort(re, fnc, data);
-
-            // merge sorted list with (also sorted) remainder
-            l = ucx_list_sort_merge(ln+rn+remainder_length,
-                    sorted, remainder, NULL, fnc, data);
-        } else {
-            // no remainder - we've got our sorted list
-            l = sorted;
-        }
-
-        return l;
-    }
-}
-
-UcxList *ucx_list_first(const UcxList *l) {
-    if (!l) {
-        return NULL;
-    }
-    
-    const UcxList *e = l;
-    while (e->prev) {
-        e = e->prev;
-    }
-    return (UcxList *)e;
-}
-
-UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
-    return ucx_list_remove_a(ucx_default_allocator(), l, e);
-}
-    
-UcxList *ucx_list_remove_a(UcxAllocator *alloc, UcxList *l, UcxList *e) {
-    if (l == e) {
-        l = e->next;
-    }
-    
-    if (e->next) {
-        e->next->prev = e->prev;
-    }
-    
-    if (e->prev) {
-        e->prev->next = e->next;
-    }
-    
-    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