diff -r 92e482410453 -r d345541018fa src/list.c --- a/src/list.c Mon Dec 30 09:54:10 2019 +0100 +++ b/src/list.c Sat Feb 06 19:11:44 2021 +0100 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. + * Copyright 2021 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: @@ -26,403 +26,4 @@ * 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); -} +#include "cx/list.h"