Sat, 15 Apr 2023 15:45:42 +0200
remove ucx (breaks build)
--- a/make/Makefile.mk Sat Apr 15 15:42:31 2023 +0200 +++ b/make/Makefile.mk Sat Apr 15 15:45:42 2023 +0200 @@ -1,7 +1,7 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. # -# Copyright 2013 Olaf Wintermann. All rights reserved. +# Copyright 2023 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: @@ -41,9 +41,6 @@ $(BUILD_DIRS): mkdir -p $@ -ucx: FORCE - cd ucx; $(MAKE) - ui: FORCE cd ui; $(MAKE) all
--- a/ucx/Makefile Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -# -# Copyright 2013 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. -# - -BUILD_ROOT = ../ -include ../config.mk - -# list of source files -SRC = utils.c -SRC += list.c -SRC += map.c -SRC += avl.c -SRC += properties.c -SRC += mempool.c -SRC += string.c -SRC += test.c -SRC += allocator.c -SRC += logging.c -SRC += buffer.c -SRC += stack.c -SRC += ucx.c -SRC += array.c - -OBJ = $(SRC:%.c=../build/ucx/%.$(OBJ_EXT)) - -UCX_LIB = ../build/lib/libucx.$(LIB_EXT) - -all: ../build/ucx $(UCX_LIB) - -$(UCX_LIB): $(OBJ) - $(AR) $(ARFLAGS) $(UCX_LIB) $(OBJ) - -../build/ucx: - mkdir -p ../build/ucx - -../build/ucx/%.$(OBJ_EXT): %.c - $(CC) $(CFLAGS) -o $@ -c $< -
--- a/ucx/README Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -UCX is a library for common data structures, algorithms and string functions. - -More informations at: https://develop.uap-core.de/ucx/ -
--- a/ucx/allocator.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +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/allocator.h" - -#include <stdlib.h> - -static UcxAllocator default_allocator = { - NULL, - ucx_default_malloc, - ucx_default_calloc, - ucx_default_realloc, - ucx_default_free -}; - -UcxAllocator *ucx_default_allocator() { - UcxAllocator *allocator = &default_allocator; - return allocator; -} - -void *ucx_default_malloc(void *ignore, size_t n) { - return malloc(n); -} - -void *ucx_default_calloc(void *ignore, size_t n, size_t size) { - return calloc(n, size); -} - -void *ucx_default_realloc(void *ignore, void *data, size_t n) { - return realloc(data, n); -} - -void ucx_default_free(void *ignore, void *data) { - free(data); -}
--- a/ucx/array.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,467 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2019 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. - */ - -#define _GNU_SOURCE /* we want to use qsort_r(), if available */ -#define __STDC_WANT_LIB_EXT1__ 1 /* use qsort_s, if available */ - - -#include "ucx/array.h" -#include "ucx/utils.h" - -#include <string.h> -#include <stdlib.h> -#include <errno.h> - -#ifndef UCX_ARRAY_DISABLE_QSORT -#ifdef __GLIBC__ -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) -#define ucx_array_sort_impl qsort_r -#endif /* glibc version >= 2.8 */ -#elif /* not __GLIBC__ */ defined(__APPLE__) || defined(__FreeBSD__) -#define ucx_array_sort_impl ucx_qsort_r -#define USE_UCX_QSORT_R -#elif /* not (__APPLE || __FreeBSD__) */ defined(__sun) -#if __STDC_VERSION__ >= 201112L -#define ucx_array_sort_impl qsort_s -#endif -#endif /* __GLIBC__, __APLE__, __FreeBSD__, __sun */ -#endif /* UCX_ARRAY_DISABLE_QSORT */ - -#ifndef ucx_array_sort_impl -#define ucx_array_sort_impl ucx_mergesort -#endif - -static int ucx_array_ensurecap(UcxArray *array, size_t reqcap) { - size_t required_capacity = array->capacity; - while (reqcap > required_capacity) { - if (required_capacity * 2 < required_capacity) - return 1; - required_capacity <<= 1; - } - if (ucx_array_reserve(array, required_capacity)) { - return 1; - } - return 0; -} - -int ucx_array_util_set_a(UcxAllocator* alloc, void** array, size_t* capacity, - size_t elmsize, size_t index, void* data) { - - if(!alloc || !capacity || !array) { - errno = EINVAL; - return 1; - } - - size_t newcapacity = *capacity; - while(index >= newcapacity) { - if(ucx_szmul(newcapacity, 2, &newcapacity)) { - errno = EOVERFLOW; - return 1; - } - } - - size_t memlen, offset; - if(ucx_szmul(newcapacity, elmsize, &memlen)) { - errno = EOVERFLOW; - return 1; - } - /* we don't need to check index*elmsize - it is smaller than memlen */ - - - void* newptr = alrealloc(alloc, *array, memlen); - if(newptr == NULL) { - errno = ENOMEM; /* we cannot assume that every allocator sets this */ - return 1; - } - *array = newptr; - *capacity = newcapacity; - - - char* dest = *array; - dest += elmsize*index; - memcpy(dest, data, elmsize); - - return 0; -} - -int ucx_array_util_setptr_a(UcxAllocator* alloc, void** array, size_t* capacity, - size_t index, void* data) { - - return ucx_array_util_set_a(alloc, array, capacity, sizeof(void*), - index, &data); -} - -UcxArray* ucx_array_new(size_t capacity, size_t elemsize) { - return ucx_array_new_a(capacity, elemsize, ucx_default_allocator()); -} - -UcxArray* ucx_array_new_a(size_t capacity, size_t elemsize, - UcxAllocator* allocator) { - UcxArray* array = almalloc(allocator, sizeof(UcxArray)); - if(array) { - ucx_array_init_a(array, capacity, elemsize, allocator); - } - return array; -} - -void ucx_array_init(UcxArray* array, size_t capacity, size_t elemsize) { - ucx_array_init_a(array, capacity, elemsize, ucx_default_allocator()); -} - -void ucx_array_init_a(UcxArray* array, size_t capacity, size_t elemsize, - UcxAllocator* allocator) { - - array->allocator = allocator; - array->elemsize = elemsize; - array->size = 0; - array->data = alcalloc(allocator, capacity, elemsize); - - if (array->data) { - array->capacity = capacity; - } else { - array->capacity = 0; - } -} - -int ucx_array_clone(UcxArray* dest, UcxArray const* src) { - if (ucx_array_ensurecap(dest, src->capacity)) { - return 1; - } - - dest->elemsize = src->elemsize; - dest->size = src->size; - - if (dest->data) { - memcpy(dest->data, src->data, src->size*src->elemsize); - } - - return 0; -} - -int ucx_array_equals(UcxArray const *array1, UcxArray const *array2, - cmp_func cmpfnc, void* data) { - - if (array1->size != array2->size || array1->elemsize != array2->elemsize) { - return 0; - } else { - if (array1->size == 0) - return 1; - - size_t elemsize; - if (cmpfnc == NULL) { - cmpfnc = ucx_cmp_mem; - elemsize = array1->elemsize; - data = &elemsize; - } - - for (size_t i = 0 ; i < array1->size ; i++) { - int r = cmpfnc( - ucx_array_at(array1, i), - ucx_array_at(array2, i), - data); - if (r != 0) - return 0; - } - return 1; - } -} - -void ucx_array_destroy(UcxArray *array) { - if(array->data) - alfree(array->allocator, array->data); - array->data = NULL; - array->capacity = array->size = 0; -} - -void ucx_array_free(UcxArray *array) { - ucx_array_destroy(array); - alfree(array->allocator, array); -} - -int ucx_array_append_from(UcxArray *array, void *data, size_t count) { - if (ucx_array_ensurecap(array, array->size + count)) - return 1; - - void* dest = ucx_array_at(array, array->size); - if (data) { - memcpy(dest, data, array->elemsize*count); - } else { - memset(dest, 0, array->elemsize*count); - } - array->size += count; - - return 0; -} - -int ucx_array_prepend_from(UcxArray *array, void *data, size_t count) { - if (ucx_array_ensurecap(array, array->size + count)) - return 1; - - if (array->size > 0) { - void *dest = ucx_array_at(array, count); - memmove(dest, array->data, array->elemsize*array->size); - } - - if (data) { - memcpy(array->data, data, array->elemsize*count); - } else { - memset(array->data, 0, array->elemsize*count); - } - array->size += count; - - return 0; -} - -int ucx_array_set_from(UcxArray *array, size_t index, - void *data, size_t count) { - if (ucx_array_ensurecap(array, index + count)) - return 1; - - if (index+count > array->size) { - array->size = index+count; - } - - void *dest = ucx_array_at(array, index); - if (data) { - memcpy(dest, data, array->elemsize*count); - } else { - memset(dest, 0, array->elemsize*count); - } - - return 0; -} - -int ucx_array_concat(UcxArray *array1, const UcxArray *array2) { - - if (array1->elemsize != array2->elemsize) - return 1; - - size_t capacity = array1->capacity+array2->capacity; - - if (array1->capacity < capacity) { - if (ucx_array_reserve(array1, capacity)) { - return 1; - } - } - - void* dest = ucx_array_at(array1, array1->size); - memcpy(dest, array2->data, array2->size*array2->elemsize); - - array1->size += array2->size; - - return 0; -} - -void *ucx_array_at(UcxArray const *array, size_t index) { - char* memory = array->data; - char* loc = memory + index*array->elemsize; - return loc; -} - -size_t ucx_array_find(UcxArray const *array, void *elem, - cmp_func cmpfnc, void *data) { - - size_t elemsize; - if (cmpfnc == NULL) { - cmpfnc = ucx_cmp_mem; - elemsize = array->elemsize; - data = &elemsize; - } - - if (array->size > 0) { - for (size_t i = 0 ; i < array->size ; i++) { - void* ptr = ucx_array_at(array, i); - if (cmpfnc(ptr, elem, data) == 0) { - return i; - } - } - return array->size; - } else { - return 0; - } -} - -int ucx_array_contains(UcxArray const *array, void *elem, - cmp_func cmpfnc, void *data) { - return ucx_array_find(array, elem, cmpfnc, data) != array->size; -} - -static void ucx_mergesort_merge(void *arrdata,size_t elemsize, - cmp_func cmpfnc, void *data, - size_t start, size_t mid, size_t end) { - - char* array = arrdata; - - size_t rightstart = mid + 1; - - if (cmpfnc(array + mid*elemsize, - array + rightstart*elemsize, data) <= 0) { - /* already sorted */ - return; - } - - /* we need memory for one element */ - void *value = malloc(elemsize); - - while (start <= mid && rightstart <= end) { - if (cmpfnc(array + start*elemsize, - array + rightstart*elemsize, data) <= 0) { - start++; - } else { - /* save the value from the right */ - memcpy(value, array + rightstart*elemsize, elemsize); - - /* shift all left elements one element to the right */ - size_t shiftcount = rightstart-start; - void *startptr = array + start*elemsize; - void *dest = array + (start+1)*elemsize; - memmove(dest, startptr, shiftcount*elemsize); - - /* bring the first value from the right to the left */ - memcpy(startptr, value, elemsize); - - start++; - mid++; - rightstart++; - } - } - - /* free the temporary memory */ - free(value); -} - -static void ucx_mergesort_impl(void *arrdata, size_t elemsize, - cmp_func cmpfnc, void *data, size_t l, size_t r) { - if (l < r) { - size_t m = l + (r - l) / 2; - - ucx_mergesort_impl(arrdata, elemsize, cmpfnc, data, l, m); - ucx_mergesort_impl(arrdata, elemsize, cmpfnc, data, m + 1, r); - ucx_mergesort_merge(arrdata, elemsize, cmpfnc, data, l, m, r); - } -} - -static void ucx_mergesort(void *arrdata, size_t count, size_t elemsize, - cmp_func cmpfnc, void *data) { - - ucx_mergesort_impl(arrdata, elemsize, cmpfnc, data, 0, count-1); -} - -#ifdef USE_UCX_QSORT_R -struct cmpfnc_swapargs_info { - cmp_func func; - void *data; -}; - -static int cmp_func_swap_args(void *data, const void *x, const void *y) { - struct cmpfnc_swapargs_info* info = data; - return info->func(x, y, info->data); -} - -static void ucx_qsort_r(void *array, size_t count, size_t elemsize, - cmp_func cmpfnc, void *data) { - struct cmpfnc_swapargs_info info; - info.func = cmpfnc; - info.data = data; - qsort_r(array, count, elemsize, &info, cmp_func_swap_args); -} -#endif /* USE_UCX_QSORT_R */ - -void ucx_array_sort(UcxArray* array, cmp_func cmpfnc, void *data) { - ucx_array_sort_impl(array->data, array->size, array->elemsize, - cmpfnc, data); -} - -void ucx_array_remove(UcxArray *array, size_t index) { - array->size--; - if (index < array->size) { - void* dest = ucx_array_at(array, index); - void* src = ucx_array_at(array, index+1); - memmove(dest, src, (array->size - index)*array->elemsize); - } -} - -void ucx_array_remove_fast(UcxArray *array, size_t index) { - array->size--; - if (index < array->size) { - void* dest = ucx_array_at(array, index); - void* src = ucx_array_at(array, array->size); - memcpy(dest, src, array->elemsize); - } -} - -int ucx_array_shrink(UcxArray* array) { - void* newptr = alrealloc(array->allocator, array->data, - array->size*array->elemsize); - if (newptr) { - array->data = newptr; - array->capacity = array->size; - return 0; - } else { - return 1; - } -} - -int ucx_array_resize(UcxArray* array, size_t capacity) { - if (array->capacity >= capacity) { - void* newptr = alrealloc(array->allocator, array->data, - capacity*array->elemsize); - if (newptr) { - array->data = newptr; - array->capacity = capacity; - if (array->size > array->capacity) { - array->size = array->capacity; - } - return 0; - } else { - return 1; - } - } else { - return ucx_array_reserve(array, capacity); - } -} - -int ucx_array_reserve(UcxArray* array, size_t capacity) { - if (array->capacity > capacity) { - return 0; - } else { - void* newptr = alrealloc(array->allocator, array->data, - capacity*array->elemsize); - if (newptr) { - array->data = newptr; - array->capacity = capacity; - return 0; - } else { - return 1; - } - } -} - -int ucx_array_grow(UcxArray* array, size_t count) { - return ucx_array_reserve(array, array->size+count); -}
--- a/ucx/avl.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,373 +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/avl.h" - -#include <limits.h> - -#define ptrcast(ptr) ((void*)(ptr)) -#define alloc_tree(al) (UcxAVLTree*) almalloc((al), sizeof(UcxAVLTree)) -#define alloc_node(al) (UcxAVLNode*) almalloc((al), sizeof(UcxAVLNode)) - -static void ucx_avl_connect(UcxAVLTree *tree, - UcxAVLNode *node, UcxAVLNode *child, intptr_t nullkey) { - if (child) { - child->parent = node; - } - // if child is NULL, nullkey decides if left or right pointer is cleared - if (tree->cmpfunc( - ptrcast(child ? child->key : nullkey), - ptrcast(node->key), tree->userdata) > 0) { - node->right = child; - } else { - node->left = child; - } - size_t lh = node->left ? node->left->height : 0; - size_t rh = node->right ? node->right->height : 0; - node->height = 1 + (lh > rh ? lh : rh); -} - -#define avlheight(node) ((node) ? (node)->height : 0) - -static UcxAVLNode* avl_rotright(UcxAVLTree *tree, UcxAVLNode *l0) { - UcxAVLNode *p = l0->parent; - UcxAVLNode *l1 = l0->left; - if (p) { - ucx_avl_connect(tree, p, l1, 0); - } else { - l1->parent = NULL; - } - ucx_avl_connect(tree, l0, l1->right, l1->key); - ucx_avl_connect(tree, l1, l0, 0); - return l1; -} - -static UcxAVLNode* avl_rotleft(UcxAVLTree *tree, UcxAVLNode *l0) { - UcxAVLNode *p = l0->parent; - UcxAVLNode *l1 = l0->right; - if (p) { - ucx_avl_connect(tree, p, l1, 0); - } else { - l1->parent = NULL; - } - ucx_avl_connect(tree, l0, l1->left, l1->key); - ucx_avl_connect(tree, l1, l0, 0); - return l1; -} - -static void ucx_avl_balance(UcxAVLTree *tree, UcxAVLNode *n) { - int lh = avlheight(n->left); - int rh = avlheight(n->right); - n->height = 1 + (lh > rh ? lh : rh); - - if (lh - rh == 2) { - UcxAVLNode *c = n->left; - if (avlheight(c->right) - avlheight(c->left) == 1) { - avl_rotleft(tree, c); - } - n = avl_rotright(tree, n); - } else if (rh - lh == 2) { - UcxAVLNode *c = n->right; - if (avlheight(c->left) - avlheight(c->right) == 1) { - avl_rotright(tree, c); - } - n = avl_rotleft(tree, n); - } - - if (n->parent) { - ucx_avl_balance(tree, n->parent); - } else { - tree->root = n; - } -} - -UcxAVLTree *ucx_avl_new(cmp_func cmpfunc) { - return ucx_avl_new_a(cmpfunc, ucx_default_allocator()); -} - -UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator) { - UcxAVLTree* tree = alloc_tree(allocator); - if (tree) { - tree->allocator = allocator; - tree->cmpfunc = cmpfunc; - tree->root = NULL; - tree->userdata = NULL; - } - - return tree; -} - -static void ucx_avl_free_node(UcxAllocator *al, UcxAVLNode *node) { - if (node) { - ucx_avl_free_node(al, node->left); - ucx_avl_free_node(al, node->right); - alfree(al, node); - } -} - -void ucx_avl_free(UcxAVLTree *tree) { - UcxAllocator *al = tree->allocator; - ucx_avl_free_node(al, tree->root); - alfree(al, tree); -} - -static void ucx_avl_free_content_node(UcxAllocator *al, UcxAVLNode *node, - ucx_destructor destr) { - if (node) { - ucx_avl_free_content_node(al, node->left, destr); - ucx_avl_free_content_node(al, node->right, destr); - if (destr) { - destr(node->value); - } else { - alfree(al, node->value); - } - } -} - -void ucx_avl_free_content(UcxAVLTree *tree, ucx_destructor destr) { - ucx_avl_free_content_node(tree->allocator, tree->root, destr); -} - -UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key) { - UcxAVLNode *n = tree->root; - int cmpresult; - while (n && (cmpresult = tree->cmpfunc( - ptrcast(key), ptrcast(n->key), tree->userdata))) { - n = cmpresult > 0 ? n->right : n->left; - } - return n; -} - -void *ucx_avl_get(UcxAVLTree *tree, intptr_t key) { - UcxAVLNode *n = ucx_avl_get_node(tree, key); - return n ? n->value : NULL; -} - -UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key, - distance_func dfnc, int mode) { - UcxAVLNode *n = tree->root; - UcxAVLNode *closest = NULL; - - intmax_t cmpresult; - intmax_t closest_dist; - closest_dist = mode == UCX_AVL_FIND_LOWER_BOUNDED ? INTMAX_MIN : INTMAX_MAX; - - while (n && (cmpresult = dfnc( - ptrcast(key), ptrcast(n->key), tree->userdata))) { - if (mode == UCX_AVL_FIND_CLOSEST) { - intmax_t dist = cmpresult; - if (dist < 0) dist *= -1; - if (dist < closest_dist) { - closest_dist = dist; - closest = n; - } - } else if (mode == UCX_AVL_FIND_LOWER_BOUNDED && cmpresult <= 0) { - if (cmpresult > closest_dist) { - closest_dist = cmpresult; - closest = n; - } - } else if (mode == UCX_AVL_FIND_UPPER_BOUNDED && cmpresult >= 0) { - if (cmpresult < closest_dist) { - closest_dist = cmpresult; - closest = n; - } - } - n = cmpresult > 0 ? n->right : n->left; - } - return n ? n : closest; -} - -void *ucx_avl_find(UcxAVLTree *tree, intptr_t key, - distance_func dfnc, int mode) { - UcxAVLNode *n = ucx_avl_find_node(tree, key, dfnc, mode); - return n ? n->value : NULL; -} - -int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value) { - return ucx_avl_put_s(tree, key, value, NULL); -} - -int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value, - void **oldvalue) { - if (tree->root) { - UcxAVLNode *n = tree->root; - int cmpresult; - while ((cmpresult = tree->cmpfunc( - ptrcast(key), ptrcast(n->key), tree->userdata))) { - UcxAVLNode *m = cmpresult > 0 ? n->right : n->left; - if (m) { - n = m; - } else { - break; - } - } - - if (cmpresult) { - UcxAVLNode* e = alloc_node(tree->allocator); - if (e) { - e->key = key; e->value = value; e->height = 1; - e->parent = e->left = e->right = NULL; - ucx_avl_connect(tree, n, e, 0); - ucx_avl_balance(tree, n); - return 0; - } else { - return 1; - } - } else { - if (oldvalue) { - *oldvalue = n->value; - } - n->value = value; - return 0; - } - } else { - tree->root = alloc_node(tree->allocator); - if (tree->root) { - tree->root->key = key; tree->root->value = value; - tree->root->height = 1; - tree->root->parent = tree->root->left = tree->root->right = NULL; - - if (oldvalue) { - *oldvalue = NULL; - } - - return 0; - } else { - return 1; - } - } -} - -int ucx_avl_remove(UcxAVLTree *tree, intptr_t key) { - return ucx_avl_remove_s(tree, key, NULL, NULL); -} - -int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node) { - return ucx_avl_remove_s(tree, node->key, NULL, NULL); -} - -int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key, - intptr_t *oldkey, void **oldvalue) { - - UcxAVLNode *n = tree->root; - int cmpresult; - while (n && (cmpresult = tree->cmpfunc( - ptrcast(key), ptrcast(n->key), tree->userdata))) { - n = cmpresult > 0 ? n->right : n->left; - } - if (n) { - if (oldkey) { - *oldkey = n->key; - } - if (oldvalue) { - *oldvalue = n->value; - } - - UcxAVLNode *p = n->parent; - if (n->left && n->right) { - UcxAVLNode *s = n->right; - while (s->left) { - s = s->left; - } - ucx_avl_connect(tree, s->parent, s->right, s->key); - n->key = s->key; n->value = s->value; - p = s->parent; - alfree(tree->allocator, s); - } else { - if (p) { - ucx_avl_connect(tree, p, n->right ? n->right:n->left, n->key); - } else { - tree->root = n->right ? n->right : n->left; - if (tree->root) { - tree->root->parent = NULL; - } - } - alfree(tree->allocator, n); - } - - if (p) { - ucx_avl_balance(tree, p); - } - - return 0; - } else { - return 1; - } -} - -static size_t ucx_avl_countn(UcxAVLNode *node) { - if (node) { - return 1 + ucx_avl_countn(node->left) + ucx_avl_countn(node->right); - } else { - return 0; - } -} - -size_t ucx_avl_count(UcxAVLTree *tree) { - return ucx_avl_countn(tree->root); -} - -UcxAVLNode* ucx_avl_pred(UcxAVLNode* node) { - if (node->left) { - UcxAVLNode* n = node->left; - while (n->right) { - n = n->right; - } - return n; - } else { - UcxAVLNode* n = node; - while (n->parent) { - if (n->parent->right == n) { - return n->parent; - } else { - n = n->parent; - } - } - return NULL; - } -} - -UcxAVLNode* ucx_avl_succ(UcxAVLNode* node) { - if (node->right) { - UcxAVLNode* n = node->right; - while (n->left) { - n = n->left; - } - return n; - } else { - UcxAVLNode* n = node; - while (n->parent) { - if (n->parent->left == n) { - return n->parent; - } else { - n = n->parent; - } - } - return NULL; - } -}
--- a/ucx/buffer.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +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/buffer.h" - -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> - -UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { - UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); - if (buffer) { - buffer->flags = flags; - if (!space) { - buffer->space = (char*)malloc(capacity); - if (!buffer->space) { - free(buffer); - return NULL; - } - memset(buffer->space, 0, capacity); - buffer->flags |= UCX_BUFFER_AUTOFREE; - } else { - buffer->space = (char*)space; - } - buffer->capacity = capacity; - buffer->size = 0; - - buffer->pos = 0; - } - - return buffer; -} - -void ucx_buffer_free(UcxBuffer *buffer) { - if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) { - free(buffer->space); - } - free(buffer); -} - -UcxBuffer* ucx_buffer_extract( - UcxBuffer *src, size_t start, size_t length, int flags) { - if (src->size == 0 || length == 0 || - ((size_t)-1) - start < length || start+length > src->capacity) - { - return NULL; - } - - UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); - if (dst) { - dst->space = (char*)malloc(length); - if (!dst->space) { - free(dst); - return NULL; - } - dst->capacity = length; - dst->size = length; - dst->flags = flags | UCX_BUFFER_AUTOFREE; - dst->pos = 0; - memcpy(dst->space, src->space+start, length); - } - return dst; -} - -int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) { - size_t npos; - switch (whence) { - case SEEK_CUR: - npos = buffer->pos; - break; - case SEEK_END: - npos = buffer->size; - break; - case SEEK_SET: - npos = 0; - break; - default: - return -1; - } - - size_t opos = npos; - npos += offset; - - if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { - return -1; - } - - if (npos >= buffer->size) { - return -1; - } else { - buffer->pos = npos; - return 0; - } - -} - -int ucx_buffer_eof(UcxBuffer *buffer) { - return buffer->pos >= buffer->size; -} - -int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { - size_t newcap = buffer->capacity; - - if (buffer->capacity + len < buffer->capacity) { - return -1; - } - - while (buffer->capacity + len > newcap) { - newcap <<= 1; - if (newcap < buffer->capacity) { - return -1; - } - } - - char *newspace = (char*)realloc(buffer->space, newcap); - if (newspace) { - memset(newspace+buffer->size, 0, newcap-buffer->size); - buffer->space = newspace; - buffer->capacity = newcap; - } else { - return -1; - } - - return 0; -} - -size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, - UcxBuffer *buffer) { - size_t len; - if(ucx_szmul(size, nitems, &len)) { - return 0; - } - size_t required = buffer->pos + len; - if (buffer->pos > required) { - return 0; - } - - if (required > buffer->capacity) { - if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { - if (ucx_buffer_extend(buffer, required - buffer->capacity)) { - return 0; - } - } else { - len = buffer->capacity - buffer->pos; - if (size > 1) { - len -= len%size; - } - } - } - - if (len == 0) { - return len; - } - - memcpy(buffer->space + buffer->pos, ptr, len); - buffer->pos += len; - if(buffer->pos > buffer->size) { - buffer->size = buffer->pos; - } - - return len / size; -} - -size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, - UcxBuffer *buffer) { - size_t len; - if(ucx_szmul(size, nitems, &len)) { - return 0; - } - if (buffer->pos + len > buffer->size) { - len = buffer->size - buffer->pos; - if (size > 1) len -= len%size; - } - - if (len <= 0) { - return len; - } - - memcpy(ptr, buffer->space + buffer->pos, len); - buffer->pos += len; - - return len / size; -} - -int ucx_buffer_putc(UcxBuffer *buffer, int c) { - if(buffer->pos >= buffer->capacity) { - if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { - if(ucx_buffer_extend(buffer, 1)) { - return EOF; - } - } else { - return EOF; - } - } - - c &= 0xFF; - buffer->space[buffer->pos] = (char) c; - buffer->pos++; - if(buffer->pos > buffer->size) { - buffer->size = buffer->pos; - } - return c; -} - -int ucx_buffer_getc(UcxBuffer *buffer) { - if (ucx_buffer_eof(buffer)) { - return EOF; - } else { - int c = ((unsigned char*)buffer->space)[buffer->pos]; - buffer->pos++; - return c; - } -} - -size_t ucx_buffer_puts(UcxBuffer *buffer, const char *str) { - return ucx_buffer_write((const void*)str, 1, strlen(str), buffer); -} - -int ucx_buffer_shift_left(UcxBuffer* buffer, size_t shift) { - if (shift >= buffer->size) { - buffer->pos = buffer->size = 0; - } else { - memmove(buffer->space, buffer->space + shift, buffer->size - shift); - buffer->size -= shift; - - if (buffer->pos >= shift) { - buffer->pos -= shift; - } else { - buffer->pos = 0; - } - } - return 0; -} - -int ucx_buffer_shift_right(UcxBuffer* buffer, size_t shift) { - size_t req_capacity = buffer->size + shift; - size_t movebytes; - - // auto extend buffer, if required and enabled - if (buffer->capacity < req_capacity) { - if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { - if (ucx_buffer_extend(buffer, req_capacity - buffer->capacity)) { - return 1; - } - movebytes = buffer->size; - } else { - movebytes = buffer->capacity - shift; - } - } else { - movebytes = buffer->size; - } - - memmove(buffer->space + shift, buffer->space, movebytes); - buffer->size = shift+movebytes; - - buffer->pos += shift; - if (buffer->pos > buffer->size) { - buffer->pos = buffer->size; - } - - return 0; -} - -int ucx_buffer_shift(UcxBuffer* buffer, off_t shift) { - if (shift < 0) { - return ucx_buffer_shift_left(buffer, (size_t) (-shift)); - } else if (shift > 0) { - return ucx_buffer_shift_right(buffer, (size_t) shift); - } else { - return 0; - } -}
--- 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); -}
--- a/ucx/logging.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +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/logging.h" - -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <time.h> - -UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask) { - UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger)); - if (logger != NULL) { - logger->stream = stream; - logger->writer = (write_func)fwrite; - logger->dateformat = (char*) "%F %T %z "; - logger->level = level; - logger->mask = mask; - logger->levels = ucx_map_new(8); - - unsigned int l; - l = UCX_LOGGER_ERROR; - ucx_map_int_put(logger->levels, l, (void*) "[ERROR]"); - l = UCX_LOGGER_WARN; - ucx_map_int_put(logger->levels, l, (void*) "[WARNING]"); - l = UCX_LOGGER_INFO; - ucx_map_int_put(logger->levels, l, (void*) "[INFO]"); - l = UCX_LOGGER_DEBUG; - ucx_map_int_put(logger->levels, l, (void*) "[DEBUG]"); - l = UCX_LOGGER_TRACE; - ucx_map_int_put(logger->levels, l, (void*) "[TRACE]"); - } - - return logger; -} - -void ucx_logger_free(UcxLogger *logger) { - ucx_map_free(logger->levels); - free(logger); -} - -// estimated max. message length (documented) -#define UCX_LOGGER_MSGMAX 4096 - -void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file, - const unsigned int line, const char *format, ...) { - if (level <= logger->level) { - char msg[UCX_LOGGER_MSGMAX]; - const char *text; - size_t k = 0; - size_t n; - - if ((logger->mask & UCX_LOGGER_LEVEL) > 0) { - text = (const char*) ucx_map_int_get(logger->levels, level); - if (!text) { - text = "[UNKNOWN]"; - } - n = strlen(text); - n = n > 256 ? 256 : n; - memcpy(msg+k, text, n); - k += n; - msg[k++] = ' '; - } - if ((logger->mask & UCX_LOGGER_TIMESTAMP) > 0) { - time_t now = time(NULL); - k += strftime(msg+k, 128, logger->dateformat, localtime(&now)); - } - if ((logger->mask & UCX_LOGGER_SOURCE) > 0) { - char *fpart = strrchr(file, '/'); - if (fpart) file = fpart+1; - fpart = strrchr(file, '\\'); - if (fpart) file = fpart+1; - n = strlen(file); - memcpy(msg+k, file, n); - k += n; - k += sprintf(msg+k, ":%u ", line); - } - - if (k > 0) { - msg[k++] = '-'; msg[k++] = ' '; - } - - va_list args; - va_start (args, format); - k += vsnprintf(msg+k, UCX_LOGGER_MSGMAX-k-1, format, args); - va_end (args); - - msg[k++] = '\n'; - - logger->writer(msg, 1, k, logger->stream); - } -}
--- a/ucx/map.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,402 +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/map.h" - -#include <stdlib.h> -#include <string.h> - -UcxMap *ucx_map_new(size_t size) { - return ucx_map_new_a(NULL, size); -} - -UcxMap *ucx_map_new_a(UcxAllocator *allocator, size_t size) { - if(size == 0) { - size = 16; - } - - if(!allocator) { - allocator = ucx_default_allocator(); - } - - UcxMap *map = (UcxMap*)almalloc(allocator, sizeof(UcxMap)); - if (!map) { - return NULL; - } - - map->allocator = allocator; - map->map = (UcxMapElement**)alcalloc( - allocator, size, sizeof(UcxMapElement*)); - if(map->map == NULL) { - alfree(allocator, map); - return NULL; - } - map->size = size; - map->count = 0; - - return map; -} - -static void ucx_map_free_elmlist_contents(UcxMap *map) { - for (size_t n = 0 ; n < map->size ; n++) { - UcxMapElement *elem = map->map[n]; - if (elem != NULL) { - do { - UcxMapElement *next = elem->next; - alfree(map->allocator, elem->key.data); - alfree(map->allocator, elem); - elem = next; - } while (elem != NULL); - } - } -} - -void ucx_map_free(UcxMap *map) { - ucx_map_free_elmlist_contents(map); - alfree(map->allocator, map->map); - alfree(map->allocator, map); -} - -void ucx_map_free_content(UcxMap *map, ucx_destructor destr) { - UcxMapIterator iter = ucx_map_iterator(map); - void *val; - UCX_MAP_FOREACH(key, val, iter) { - if (destr) { - destr(val); - } else { - alfree(map->allocator, val); - } - } -} - -void ucx_map_clear(UcxMap *map) { - if (map->count == 0) { - return; // nothing to do - } - ucx_map_free_elmlist_contents(map); - memset(map->map, 0, map->size*sizeof(UcxMapElement*)); - map->count = 0; -} - -int ucx_map_copy(UcxMap const *from, UcxMap *to, copy_func fnc, void *data) { - UcxMapIterator i = ucx_map_iterator(from); - void *value; - UCX_MAP_FOREACH(key, value, i) { - if (ucx_map_put(to, key, fnc ? fnc(value, data) : value)) { - return 1; - } - } - return 0; -} - -UcxMap *ucx_map_clone(UcxMap const *map, copy_func fnc, void *data) { - return ucx_map_clone_a(ucx_default_allocator(), map, fnc, data); -} - -UcxMap *ucx_map_clone_a(UcxAllocator *allocator, - UcxMap const *map, copy_func fnc, void *data) { - size_t bs = (map->count * 5) >> 1; - UcxMap *newmap = ucx_map_new_a(allocator, bs > map->size ? bs : map->size); - if (!newmap) { - return NULL; - } - ucx_map_copy(map, newmap, fnc, data); - return newmap; -} - -int ucx_map_rehash(UcxMap *map) { - size_t load = (map->size * 3) >> 2; - if (map->count > load) { - UcxMap oldmap; - oldmap.map = map->map; - oldmap.size = map->size; - oldmap.count = map->count; - oldmap.allocator = map->allocator; - - map->size = (map->count * 5) >> 1; - map->map = (UcxMapElement**)alcalloc( - map->allocator, map->size, sizeof(UcxMapElement*)); - if (!map->map) { - *map = oldmap; - return 1; - } - map->count = 0; - ucx_map_copy(&oldmap, map, NULL, NULL); - - /* free the UcxMapElement list of oldmap */ - ucx_map_free_elmlist_contents(&oldmap); - alfree(map->allocator, oldmap.map); - } - return 0; -} - -int ucx_map_put(UcxMap *map, UcxKey key, void *data) { - UcxAllocator *allocator = map->allocator; - - if (key.hash == 0) { - key.hash = ucx_hash((const char*)key.data, key.len); - } - - struct UcxMapKey mapkey; - mapkey.hash = key.hash; - - size_t slot = mapkey.hash%map->size; - UcxMapElement *elm = map->map[slot]; - UcxMapElement *prev = NULL; - - while (elm && elm->key.hash < mapkey.hash) { - prev = elm; - elm = elm->next; - } - - if (!elm || elm->key.hash != mapkey.hash) { - UcxMapElement *e = (UcxMapElement*)almalloc( - allocator, sizeof(UcxMapElement)); - if (!e) { - return -1; - } - e->key.data = NULL; - if (prev) { - prev->next = e; - } else { - map->map[slot] = e; - } - e->next = elm; - elm = e; - } - - if (!elm->key.data) { - void *kd = almalloc(allocator, key.len); - if (!kd) { - return -1; - } - memcpy(kd, key.data, key.len); - mapkey.data = kd; - mapkey.len = key.len; - elm->key = mapkey; - map->count++; - } - elm->data = data; - - return 0; -} - -static void* ucx_map_get_and_remove(UcxMap *map, UcxKey key, int remove) { - if(key.hash == 0) { - key.hash = ucx_hash((const char*)key.data, key.len); - } - - size_t slot = key.hash%map->size; - UcxMapElement *elm = map->map[slot]; - UcxMapElement *pelm = NULL; - while (elm && elm->key.hash <= key.hash) { - if(elm->key.hash == key.hash) { - int n = (key.len > elm->key.len) ? elm->key.len : key.len; - if (memcmp(elm->key.data, key.data, n) == 0) { - void *data = elm->data; - if (remove) { - if (pelm) { - pelm->next = elm->next; - } else { - map->map[slot] = elm->next; - } - alfree(map->allocator, elm->key.data); - alfree(map->allocator, elm); - map->count--; - } - - return data; - } - } - pelm = elm; - elm = pelm->next; - } - - return NULL; -} - -void *ucx_map_get(UcxMap const *map, UcxKey key) { - return ucx_map_get_and_remove((UcxMap *)map, key, 0); -} - -void *ucx_map_remove(UcxMap *map, UcxKey key) { - return ucx_map_get_and_remove(map, key, 1); -} - -UcxKey ucx_key(const void *data, size_t len) { - UcxKey key; - key.data = data; - key.len = len; - key.hash = ucx_hash((const char*)data, len); - return key; -} - - -int ucx_hash(const char *data, size_t len) { - /* murmur hash 2 */ - - int m = 0x5bd1e995; - int r = 24; - - int h = 25 ^ len; - - int i = 0; - while (len >= 4) { - int k = data[i + 0] & 0xFF; - k |= (data[i + 1] & 0xFF) << 8; - k |= (data[i + 2] & 0xFF) << 16; - k |= (data[i + 3] & 0xFF) << 24; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - i += 4; - len -= 4; - } - - switch (len) { - case 3: h ^= (data[i + 2] & 0xFF) << 16; - /* no break */ - case 2: h ^= (data[i + 1] & 0xFF) << 8; - /* no break */ - case 1: h ^= (data[i + 0] & 0xFF); h *= m; - /* no break */ - } - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - -UcxMapIterator ucx_map_iterator(UcxMap const *map) { - UcxMapIterator i; - i.map = map; - i.cur = NULL; - i.index = 0; - return i; -} - -int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm) { - UcxMapElement *e = i->cur; - - if (e) { - e = e->next; - } else { - e = i->map->map[0]; - } - - while (i->index < i->map->size) { - if (e) { - if (e->data) { - i->cur = e; - *elm = e->data; - key->data = e->key.data; - key->hash = e->key.hash; - key->len = e->key.len; - return 1; - } - - e = e->next; - } else { - i->index++; - - if (i->index < i->map->size) { - e = i->map->map[i->index]; - } - } - } - - return 0; -} - -UcxMap* ucx_map_union(const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata) { - return ucx_map_union_a(ucx_default_allocator(), - first, second, cpfnc, cpdata); -} - -UcxMap* ucx_map_union_a(UcxAllocator *allocator, - const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata) { - UcxMap* result = ucx_map_clone_a(allocator, first, cpfnc, cpdata); - ucx_map_copy(second, result, cpfnc, cpdata); - return result; -} - -UcxMap* ucx_map_intersection(const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata) { - return ucx_map_intersection_a(ucx_default_allocator(), - first, second, cpfnc, cpdata); -} - -UcxMap* ucx_map_intersection_a(UcxAllocator *allocator, - const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata) { - UcxMap *result = ucx_map_new_a(allocator, first->size < second->size ? - first->size : second->size); - - UcxMapIterator iter = ucx_map_iterator(first); - void* value; - UCX_MAP_FOREACH(key, value, iter) { - if (ucx_map_get(second, key)) { - ucx_map_put(result, key, cpfnc ? cpfnc(value, cpdata) : value); - } - } - - return result; -} - -UcxMap* ucx_map_difference(const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata) { - return ucx_map_difference_a(ucx_default_allocator(), - first, second, cpfnc, cpdata); -} - -UcxMap* ucx_map_difference_a(UcxAllocator *allocator, - const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata) { - - UcxMap *result = ucx_map_new_a(allocator, first->size - second->count); - - UcxMapIterator iter = ucx_map_iterator(first); - void* value; - UCX_MAP_FOREACH(key, value, iter) { - if (!ucx_map_get(second, key)) { - ucx_map_put(result, key, cpfnc ? cpfnc(value, cpdata) : value); - } - } - - ucx_map_rehash(result); - return result; -} \ No newline at end of file
--- a/ucx/mempool.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,237 +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/mempool.h" - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#ifdef __cplusplus -#define __STDC_FORMAT_MACROS -#endif -#include <inttypes.h> - -/** Capsule for destructible memory chunks. */ -typedef struct { - /** The destructor for the memory chunk. */ - ucx_destructor destructor; - /** - * First byte of the memory chunk. - * Note, that the address <code>&c</code> is also the address - * of the whole memory chunk. - */ - char c; -} ucx_memchunk; - -/** Capsule for data and its destructor. */ -typedef struct { - /** The destructor for the data. */ - ucx_destructor destructor; - /** A pointer to the data. */ - void *ptr; -} ucx_regdestr; - -#ifdef __cplusplus -extern "C" -#endif -void ucx_mempool_shared_destr(void* ptr) { - ucx_regdestr *rd = (ucx_regdestr*)ptr; - rd->destructor(rd->ptr); -} - -UcxMempool *ucx_mempool_new(size_t n) { - size_t poolsz; - if(ucx_szmul(n, sizeof(void*), &poolsz)) { - return NULL; - } - - UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool)); - if (!pool) { - return NULL; - } - - pool->data = (void**) malloc(poolsz); - if (pool->data == NULL) { - free(pool); - return NULL; - } - - pool->ndata = 0; - pool->size = n; - - UcxAllocator *allocator = (UcxAllocator*)malloc(sizeof(UcxAllocator)); - if(!allocator) { - free(pool->data); - free(pool); - return NULL; - } - allocator->malloc = (ucx_allocator_malloc)ucx_mempool_malloc; - allocator->calloc = (ucx_allocator_calloc)ucx_mempool_calloc; - allocator->realloc = (ucx_allocator_realloc)ucx_mempool_realloc; - allocator->free = (ucx_allocator_free)ucx_mempool_free; - allocator->pool = pool; - pool->allocator = allocator; - - return pool; -} - -int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) { - if (newcap < pool->ndata) { - return 1; - } - - size_t newcapsz; - if(ucx_szmul(newcap, sizeof(void*), &newcapsz)) { - return 1; - } - - void **data = (void**) realloc(pool->data, newcapsz); - if (data) { - pool->data = data; - pool->size = newcap; - return 0; - } else { - return 1; - } -} - -void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { - if(((size_t)-1) - sizeof(ucx_destructor) < n) { - return NULL; - } - - if (pool->ndata >= pool->size) { - size_t newcap = pool->size*2; - if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) { - return NULL; - } - } - - void *p = malloc(sizeof(ucx_destructor) + n); - ucx_memchunk *mem = (ucx_memchunk*)p; - if (!mem) { - return NULL; - } - - mem->destructor = NULL; - pool->data[pool->ndata] = mem; - pool->ndata++; - - return &(mem->c); -} - -void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) { - size_t msz; - if(ucx_szmul(nelem, elsize, &msz)) { - return NULL; - } - - void *ptr = ucx_mempool_malloc(pool, msz); - if (!ptr) { - return NULL; - } - memset(ptr, 0, nelem * elsize); - return ptr; -} - -void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) { - if(((size_t)-1) - sizeof(ucx_destructor) < n) { - return NULL; - } - - char *mem = ((char*)ptr) - sizeof(ucx_destructor); - char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor)); - if (!newm) { - return NULL; - } - if (mem != newm) { - for(size_t i=0 ; i < pool->ndata ; i++) { - if(pool->data[i] == mem) { - pool->data[i] = newm; - return newm + sizeof(ucx_destructor); - } - } - fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", - (intptr_t)ptr, (intptr_t)pool); - abort(); - } else { - return newm + sizeof(ucx_destructor); - } -} - -void ucx_mempool_free(UcxMempool *pool, void *ptr) { - ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor)); - for(size_t i=0 ; i<pool->ndata ; i++) { - if(chunk == pool->data[i]) { - if(chunk->destructor != NULL) { - chunk->destructor(&(chunk->c)); - } - free(chunk); - size_t last_index = pool->ndata - 1; - if(i != last_index) { - pool->data[i] = pool->data[last_index]; - pool->data[last_index] = NULL; - } - pool->ndata--; - return; - } - } - fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", - (intptr_t)ptr, (intptr_t)pool); - abort(); -} - -void ucx_mempool_destroy(UcxMempool *pool) { - ucx_memchunk *chunk; - for(size_t i=0 ; i<pool->ndata ; i++) { - chunk = (ucx_memchunk*) pool->data[i]; - if(chunk) { - if(chunk->destructor) { - chunk->destructor(&(chunk->c)); - } - free(chunk); - } - } - free(pool->data); - free(pool->allocator); - free(pool); -} - -void ucx_mempool_set_destr(void *ptr, ucx_destructor func) { - *(ucx_destructor*)((char*)ptr-sizeof(ucx_destructor)) = func; -} - -void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr) { - ucx_regdestr *rd = (ucx_regdestr*)ucx_mempool_malloc( - pool, - sizeof(ucx_regdestr)); - rd->destructor = destr; - rd->ptr = ptr; - ucx_mempool_set_destr(rd, ucx_mempool_shared_destr); -} -
--- a/ucx/properties.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,264 +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/properties.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -UcxProperties *ucx_properties_new() { - UcxProperties *parser = (UcxProperties*)malloc( - sizeof(UcxProperties)); - if(!parser) { - return NULL; - } - - parser->buffer = NULL; - parser->buflen = 0; - parser->pos = 0; - parser->tmp = NULL; - parser->tmplen = 0; - parser->tmpcap = 0; - parser->error = 0; - parser->delimiter = '='; - parser->comment1 = '#'; - parser->comment2 = 0; - parser->comment3 = 0; - - return parser; -} - -void ucx_properties_free(UcxProperties *parser) { - if(parser->tmp) { - free(parser->tmp); - } - free(parser); -} - -void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len) { - parser->buffer = buf; - parser->buflen = len; - parser->pos = 0; -} - -static void parser_tmp_append(UcxProperties *parser, char *buf, size_t len) { - if(parser->tmpcap - parser->tmplen < len) { - size_t newcap = parser->tmpcap + len + 64; - parser->tmp = (char*)realloc(parser->tmp, newcap); - parser->tmpcap = newcap; - } - memcpy(parser->tmp + parser->tmplen, buf, len); - parser->tmplen += len; -} - -int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value) { - if(parser->tmplen > 0) { - char *buf = parser->buffer + parser->pos; - size_t len = parser->buflen - parser->pos; - sstr_t str = sstrn(buf, len); - sstr_t nl = sstrchr(str, '\n'); - if(nl.ptr) { - size_t newlen = (size_t)(nl.ptr - buf) + 1; - parser_tmp_append(parser, buf, newlen); - // the tmp buffer contains exactly one line now - - char *orig_buf = parser->buffer; - size_t orig_len = parser->buflen; - - parser->buffer = parser->tmp; - parser->buflen = parser->tmplen; - parser->pos = 0; - parser->tmp = NULL; - parser->tmpcap = 0; - parser->tmplen = 0; - // run ucx_properties_next with the tmp buffer as main buffer - int ret = ucx_properties_next(parser, name, value); - - // restore original buffer - parser->tmp = parser->buffer; - parser->buffer = orig_buf; - parser->buflen = orig_len; - parser->pos = newlen; - - /* - * if ret == 0 the tmp buffer contained just space or a comment - * we parse again with the original buffer to get a name/value - * or a new tmp buffer - */ - return ret ? ret : ucx_properties_next(parser, name, value); - } else { - parser_tmp_append(parser, buf, len); - return 0; - } - } else if(parser->tmp) { - free(parser->tmp); - parser->tmp = NULL; - } - - char comment1 = parser->comment1; - char comment2 = parser->comment2; - char comment3 = parser->comment3; - char delimiter = parser->delimiter; - - // get one line and parse it - while(parser->pos < parser->buflen) { - char *buf = parser->buffer + parser->pos; - size_t len = parser->buflen - parser->pos; - - /* - * First we check if we have at least one line. We also get indices of - * delimiter and comment chars - */ - size_t delimiter_index = 0; - size_t comment_index = 0; - int has_comment = 0; - - size_t i = 0; - char c = 0; - for(;i<len;i++) { - c = buf[i]; - if(c == comment1 || c == comment2 || c == comment3) { - if(comment_index == 0) { - comment_index = i; - has_comment = 1; - } - } else if(c == delimiter) { - if(delimiter_index == 0 && !has_comment) { - delimiter_index = i; - } - } else if(c == '\n') { - break; - } - } - - if(c != '\n') { - // we don't have enough data for a line - // store remaining bytes in temporary buffer for next round - parser->tmpcap = len + 128; - parser->tmp = (char*)malloc(parser->tmpcap); - parser->tmplen = len; - memcpy(parser->tmp, buf, len); - return 0; - } - - sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i); - // check line - if(delimiter_index == 0) { - line = sstrtrim(line); - if(line.length != 0) { - parser->error = 1; - } - } else { - sstr_t n = sstrn(buf, delimiter_index); - sstr_t v = sstrn( - buf + delimiter_index + 1, - line.length - delimiter_index - 1); - n = sstrtrim(n); - v = sstrtrim(v); - if(n.length != 0 || v.length != 0) { - *name = n; - *value = v; - parser->pos += i + 1; - return 1; - } else { - parser->error = 1; - } - } - - parser->pos += i + 1; - } - - return 0; -} - -int ucx_properties2map(UcxProperties *parser, UcxMap *map) { - sstr_t name; - sstr_t value; - while(ucx_properties_next(parser, &name, &value)) { - value = sstrdup_a(map->allocator, value); - if(!value.ptr) { - return 1; - } - if(ucx_map_sstr_put(map, name, value.ptr)) { - alfree(map->allocator, value.ptr); - return 1; - } - } - if (parser->error) { - return parser->error; - } else { - return 0; - } -} - -// buffer size is documented - change doc, when you change bufsize! -#define UCX_PROPLOAD_BUFSIZE 1024 -int ucx_properties_load(UcxMap *map, FILE *file) { - UcxProperties *parser = ucx_properties_new(); - if(!(parser && map && file)) { - return 1; - } - - int error = 0; - size_t r; - char buf[UCX_PROPLOAD_BUFSIZE]; - while((r = fread(buf, 1, UCX_PROPLOAD_BUFSIZE, file)) != 0) { - ucx_properties_fill(parser, buf, r); - error = ucx_properties2map(parser, map); - if (error) { - break; - } - } - ucx_properties_free(parser); - return error; -} - -int ucx_properties_store(UcxMap *map, FILE *file) { - UcxMapIterator iter = ucx_map_iterator(map); - void *v; - sstr_t value; - size_t written; - - UCX_MAP_FOREACH(k, v, iter) { - value = sstr((char*)v); - - written = 0; - written += fwrite(k.data, 1, k.len, file); - written += fwrite(" = ", 1, 3, file); - written += fwrite(value.ptr, 1, value.length, file); - written += fwrite("\n", 1, 1, file); - - if (written != k.len + value.length + 4) { - return 1; - } - } - - return 0; -} -
--- a/ucx/stack.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +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/stack.h" - -#include <string.h> - -static size_t ucx_stack_align(size_t n) { - int align = n % sizeof(void*); - if (align) { - n += sizeof(void*) - align; - } - return n; -} - -void ucx_stack_init(UcxStack *stack, char* space, size_t size) { - stack->size = size - size % sizeof(void*); - stack->space = space; - stack->top = NULL; - - stack->allocator.pool = stack; - stack->allocator.malloc = (ucx_allocator_malloc) ucx_stack_malloc; - stack->allocator.calloc = (ucx_allocator_calloc) ucx_stack_calloc; - stack->allocator.realloc = (ucx_allocator_realloc) ucx_stack_realloc; - stack->allocator.free = (ucx_allocator_free) ucx_stack_free; -} - -void *ucx_stack_malloc(UcxStack *stack, size_t n) { - - if (ucx_stack_avail(stack) < ucx_stack_align(n)) { - return NULL; - } else { - char *prev = stack->top; - if (stack->top) { - stack->top += ucx_stack_align(ucx_stack_topsize(stack)); - } else { - stack->top = stack->space; - } - - ((struct ucx_stack_metadata*)stack->top)->prev = prev; - ((struct ucx_stack_metadata*)stack->top)->size = n; - stack->top += sizeof(struct ucx_stack_metadata); - - return stack->top; - } -} - -void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize) { - void *mem = ucx_stack_malloc(stack, nelem*elsize); - memset(mem, 0, nelem*elsize); - return mem; -} - -void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) { - if (ptr == stack->top) { - if (stack->size - (stack->top - stack->space) < ucx_stack_align(n)) { - return NULL; - } else { - ((struct ucx_stack_metadata*)stack->top - 1)->size = n; - return ptr; - } - } else { - if (ucx_stack_align(((struct ucx_stack_metadata*)ptr - 1)->size) < - ucx_stack_align(n)) { - void *nptr = ucx_stack_malloc(stack, n); - if (nptr) { - memcpy(nptr, ptr, n); - ucx_stack_free(stack, ptr); - - return nptr; - } else { - return NULL; - } - } else { - ((struct ucx_stack_metadata*)ptr - 1)->size = n; - return ptr; - } - } -} - -void ucx_stack_free(UcxStack *stack, void *ptr) { - if (ptr == stack->top) { - stack->top = ((struct ucx_stack_metadata*) stack->top - 1)->prev; - } else { - struct ucx_stack_metadata *next = (struct ucx_stack_metadata*)( - (char*)ptr + - ucx_stack_align(((struct ucx_stack_metadata*) ptr - 1)->size) - ); - next->prev = ((struct ucx_stack_metadata*) ptr - 1)->prev; - } -} - -void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) { - if (ucx_stack_empty(stack)) { - return; - } - - if (dest) { - size_t len = ucx_stack_topsize(stack); - if (len > n) { - len = n; - } - - memcpy(dest, stack->top, len); - } - - ucx_stack_free(stack, stack->top); -} - -size_t ucx_stack_avail(UcxStack *stack) { - size_t avail = ((stack->top ? (stack->size - - (stack->top - stack->space) - - ucx_stack_align(ucx_stack_topsize(stack))) - : stack->size)); - - if (avail > sizeof(struct ucx_stack_metadata)) { - return avail - sizeof(struct ucx_stack_metadata); - } else { - return 0; - } -} - -void *ucx_stack_push(UcxStack *stack, size_t n, const void *data) { - void *space = ucx_stack_malloc(stack, n); - if (space) { - memcpy(space, data, n); - } - return space; -} - -void *ucx_stack_pusharr(UcxStack *stack, - size_t nelem, size_t elsize, const void *data) { - - // skip the memset by using malloc - void *space = ucx_stack_malloc(stack, nelem*elsize); - if (space) { - memcpy(space, data, nelem*elsize); - } - return space; -}
--- a/ucx/string.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,807 +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/string.h" - -#include "ucx/allocator.h" - -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <stdint.h> -#include <ctype.h> - -#ifndef _WIN32 -#include <strings.h> /* for strncasecmp() */ -#endif /* _WIN32 */ - -sstr_t sstr(char *cstring) { - sstr_t string; - string.ptr = cstring; - string.length = strlen(cstring); - return string; -} - -sstr_t sstrn(char *cstring, size_t length) { - sstr_t string; - string.ptr = cstring; - string.length = length; - return string; -} - -scstr_t scstr(const char *cstring) { - scstr_t string; - string.ptr = cstring; - string.length = strlen(cstring); - return string; -} - -scstr_t scstrn(const char *cstring, size_t length) { - scstr_t string; - string.ptr = cstring; - string.length = length; - return string; -} - - -size_t scstrnlen(size_t n, ...) { - if (n == 0) return 0; - - va_list ap; - va_start(ap, n); - - size_t size = 0; - - for (size_t i = 0 ; i < n ; i++) { - scstr_t str = va_arg(ap, scstr_t); - if(SIZE_MAX - str.length < size) { - size = SIZE_MAX; - break; - } - size += str.length; - } - va_end(ap); - - return size; -} - -static sstr_t sstrvcat_a( - UcxAllocator *a, - size_t count, - scstr_t s1, - va_list ap) { - sstr_t str; - str.ptr = NULL; - str.length = 0; - if(count < 2) { - return str; - } - - scstr_t s2 = va_arg (ap, scstr_t); - - if(((size_t)-1) - s1.length < s2.length) { - return str; - } - - scstr_t *strings = (scstr_t*) calloc(count, sizeof(scstr_t)); - if(!strings) { - return str; - } - - // get all args and overall length - strings[0] = s1; - strings[1] = s2; - size_t slen = s1.length + s2.length; - int error = 0; - for (size_t i=2;i<count;i++) { - scstr_t s = va_arg (ap, scstr_t); - strings[i] = s; - if(((size_t)-1) - s.length < slen) { - error = 1; - break; - } - slen += s.length; - } - if(error) { - free(strings); - return str; - } - - // create new string - str.ptr = (char*) almalloc(a, slen + 1); - str.length = slen; - if(!str.ptr) { - free(strings); - str.length = 0; - return str; - } - - // concatenate strings - size_t pos = 0; - for (size_t i=0;i<count;i++) { - scstr_t s = strings[i]; - memcpy(str.ptr + pos, s.ptr, s.length); - pos += s.length; - } - - str.ptr[str.length] = '\0'; - - free(strings); - - return str; -} - -sstr_t scstrcat(size_t count, scstr_t s1, ...) { - va_list ap; - va_start(ap, s1); - sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, ap); - va_end(ap); - return s; -} - -sstr_t scstrcat_a(UcxAllocator *a, size_t count, scstr_t s1, ...) { - va_list ap; - va_start(ap, s1); - sstr_t s = sstrvcat_a(a, count, s1, ap); - va_end(ap); - return s; -} - -static int ucx_substring( - size_t str_length, - size_t start, - size_t length, - size_t *newlen, - size_t *newpos) -{ - *newlen = 0; - *newpos = 0; - - if(start > str_length) { - return 0; - } - - if(length > str_length - start) { - length = str_length - start; - } - *newlen = length; - *newpos = start; - return 1; -} - -sstr_t sstrsubs(sstr_t s, size_t start) { - return sstrsubsl (s, start, s.length-start); -} - -sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { - size_t pos; - sstr_t ret = { NULL, 0 }; - if(ucx_substring(s.length, start, length, &ret.length, &pos)) { - ret.ptr = s.ptr + pos; - } - return ret; -} - -scstr_t scstrsubs(scstr_t string, size_t start) { - return scstrsubsl(string, start, string.length-start); -} - -scstr_t scstrsubsl(scstr_t s, size_t start, size_t length) { - size_t pos; - scstr_t ret = { NULL, 0 }; - if(ucx_substring(s.length, start, length, &ret.length, &pos)) { - ret.ptr = s.ptr + pos; - } - return ret; -} - - -static int ucx_strchr(const char *str, size_t length, int chr, size_t *pos) { - for(size_t i=0;i<length;i++) { - if(str[i] == chr) { - *pos = i; - return 1; - } - } - return 0; -} - -static int ucx_strrchr(const char *str, size_t length, int chr, size_t *pos) { - if(length > 0) { - for(size_t i=length ; i>0 ; i--) { - if(str[i-1] == chr) { - *pos = i-1; - return 1; - } - } - } - return 0; -} - -sstr_t sstrchr(sstr_t s, int c) { - size_t pos = 0; - if(ucx_strchr(s.ptr, s.length, c, &pos)) { - return sstrsubs(s, pos); - } - return sstrn(NULL, 0); -} - -sstr_t sstrrchr(sstr_t s, int c) { - size_t pos = 0; - if(ucx_strrchr(s.ptr, s.length, c, &pos)) { - return sstrsubs(s, pos); - } - return sstrn(NULL, 0); -} - -scstr_t scstrchr(scstr_t s, int c) { - size_t pos = 0; - if(ucx_strchr(s.ptr, s.length, c, &pos)) { - return scstrsubs(s, pos); - } - return scstrn(NULL, 0); -} - -scstr_t scstrrchr(scstr_t s, int c) { - size_t pos = 0; - if(ucx_strrchr(s.ptr, s.length, c, &pos)) { - return scstrsubs(s, pos); - } - return scstrn(NULL, 0); -} - -#define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \ - ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index]) - -#define ptable_w(useheap, ptable, index, src) do {\ - if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\ - else ((size_t*)ptable)[index] = src;\ - } while (0); - - -static const char* ucx_strstr( - const char *str, - size_t length, - const char *match, - size_t matchlen, - size_t *newlen) -{ - *newlen = length; - if (matchlen == 0) { - return str; - } - - const char *result = NULL; - size_t resultlen = 0; - - /* - * IMPORTANT: - * our prefix table contains the prefix length PLUS ONE - * this is our decision, because we want to use the full range of size_t - * the original algorithm needs a (-1) at one single place - * and we want to avoid that - */ - - /* static prefix table */ - static uint8_t s_prefix_table[256]; - - /* check pattern length and use appropriate prefix table */ - /* if the pattern exceeds static prefix table, allocate on the heap */ - register int useheap = matchlen > 255; - register void* ptable = useheap ? - calloc(matchlen+1, sizeof(size_t)): s_prefix_table; - - /* keep counter in registers */ - register size_t i, j; - - /* fill prefix table */ - i = 0; j = 0; - ptable_w(useheap, ptable, i, j); - while (i < matchlen) { - while (j >= 1 && match[j-1] != match[i]) { - ptable_r(j, useheap, ptable, j-1); - } - i++; j++; - ptable_w(useheap, ptable, i, j); - } - - /* search */ - i = 0; j = 1; - while (i < length) { - while (j >= 1 && str[i] != match[j-1]) { - ptable_r(j, useheap, ptable, j-1); - } - i++; j++; - if (j-1 == matchlen) { - size_t start = i - matchlen; - result = str + start; - resultlen = length - start; - break; - } - } - - /* if prefix table was allocated on the heap, free it */ - if (ptable != s_prefix_table) { - free(ptable); - } - - *newlen = resultlen; - return result; -} - -sstr_t scstrsstr(sstr_t string, scstr_t match) { - sstr_t result; - - size_t reslen; - const char *resstr = ucx_strstr(string.ptr, string.length, match.ptr, match.length, &reslen); - if(!resstr) { - result.ptr = NULL; - result.length = 0; - return result; - } - - size_t pos = resstr - string.ptr; - result.ptr = string.ptr + pos; - result.length = reslen; - - return result; -} - -scstr_t scstrscstr(scstr_t string, scstr_t match) { - scstr_t result; - - size_t reslen; - const char *resstr = ucx_strstr(string.ptr, string.length, match.ptr, match.length, &reslen); - if(!resstr) { - result.ptr = NULL; - result.length = 0; - return result; - } - - size_t pos = resstr - string.ptr; - result.ptr = string.ptr + pos; - result.length = reslen; - - return result; -} - -#undef ptable_r -#undef ptable_w - -sstr_t* scstrsplit(scstr_t s, scstr_t d, ssize_t *n) { - return scstrsplit_a(ucx_default_allocator(), s, d, n); -} - -sstr_t* scstrsplit_a(UcxAllocator *allocator, scstr_t s, scstr_t d, ssize_t *n) { - if (s.length == 0 || d.length == 0) { - *n = -1; - return NULL; - } - - /* special cases: delimiter is at least as large as the string */ - if (d.length >= s.length) { - /* exact match */ - if (sstrcmp(s, d) == 0) { - *n = 0; - return NULL; - } else /* no match possible */ { - *n = 1; - sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)); - if(result) { - *result = sstrdup_a(allocator, s); - } else { - *n = -2; - } - return result; - } - } - - ssize_t nmax = *n; - size_t arrlen = 16; - sstr_t* result = (sstr_t*) alcalloc(allocator, arrlen, sizeof(sstr_t)); - - if (result) { - scstr_t curpos = s; - ssize_t j = 1; - while (1) { - scstr_t match; - /* optimize for one byte delimiters */ - if (d.length == 1) { - match = curpos; - for (size_t i = 0 ; i < curpos.length ; i++) { - if (curpos.ptr[i] == *(d.ptr)) { - match.ptr = curpos.ptr + i; - break; - } - match.length--; - } - } else { - match = scstrscstr(curpos, d); - } - if (match.length > 0) { - /* is this our last try? */ - if (nmax == 0 || j < nmax) { - /* copy the current string to the array */ - scstr_t item = scstrn(curpos.ptr, match.ptr - curpos.ptr); - result[j-1] = sstrdup_a(allocator, item); - size_t processed = item.length + d.length; - curpos.ptr += processed; - curpos.length -= processed; - - /* allocate memory for the next string */ - j++; - if (j > arrlen) { - arrlen *= 2; - size_t reallocsz; - sstr_t* reallocated = NULL; - if(!ucx_szmul(arrlen, sizeof(sstr_t), &reallocsz)) { - reallocated = (sstr_t*) alrealloc( - allocator, result, reallocsz); - } - if (reallocated) { - result = reallocated; - } else { - for (ssize_t i = 0 ; i < j-1 ; i++) { - alfree(allocator, result[i].ptr); - } - alfree(allocator, result); - *n = -2; - return NULL; - } - } - } else { - /* nmax reached, copy the _full_ remaining string */ - result[j-1] = sstrdup_a(allocator, curpos); - break; - } - } else { - /* no more matches, copy last string */ - result[j-1] = sstrdup_a(allocator, curpos); - break; - } - } - *n = j; - } else { - *n = -2; - } - - return result; -} - -int scstrcmp(scstr_t s1, scstr_t s2) { - if (s1.length == s2.length) { - return memcmp(s1.ptr, s2.ptr, s1.length); - } else if (s1.length > s2.length) { - return 1; - } else { - return -1; - } -} - -int scstrcasecmp(scstr_t s1, scstr_t s2) { - if (s1.length == s2.length) { -#ifdef _WIN32 - return _strnicmp(s1.ptr, s2.ptr, s1.length); -#else - return strncasecmp(s1.ptr, s2.ptr, s1.length); -#endif - } else if (s1.length > s2.length) { - return 1; - } else { - return -1; - } -} - -sstr_t scstrdup(scstr_t s) { - return sstrdup_a(ucx_default_allocator(), s); -} - -sstr_t scstrdup_a(UcxAllocator *allocator, scstr_t s) { - sstr_t newstring; - newstring.ptr = (char*)almalloc(allocator, s.length + 1); - if (newstring.ptr) { - newstring.length = s.length; - newstring.ptr[newstring.length] = 0; - - memcpy(newstring.ptr, s.ptr, s.length); - } else { - newstring.length = 0; - } - - return newstring; -} - - -static size_t ucx_strtrim(const char *s, size_t len, size_t *newlen) { - const char *newptr = s; - size_t length = len; - - while(length > 0 && isspace(*newptr)) { - newptr++; - length--; - } - while(length > 0 && isspace(newptr[length-1])) { - length--; - } - - *newlen = length; - return newptr - s; -} - -sstr_t sstrtrim(sstr_t string) { - sstr_t newstr; - newstr.ptr = string.ptr - + ucx_strtrim(string.ptr, string.length, &newstr.length); - return newstr; -} - -scstr_t scstrtrim(scstr_t string) { - scstr_t newstr; - newstr.ptr = string.ptr - + ucx_strtrim(string.ptr, string.length, &newstr.length); - return newstr; -} - -int scstrprefix(scstr_t string, scstr_t prefix) { - if (string.length == 0) { - return prefix.length == 0; - } - if (prefix.length == 0) { - return 1; - } - - if (prefix.length > string.length) { - return 0; - } else { - return memcmp(string.ptr, prefix.ptr, prefix.length) == 0; - } -} - -int scstrsuffix(scstr_t string, scstr_t suffix) { - if (string.length == 0) { - return suffix.length == 0; - } - if (suffix.length == 0) { - return 1; - } - - if (suffix.length > string.length) { - return 0; - } else { - return memcmp(string.ptr+string.length-suffix.length, - suffix.ptr, suffix.length) == 0; - } -} - -int scstrcaseprefix(scstr_t string, scstr_t prefix) { - if (string.length == 0) { - return prefix.length == 0; - } - if (prefix.length == 0) { - return 1; - } - - if (prefix.length > string.length) { - return 0; - } else { - scstr_t subs = scstrsubsl(string, 0, prefix.length); - return scstrcasecmp(subs, prefix) == 0; - } -} - -int scstrcasesuffix(scstr_t string, scstr_t suffix) { - if (string.length == 0) { - return suffix.length == 0; - } - if (suffix.length == 0) { - return 1; - } - - if (suffix.length > string.length) { - return 0; - } else { - scstr_t subs = scstrsubs(string, string.length-suffix.length); - return scstrcasecmp(subs, suffix) == 0; - } -} - -sstr_t scstrlower(scstr_t string) { - sstr_t ret = sstrdup(string); - for (size_t i = 0; i < ret.length ; i++) { - ret.ptr[i] = tolower(ret.ptr[i]); - } - return ret; -} - -sstr_t scstrlower_a(UcxAllocator *allocator, scstr_t string) { - sstr_t ret = sstrdup_a(allocator, string); - for (size_t i = 0; i < ret.length ; i++) { - ret.ptr[i] = tolower(ret.ptr[i]); - } - return ret; -} - -sstr_t scstrupper(scstr_t string) { - sstr_t ret = sstrdup(string); - for (size_t i = 0; i < ret.length ; i++) { - ret.ptr[i] = toupper(ret.ptr[i]); - } - return ret; -} - -sstr_t scstrupper_a(UcxAllocator *allocator, scstr_t string) { - sstr_t ret = sstrdup_a(allocator, string); - for (size_t i = 0; i < ret.length ; i++) { - ret.ptr[i] = toupper(ret.ptr[i]); - } - return ret; -} - -#define REPLACE_INDEX_BUFFER_MAX 100 - -struct scstrreplace_ibuf { - size_t* buf; - unsigned int len; /* small indices */ - struct scstrreplace_ibuf* next; -}; - -static void scstrrepl_free_ibuf(struct scstrreplace_ibuf *buf) { - while (buf) { - struct scstrreplace_ibuf *next = buf->next; - free(buf->buf); - free(buf); - buf = next; - } -} - -sstr_t scstrreplacen_a(UcxAllocator *allocator, scstr_t str, - scstr_t pattern, scstr_t replacement, size_t replmax) { - - if (pattern.length == 0 || pattern.length > str.length || replmax == 0) - return sstrdup(str); - - /* Compute expected buffer length */ - size_t ibufmax = str.length / pattern.length; - size_t ibuflen = replmax < ibufmax ? replmax : ibufmax; - if (ibuflen > REPLACE_INDEX_BUFFER_MAX) { - ibuflen = REPLACE_INDEX_BUFFER_MAX; - } - - /* Allocate first index buffer */ - struct scstrreplace_ibuf *firstbuf, *curbuf; - firstbuf = curbuf = calloc(1, sizeof(struct scstrreplace_ibuf)); - if (!firstbuf) return sstrn(NULL, 0); - firstbuf->buf = calloc(ibuflen, sizeof(size_t)); - if (!firstbuf->buf) { - free(firstbuf); - return sstrn(NULL, 0); - } - - /* Search occurrences */ - scstr_t searchstr = str; - size_t found = 0; - do { - scstr_t match = scstrscstr(searchstr, pattern); - if (match.length > 0) { - /* Allocate next buffer in chain, if required */ - if (curbuf->len == ibuflen) { - struct scstrreplace_ibuf *nextbuf = - calloc(1, sizeof(struct scstrreplace_ibuf)); - if (!nextbuf) { - scstrrepl_free_ibuf(firstbuf); - return sstrn(NULL, 0); - } - nextbuf->buf = calloc(ibuflen, sizeof(size_t)); - if (!nextbuf->buf) { - free(nextbuf); - scstrrepl_free_ibuf(firstbuf); - return sstrn(NULL, 0); - } - curbuf->next = nextbuf; - curbuf = nextbuf; - } - - /* Record match index */ - found++; - size_t idx = match.ptr - str.ptr; - curbuf->buf[curbuf->len++] = idx; - searchstr.ptr = match.ptr + pattern.length; - searchstr.length = str.length - idx - pattern.length; - } else { - break; - } - } while (searchstr.length > 0 && found < replmax); - - /* Allocate result string */ - sstr_t result; - { - ssize_t adjlen = (ssize_t) replacement.length - (ssize_t) pattern.length; - size_t rcount = 0; - curbuf = firstbuf; - do { - rcount += curbuf->len; - curbuf = curbuf->next; - } while (curbuf); - result.length = str.length + rcount * adjlen; - result.ptr = almalloc(allocator, result.length); - if (!result.ptr) { - scstrrepl_free_ibuf(firstbuf); - return sstrn(NULL, 0); - } - } - - /* Build result string */ - curbuf = firstbuf; - size_t srcidx = 0; - char* destptr = result.ptr; - do { - for (size_t i = 0; i < curbuf->len; i++) { - /* Copy source part up to next match*/ - size_t idx = curbuf->buf[i]; - size_t srclen = idx - srcidx; - if (srclen > 0) { - memcpy(destptr, str.ptr+srcidx, srclen); - destptr += srclen; - srcidx += srclen; - } - - /* Copy the replacement and skip the source pattern */ - srcidx += pattern.length; - memcpy(destptr, replacement.ptr, replacement.length); - destptr += replacement.length; - } - curbuf = curbuf->next; - } while (curbuf); - memcpy(destptr, str.ptr+srcidx, str.length-srcidx); - - /* Free index buffer */ - scstrrepl_free_ibuf(firstbuf); - - return result; -} - -sstr_t scstrreplacen(scstr_t str, scstr_t pattern, - scstr_t replacement, size_t replmax) { - return scstrreplacen_a(ucx_default_allocator(), - str, pattern, replacement, replmax); -} - - -// type adjustment functions -scstr_t ucx_sc2sc(scstr_t str) { - return str; -} -scstr_t ucx_ss2sc(sstr_t str) { - scstr_t cs; - cs.ptr = str.ptr; - cs.length = str.length; - return cs; -} -scstr_t ucx_ss2c_s(scstr_t c) { - return c; -}
--- a/ucx/test.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +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/test.h" - -UcxTestSuite* ucx_test_suite_new() { - UcxTestSuite* suite = (UcxTestSuite*) malloc(sizeof(UcxTestSuite)); - if (suite != NULL) { - suite->success = 0; - suite->failure = 0; - suite->tests = NULL; - } - - return suite; -} - -void ucx_test_suite_free(UcxTestSuite* suite) { - UcxTestList *l = suite->tests; - while (l != NULL) { - UcxTestList *e = l; - l = l->next; - free(e); - } - free(suite); -} - -int ucx_test_register(UcxTestSuite* suite, UcxTest test) { - if (suite->tests) { - UcxTestList *newelem = (UcxTestList*) malloc(sizeof(UcxTestList)); - if (newelem) { - newelem->test = test; - newelem->next = NULL; - - UcxTestList *last = suite->tests; - while (last->next) { - last = last->next; - } - last->next = newelem; - - return EXIT_SUCCESS; - } else { - return EXIT_FAILURE; - } - } else { - suite->tests = (UcxTestList*) malloc(sizeof(UcxTestList)); - if (suite->tests) { - suite->tests->test = test; - suite->tests->next = NULL; - - return EXIT_SUCCESS; - } else { - return EXIT_FAILURE; - } - } -} - -void ucx_test_run(UcxTestSuite* suite, FILE* output) { - suite->success = 0; - suite->failure = 0; - for (UcxTestList* elem = suite->tests ; elem ; elem = elem->next) { - elem->test(suite, output); - } - fwrite("\nAll test completed.\n", 1, 21, output); - fprintf(output, " Total: %u\n Success: %u\n Failure: %u\n", - suite->success+suite->failure, suite->success, suite->failure); -}
--- a/ucx/ucx.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/** - * @mainpage UAP Common Extensions - * Library with common and useful functions, macros and data structures. - * <p> - * Latest available source:<br> - * <a href="https://sourceforge.net/projects/ucx/files/"> - * https://sourceforge.net/projects/ucx/files/</a> - * </p> - * - * <p> - * Repositories:<br> - * <a href="https://sourceforge.net/p/ucx/code"> - * https://sourceforge.net/p/ucx/code</a> - * - or - - * <a href="https://develop.uap-core.de/hg/ucx"> - * https://develop.uap-core.de/hg/ucx</a> - * </p> - * - * <h2>LICENCE</h2> - * - * 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/ucx.h" - -int ucx_szmul_impl(size_t a, size_t b, size_t *result) { - if(a == 0 || b == 0) { - *result = 0; - return 0; - } - size_t r = a * b; - if(r / b == a) { - *result = r; - return 0; - } else { - *result = 0; - return 1; - } -} -
--- a/ucx/ucx/allocator.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +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. - */ -/** - * Allocator for custom memory management. - * - * A UCX allocator consists of a pointer to the memory area / pool and four - * function pointers to memory management functions operating on this memory - * area / pool. These functions shall behave equivalent to the standard libc - * functions <code>malloc(), calloc(), realloc()</code> and <code>free()</code>. - * - * The signature of the memory management functions is based on the signature - * of the respective libc function but each of them takes the pointer to the - * memory area / pool as first argument. - * - * As the pointer to the memory area / pool can be arbitrarily chosen, any data - * can be provided to the memory management functions. A UcxMempool is just - * one example. - * - * @see mempool.h - * @see UcxMap - * - * @file allocator.h - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_ALLOCATOR_H -#define UCX_ALLOCATOR_H - -#include "ucx.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * A function pointer to the allocators <code>malloc()</code> function. - * @see UcxAllocator - */ -typedef void*(*ucx_allocator_malloc)(void *pool, size_t n); - -/** - * A function pointer to the allocators <code>calloc()</code> function. - * @see UcxAllocator - */ -typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size); - -/** - * A function pointer to the allocators <code>realloc()</code> function. - * @see UcxAllocator - */ -typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n); - -/** - * A function pointer to the allocators <code>free()</code> function. - * @see UcxAllocator - */ -typedef void(*ucx_allocator_free)(void *pool, void *data); - -/** - * UCX allocator data structure containing memory management functions. - */ -typedef struct { - /** Pointer to an area of memory or a complex memory pool. - * This pointer will be passed to any memory management function as first - * argument. - */ - void *pool; - /** - * The <code>malloc()</code> function for this allocator. - */ - ucx_allocator_malloc malloc; - /** - * The <code>calloc()</code> function for this allocator. - */ - ucx_allocator_calloc calloc; - /** - * The <code>realloc()</code> function for this allocator. - */ - ucx_allocator_realloc realloc; - /** - * The <code>free()</code> function for this allocator. - */ - ucx_allocator_free free; -} UcxAllocator; - -/** - * Returns a pointer to the default allocator. - * - * The default allocator contains wrappers to the standard libc memory - * management functions. Use this function to get a pointer to a globally - * available allocator. You may also define an own UcxAllocator by assigning - * #UCX_ALLOCATOR_DEFAULT to a variable and pass the address of this variable - * to any function that takes a UcxAllocator as argument. Note that using - * this function is the recommended way of passing a default allocator, thus - * it never runs out of scope. - * - * @return a pointer to the default allocator - * - * @see UCX_ALLOCATOR_DEFAULT - */ -UcxAllocator *ucx_default_allocator(); - -/** - * A wrapper for the standard libc <code>malloc()</code> function. - * @param ignore ignored (may be used by allocators for pooled memory) - * @param n argument passed to <code>malloc()</code> - * @return return value of <code>malloc()</code> - */ -void *ucx_default_malloc(void *ignore, size_t n); -/** - * A wrapper for the standard libc <code>calloc()</code> function. - * @param ignore ignored (may be used by allocators for pooled memory) - * @param n argument passed to <code>calloc()</code> - * @param size argument passed to <code>calloc()</code> - * @return return value of <code>calloc()</code> - */ -void *ucx_default_calloc(void *ignore, size_t n, size_t size); -/** - * A wrapper for the standard libc <code>realloc()</code> function. - * @param ignore ignored (may be used by allocators for pooled memory) - * @param data argumend passed to <code>realloc()</code> - * @param n argument passed to <code>realloc()</code> - * @return return value of <code>realloc()</code> - */ -void *ucx_default_realloc(void *ignore, void *data, size_t n); -/** - * A wrapper for the standard libc <code>free()</code> function. - * @param ignore ignored (may be used by allocators for pooled memory) - * @param data argument passed to <code>free()</code> - */ -void ucx_default_free(void *ignore, void *data); - -/** - * Shorthand for calling an allocators malloc function. - * @param allocator the allocator to use - * @param n size of space to allocate - * @return a pointer to the allocated memory area - */ -#define almalloc(allocator, n) ((allocator)->malloc((allocator)->pool, n)) - -/** - * Shorthand for calling an allocators calloc function. - * @param allocator the allocator to use - * @param n the count of elements the space should be allocated for - * @param size the size of each element - * @return a pointer to the allocated memory area - */ -#define alcalloc(allocator, n, size) \ - ((allocator)->calloc((allocator)->pool, n, size)) - -/** - * Shorthand for calling an allocators realloc function. - * @param allocator the allocator to use - * @param ptr the pointer to the memory area that shall be reallocated - * @param n the new size of the allocated memory area - * @return a pointer to the reallocated memory area - */ -#define alrealloc(allocator, ptr, n) \ - ((allocator)->realloc((allocator)->pool, ptr, n)) - -/** - * Shorthand for calling an allocators free function. - * @param allocator the allocator to use - * @param ptr the pointer to the memory area that shall be freed - */ -#define alfree(allocator, ptr) ((allocator)->free((allocator)->pool, ptr)) - -/** - * Convenient macro for a default allocator <code>struct</code> definition. - */ -#define UCX_ALLOCATOR_DEFAULT {NULL, \ - ucx_default_malloc, ucx_default_calloc, ucx_default_realloc, \ - ucx_default_free } - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_ALLOCATOR_H */ -
--- a/ucx/ucx/array.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,460 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2019 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. - */ -/** - * Dynamically allocated array implementation. - * - * @file array.h - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_ARRAY_H -#define UCX_ARRAY_H - -#include "ucx.h" -#include "allocator.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * UCX array type. - */ -typedef struct { - /** - * The current capacity of the array. - */ - size_t capacity; - /** - * The actual number of elements in the array. - */ - size_t size; - /** - * The size of an individual element in bytes. - */ - size_t elemsize; - /** - * A pointer to the data. - */ - void* data; - /** - * The allocator used for the data. - */ - UcxAllocator* allocator; -} UcxArray; - -/** - * Sets an element in an arbitrary user defined array. - * The data is copied from the specified data location. - * - * If the capacity is insufficient, the array is automatically reallocated and - * the possibly new pointer is stored in the <code>array</code> argument. - * - * On reallocation the capacity of the array is doubled until it is sufficient. - * The new capacity is stored back to <code>capacity</code>. - * - * @param array a pointer to location of the array pointer - * @param capacity a pointer to the capacity - * @param elmsize the size of each element - * @param idx the index of the element to set - * @param data a pointer to the element data - * @return zero on success or non-zero on error (errno will be set) - */ -#define ucx_array_util_set(array, capacity, elmsize, idx, data) \ - ucx_array_util_set_a(ucx_default_allocator(), (void**)(array), capacity, \ - elmsize, idx, data) - -/** - * Sets an element in an arbitrary user defined array. - * The data is copied from the specified data location. - * - * If the capacity is insufficient, the array is automatically reallocated - * using the specified allocator and the possibly new pointer is stored in - * the <code>array</code> argument. - * - * On reallocation the capacity of the array is doubled until it is sufficient. - * The new capacity is stored back to <code>capacity</code>. - * - * @param alloc the allocator that shall be used to reallocate the array - * @param array a pointer to location of the array pointer - * @param capacity a pointer to the capacity - * @param elmsize the size of each element - * @param idx the index of the element to set - * @param data a pointer to the element data - * @return zero on success or non-zero on error (errno will be set) - */ -int ucx_array_util_set_a(UcxAllocator* alloc, void** array, size_t* capacity, - size_t elmsize, size_t idx, void* data); - -/** - * Stores a pointer in an arbitrary user defined array. - * The element size of the array must be sizeof(void*). - * - * If the capacity is insufficient, the array is automatically reallocated and - * the possibly new pointer is stored in the <code>array</code> argument. - * - * On reallocation the capacity of the array is doubled until it is sufficient. - * The new capacity is stored back to <code>capacity</code>. - * - * @param array a pointer to location of the array pointer - * @param capacity a pointer to the capacity - * @param idx the index of the element to set - * @param ptr the pointer to store - * @return zero on success or non-zero on error (errno will be set) - */ -#define ucx_array_util_setptr(array, capacity, idx, ptr) \ - ucx_array_util_setptr_a(ucx_default_allocator(), (void**)(array), \ - capacity, idx, ptr) - -/** - * Stores a pointer in an arbitrary user defined array. - * The element size of the array must be sizeof(void*). - * - * If the capacity is insufficient, the array is automatically reallocated - * using the specified allocator and the possibly new pointer is stored in - * the <code>array</code> argument. - * - * On reallocation the capacity of the array is doubled until it is sufficient. - * The new capacity is stored back to <code>capacity</code>. - * - * @param alloc the allocator that shall be used to reallocate the array - * @param array a pointer to location of the array pointer - * @param capacity a pointer to the capacity - * @param idx the index of the element to set - * @param ptr the pointer to store - * @return zero on success or non-zero on error (errno will be set) - */ -int ucx_array_util_setptr_a(UcxAllocator* alloc, void** array, size_t* capacity, - size_t idx, void* ptr); - - -/** - * Creates a new UCX array with the given capacity and element size. - * @param capacity the initial capacity - * @param elemsize the element size - * @return a pointer to a new UCX array structure - */ -UcxArray* ucx_array_new(size_t capacity, size_t elemsize); - -/** - * Creates a new UCX array using the specified allocator. - * - * @param capacity the initial capacity - * @param elemsize the element size - * @param allocator the allocator to use - * @return a pointer to new UCX array structure - */ -UcxArray* ucx_array_new_a(size_t capacity, size_t elemsize, - UcxAllocator* allocator); - -/** - * Initializes a UCX array structure with the given capacity and element size. - * The structure must be uninitialized as the data pointer will be overwritten. - * - * @param array the structure to initialize - * @param capacity the initial capacity - * @param elemsize the element size - */ -void ucx_array_init(UcxArray* array, size_t capacity, size_t elemsize); - -/** - * Initializes a UCX array structure using the specified allocator. - * The structure must be uninitialized as the data pointer will be overwritten. - * - * @param array the structure to initialize - * @param capacity the initial capacity - * @param elemsize the element size - * @param allocator the allocator to use - */ -void ucx_array_init_a(UcxArray* array, size_t capacity, size_t elemsize, - UcxAllocator* allocator); - -/** - * Creates an shallow copy of an array. - * - * This function clones the specified array by using memcpy(). - * If the destination capacity is insufficient, an automatic reallocation is - * attempted. - * - * Note: if the destination array is uninitialized, the behavior is undefined. - * - * @param dest the array to copy to - * @param src the array to copy from - * @return zero on success, non-zero on reallocation failure. - */ -int ucx_array_clone(UcxArray* dest, UcxArray const* src); - - -/** - * Compares two UCX arrays element-wise by using a compare function. - * - * Elements of the two specified arrays are compared by using the specified - * compare function and the additional data. The type and content of this - * additional data depends on the cmp_func() used. - * - * This function always returns zero, if the element sizes of the arrays do - * not match and performs no comparisons in this case. - * - * @param array1 the first array - * @param array2 the second array - * @param cmpfnc the compare function - * @param data additional data for the compare function - * @return 1, if and only if the two arrays equal element-wise, 0 otherwise - */ -int ucx_array_equals(UcxArray const *array1, UcxArray const *array2, - cmp_func cmpfnc, void* data); - -/** - * Destroys the array. - * - * The data is freed and both capacity and count are reset to zero. - * If the array structure itself has been dynamically allocated, it has to be - * freed separately. - * - * @param array the array to destroy - */ -void ucx_array_destroy(UcxArray *array); - -/** - * Destroys and frees the array. - * - * @param array the array to free - */ -void ucx_array_free(UcxArray *array); - -/** - * Inserts elements at the end of the array. - * - * This is an O(1) operation. - * The array will automatically grow, if the capacity is exceeded. - * If a pointer to data is provided, the data is copied into the array with - * memcpy(). Otherwise the new elements are completely zeroed. - * - * @param array a pointer the array where to append the data - * @param data a pointer to the data to insert (may be <code>NULL</code>) - * @param count number of elements to copy from data (if data is - * <code>NULL</code>, zeroed elements are appended) - * @return zero on success, non-zero if a reallocation was necessary but failed - * @see ucx_array_set_from() - * @see ucx_array_append() - */ -int ucx_array_append_from(UcxArray *array, void *data, size_t count); - - -/** - * Inserts elements at the beginning of the array. - * - * This is an expensive operation, because the contents must be moved. - * If there is no particular reason to prepend data, you should use - * ucx_array_append_from() instead. - * - * @param array a pointer the array where to prepend the data - * @param data a pointer to the data to insert (may be <code>NULL</code>) - * @param count number of elements to copy from data (if data is - * <code>NULL</code>, zeroed elements are inserted) - * @return zero on success, non-zero if a reallocation was necessary but failed - * @see ucx_array_append_from() - * @see ucx_array_set_from() - * @see ucx_array_prepend() - */ -int ucx_array_prepend_from(UcxArray *array, void *data, size_t count); - - -/** - * Sets elements starting at the specified index. - * - * If the any index is out of bounds, the array automatically grows. - * The pointer to the data may be NULL, in which case the elements are zeroed. - * - * @param array a pointer the array where to set the data - * @param index the index of the element to set - * @param data a pointer to the data to insert (may be <code>NULL</code>) - * @param count number of elements to copy from data (if data is - * <code>NULL</code>, the memory in the array is zeroed) - * @return zero on success, non-zero if a reallocation was necessary but failed - * @see ucx_array_append_from() - * @see ucx_array_set() - */ -int ucx_array_set_from(UcxArray *array, size_t index, void *data, size_t count); - -/** - * Concatenates two arrays. - * - * The contents of the second array are appended to the first array in one - * single operation. The second array is otherwise left untouched. - * - * The first array may grow automatically. If this fails, both arrays remain - * unmodified. - * - * @param array1 first array - * @param array2 second array - * @return zero on success, non-zero if reallocation was necessary but failed - * or the element size does not match - */ -int ucx_array_concat(UcxArray *array1, const UcxArray *array2); - -/** - * Returns a pointer to the array element at the specified index. - * - * @param array the array to retrieve the element from - * @param index index of the element to return - * @return a pointer to the element at the specified index or <code>NULL</code>, - * if the index is greater than the array size - */ -void *ucx_array_at(UcxArray const* array, size_t index); - -/** - * Returns the index of an element containing the specified data. - * - * This function uses a cmp_func() to compare the data of each list element - * with the specified data. If no cmp_func is provided, memcmp() is used. - * - * If the array contains the data more than once, the index of the first - * occurrence is returned. - * If the array does not contain the data, the size of array is returned. - * - * @param array the array where to search for the data - * @param elem the element data - * @param cmpfnc the compare function - * @param data additional data for the compare function - * @return the index of the element containing the specified data or the size of - * the array, if the data is not found in this array - */ -size_t ucx_array_find(UcxArray const *array, void *elem, - cmp_func cmpfnc, void *data); - -/** - * Checks, if an array contains a specific element. - * - * An element is found, if ucx_array_find() returns a value less than the size. - * - * @param array the array where to search for the data - * @param elem the element data - * @param cmpfnc the compare function - * @param data additional data for the compare function - * @return 1, if and only if the array contains the specified element data - * @see ucx_array_find() - */ -int ucx_array_contains(UcxArray const *array, void *elem, - cmp_func cmpfnc, void *data); - -/** - * Sorts a UcxArray with the best available sort algorithm. - * - * The qsort_r() function is used, if available (glibc, FreeBSD or MacOS). - * The order of arguments is automatically adjusted for the FreeBSD and MacOS - * version of qsort_r(). - * - * If qsort_r() is not available, a merge sort algorithm is used, which is - * guaranteed to use no more additional memory than for exactly one element. - * - * @param array the array to sort - * @param cmpfnc the function that shall be used to compare the element data - * @param data additional data for the cmp_func() or <code>NULL</code> - */ -void ucx_array_sort(UcxArray* array, cmp_func cmpfnc, void *data); - -/** - * Removes an element from the array. - * - * This is in general an expensive operation, because several elements may - * be moved. If the order of the elements is not relevant, use - * ucx_array_remove_fast() instead. - * - * @param array pointer to the array from which the element shall be removed - * @param index the index of the element to remove - */ -void ucx_array_remove(UcxArray *array, size_t index); - -/** - * Removes an element from the array. - * - * This is an O(1) operation, but does not maintain the order of the elements. - * The last element in the array is moved to the location of the removed - * element. - * - * @param array pointer to the array from which the element shall be removed - * @param index the index of the element to remove - */ -void ucx_array_remove_fast(UcxArray *array, size_t index); - -/** - * Shrinks the memory to exactly fit the contents. - * - * After this operation, the capacity equals the size. - * - * @param array a pointer to the array - * @return zero on success, non-zero if reallocation failed - */ -int ucx_array_shrink(UcxArray* array); - -/** - * Sets the capacity of the array. - * - * If the new capacity is smaller than the size of the array, the elements - * are removed and the size is adjusted accordingly. - * - * @param array a pointer to the array - * @param capacity the new capacity - * @return zero on success, non-zero if reallocation failed - */ -int ucx_array_resize(UcxArray* array, size_t capacity); - -/** - * Resizes the array only, if the capacity is insufficient. - * - * If the requested capacity is smaller than the current capacity, this - * function does nothing. - * - * @param array a pointer to the array - * @param capacity the guaranteed capacity - * @return zero on success, non-zero if reallocation failed - */ -int ucx_array_reserve(UcxArray* array, size_t capacity); - -/** - * Resizes the capacity, if the specified number of elements would not fit. - * - * A call to ucx_array_grow(array, count) is effectively the same as - * ucx_array_reserve(array, array->size+count). - * - * @param array a pointer to the array - * @param count the number of elements that should additionally fit - * into the array - * @return zero on success, non-zero if reallocation failed - */ -int ucx_array_grow(UcxArray* array, size_t count); - - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_ARRAY_H */ -
--- a/ucx/ucx/avl.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,353 +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. - */ - - -/** - * @file avl.h - * - * AVL tree implementation. - * - * This binary search tree implementation allows average O(1) insertion and - * removal of elements (excluding binary search time). - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_AVL_H -#define UCX_AVL_H - -#include "ucx.h" -#include "allocator.h" -#include <inttypes.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * UCX AVL Node type. - * - * @see UcxAVLNode - */ -typedef struct UcxAVLNode UcxAVLNode; - -/** - * UCX AVL Node. - */ -struct UcxAVLNode { - /** - * The key for this node. - */ - intptr_t key; - /** - * Data contained by this node. - */ - void *value; - /** - * The height of this (sub)-tree. - */ - size_t height; - /** - * Parent node. - */ - UcxAVLNode *parent; - /** - * Root node of left subtree. - */ - UcxAVLNode *left; - /** - * Root node of right subtree. - */ - UcxAVLNode *right; -}; - -/** - * UCX AVL Tree. - */ -typedef struct { - /** - * The UcxAllocator that shall be used to manage the memory for node data. - */ - UcxAllocator *allocator; - /** - * Root node of the tree. - */ - UcxAVLNode *root; - /** - * Compare function that shall be used to compare the UcxAVLNode keys. - * @see UcxAVLNode.key - */ - cmp_func cmpfunc; - /** - * Custom user data. - * This data will also be provided to the cmpfunc. - */ - void *userdata; -} UcxAVLTree; - -/** - * Initializes a new UcxAVLTree with a default allocator. - * - * @param cmpfunc the compare function that shall be used - * @return a new UcxAVLTree object - * @see ucx_avl_new_a() - */ -UcxAVLTree *ucx_avl_new(cmp_func cmpfunc); - -/** - * Initializes a new UcxAVLTree with the specified allocator. - * - * The cmpfunc should be capable of comparing two keys within this AVL tree. - * So if you want to use null terminated strings as keys, you could use the - * ucx_cmp_str() function here. - * - * @param cmpfunc the compare function that shall be used - * @param allocator the UcxAllocator that shall be used - * @return a new UcxAVLTree object - */ -UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator); - -/** - * Destroys a UcxAVLTree. - * - * Note, that the contents are not automatically freed. - * Use may use #ucx_avl_free_content() before calling this function. - * - * @param tree the tree to destroy - * @see ucx_avl_free_content() - */ -void ucx_avl_free(UcxAVLTree *tree); - -/** - * Frees the contents of a UcxAVLTree. - * - * This is a convenience function that iterates over the tree and passes all - * values to the specified destructor function. - * - * If no destructor is specified (<code>NULL</code>), the free() function of - * the tree's own allocator is used. - * - * You must ensure, that it is valid to pass each value in the map to the same - * destructor function. - * - * You should free the entire tree afterwards, as the contents will be invalid. - * - * @param tree for which the contents shall be freed - * @param destr optional pointer to a destructor function - * @see ucx_avl_free() - */ -void ucx_avl_free_content(UcxAVLTree *tree, ucx_destructor destr); - -/** - * Macro for initializing a new UcxAVLTree with the default allocator and a - * ucx_cmp_ptr() compare function. - * - * @return a new default UcxAVLTree object - */ -#define ucx_avl_default_new() \ - ucx_avl_new_a(ucx_cmp_ptr, ucx_default_allocator()) - -/** - * Gets the node from the tree, that is associated with the specified key. - * @param tree the UcxAVLTree - * @param key the key - * @return the node (or <code>NULL</code>, if the key is not present) - */ -UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key); - -/** - * Gets the value from the tree, that is associated with the specified key. - * @param tree the UcxAVLTree - * @param key the key - * @return the value (or <code>NULL</code>, if the key is not present) - */ -void *ucx_avl_get(UcxAVLTree *tree, intptr_t key); - -/** - * A mode for #ucx_avl_find_node() with the same behavior as - * #ucx_avl_get_node(). - */ -#define UCX_AVL_FIND_EXACT 0 -/** - * A mode for #ucx_avl_find_node() finding the node whose key is at least - * as large as the specified key. - */ -#define UCX_AVL_FIND_LOWER_BOUNDED 1 -/** - * A mode for #ucx_avl_find_node() finding the node whose key is at most - * as large as the specified key. - */ -#define UCX_AVL_FIND_UPPER_BOUNDED 2 -/** - * A mode for #ucx_avl_find_node() finding the node with a key that is as close - * to the specified key as possible. If the key is present, the behavior is - * like #ucx_avl_get_node(). This mode only returns <code>NULL</code> on - * empty trees. - */ -#define UCX_AVL_FIND_CLOSEST 3 - -/** - * Finds a node within the tree. The following modes are supported: - * <ul> - * <li>#UCX_AVL_FIND_EXACT: the same behavior as #ucx_avl_get_node()</li> - * <li>#UCX_AVL_FIND_LOWER_BOUNDED: finds the node whose key is at least - * as large as the specified key</li> - * <li>#UCX_AVL_FIND_UPPER_BOUNDED: finds the node whose key is at most - * as large as the specified key</li> - * <li>#UCX_AVL_FIND_CLOSEST: finds the node with a key that is as close to - * the specified key as possible. If the key is present, the behavior is - * like #ucx_avl_get_node(). This mode only returns <code>NULL</code> on - * empty trees.</li> - * </ul> - * - * The distance function provided MUST agree with the compare function of - * the AVL tree. - * - * @param tree the UcxAVLTree - * @param key the key - * @param dfnc the distance function - * @param mode the find mode - * @return the node (or <code>NULL</code>, if no node can be found) - */ -UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key, - distance_func dfnc, int mode); - -/** - * Finds a value within the tree. - * See #ucx_avl_find_node() for details. - * - * @param tree the UcxAVLTree - * @param key the key - * @param dfnc the distance function - * @param mode the find mode - * @return the value (or <code>NULL</code>, if no value can be found) - */ -void *ucx_avl_find(UcxAVLTree *tree, intptr_t key, - distance_func dfnc, int mode); - -/** - * Puts a key/value pair into the tree. - * - * Attention: use this function only, if a possible old value does not need - * to be preserved. - * - * @param tree the UcxAVLTree - * @param key the key - * @param value the new value - * @return zero, if and only if the operation succeeded - */ -int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value); - -/** - * Puts a key/value pair into the tree. - * - * This is a secure function which saves the old value to the variable pointed - * at by oldvalue. - * - * @param tree the UcxAVLTree - * @param key the key - * @param value the new value - * @param oldvalue optional: a pointer to the location where a possible old - * value shall be stored - * @return zero, if and only if the operation succeeded - */ -int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value, void **oldvalue); - -/** - * Removes a node from the AVL tree. - * - * Note: the specified node is logically removed. The tree implementation - * decides which memory area is freed. In most cases the here provided node - * is freed, so its further use is generally undefined. - * - * @param tree the UcxAVLTree - * @param node the node to remove - * @return zero, if and only if an element has been removed - */ -int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node); - -/** - * Removes an element from the AVL tree. - * - * @param tree the UcxAVLTree - * @param key the key - * @return zero, if and only if an element has been removed - */ -int ucx_avl_remove(UcxAVLTree *tree, intptr_t key); - -/** - * Removes an element from the AVL tree. - * - * This is a secure function which saves the old key and value data from node - * to the variables at the location of oldkey and oldvalue (if specified), so - * they can be freed afterwards (if necessary). - * - * Note: the returned key in oldkey is possibly not the same as the provided - * key for the lookup (in terms of memory location). - * - * @param tree the UcxAVLTree - * @param key the key of the element to remove - * @param oldkey optional: a pointer to the location where the old key shall be - * stored - * @param oldvalue optional: a pointer to the location where the old value - * shall be stored - * @return zero, if and only if an element has been removed - */ -int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key, - intptr_t *oldkey, void **oldvalue); - -/** - * Counts the nodes in the specified UcxAVLTree. - * @param tree the AVL tree - * @return the node count - */ -size_t ucx_avl_count(UcxAVLTree *tree); - -/** - * Finds the in-order predecessor of the given node. - * @param node an AVL node - * @return the in-order predecessor of the given node, or <code>NULL</code> if - * the given node is the in-order minimum - */ -UcxAVLNode* ucx_avl_pred(UcxAVLNode* node); - -/** - * Finds the in-order successor of the given node. - * @param node an AVL node - * @return the in-order successor of the given node, or <code>NULL</code> if - * the given node is the in-order maximum - */ -UcxAVLNode* ucx_avl_succ(UcxAVLNode* node); - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_AVL_H */ -
--- a/ucx/ucx/buffer.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,339 +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. - */ - -/** - * @file buffer.h - * - * Advanced buffer implementation. - * - * Instances of UcxBuffer can be used to read from or to write to like one - * would do with a stream. This allows the use of ucx_stream_copy() to copy - * contents from one buffer to another. - * - * Some features for convenient use of the buffer - * can be enabled. See the documentation of the macro constants for more - * information. - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_BUFFER_H -#define UCX_BUFFER_H - -#include "ucx.h" -#include <sys/types.h> -#include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * No buffer features enabled (all flags cleared). - */ -#define UCX_BUFFER_DEFAULT 0x00 - -/** - * If this flag is enabled, the buffer will automatically free its contents. - */ -#define UCX_BUFFER_AUTOFREE 0x01 - -/** - * If this flag is enabled, the buffer will automatically extends its capacity. - */ -#define UCX_BUFFER_AUTOEXTEND 0x02 - -/** UCX Buffer. */ -typedef struct { - /** A pointer to the buffer contents. */ - char *space; - /** Current position of the buffer. */ - size_t pos; - /** Current capacity (i.e. maximum size) of the buffer. */ - size_t capacity; - /** Current size of the buffer content. */ - size_t size; - /** - * Flag register for buffer features. - * @see #UCX_BUFFER_DEFAULT - * @see #UCX_BUFFER_AUTOFREE - * @see #UCX_BUFFER_AUTOEXTEND - */ - int flags; -} UcxBuffer; - -/** - * Creates a new buffer. - * - * <b>Note:</b> you may provide <code>NULL</code> as argument for - * <code>space</code>. Then this function will allocate the space and enforce - * the #UCX_BUFFER_AUTOFREE flag. - * - * @param space pointer to the memory area, or <code>NULL</code> to allocate - * new memory - * @param capacity the capacity of the buffer - * @param flags buffer features (see UcxBuffer.flags) - * @return the new buffer - */ -UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags); - -/** - * Destroys a buffer. - * - * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer - * are also freed. - * - * @param buffer the buffer to destroy - */ -void ucx_buffer_free(UcxBuffer* buffer); - -/** - * Creates a new buffer and fills it with extracted content from another buffer. - * - * <b>Note:</b> the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer. - * - * @param src the source buffer - * @param start the start position of extraction - * @param length the count of bytes to extract (must not be zero) - * @param flags feature mask for the new buffer - * @return a new buffer containing the extraction - */ -UcxBuffer* ucx_buffer_extract(UcxBuffer *src, - size_t start, size_t length, int flags); - -/** - * A shorthand macro for the full extraction of the buffer. - * - * @param src the source buffer - * @param flags feature mask for the new buffer - * @return a new buffer with the extracted content - */ -#define ucx_buffer_clone(src,flags) \ - ucx_buffer_extract(src, 0, (src)->capacity, flags) - - -/** - * Shifts the contents of the buffer by the given offset. - * - * If the offset is positive, the contents are shifted to the right. - * If auto extension is enabled, the buffer grows, if necessary. - * In case the auto extension fails, this function returns a non-zero value and - * no contents are changed. - * If auto extension is disabled, the contents that do not fit into the buffer - * are discarded. - * - * If the offset is negative, the contents are shifted to the left where the - * first <code>shift</code> bytes are discarded. - * The new size of the buffer is the old size minus - * the absolute shift value. - * If this value is larger than the buffer size, the buffer is emptied (but - * not cleared, see the security note below). - * - * The buffer position gets shifted alongside with the content but is kept - * within the boundaries of the buffer. - * - * <b>Security note:</b> the shifting operation does <em>not</em> erase the - * previously occupied memory cells. You can easily do that manually, e.g. by - * calling <code>memset(buffer->space, 0, shift)</code> for a right shift or - * <code>memset(buffer->size, 0, buffer->capacity-buffer->size)</code> - * for a left shift. - * - * @param buffer the buffer - * @param shift the shift offset (negative means left shift) - * @return 0 on success, non-zero if a required auto-extension fails - */ -int ucx_buffer_shift(UcxBuffer* buffer, off_t shift); - -/** - * Shifts the buffer to the right. - * See ucx_buffer_shift() for details. - * - * @param buffer the buffer - * @param shift the shift offset - * @return 0 on success, non-zero if a required auto-extension fails - * @see ucx_buffer_shift() - */ -int ucx_buffer_shift_right(UcxBuffer* buffer, size_t shift); - -/** - * Shifts the buffer to the left. - * - * See ucx_buffer_shift() for details. Note, however, that this method expects - * a positive shift offset. - * - * Since a left shift cannot fail due to memory allocation problems, this - * function always returns zero. - * - * @param buffer the buffer - * @param shift the shift offset - * @return always zero - * @see ucx_buffer_shift() - */ -int ucx_buffer_shift_left(UcxBuffer* buffer, size_t shift); - - -/** - * Moves the position of the buffer. - * - * The new position is relative to the <code>whence</code> argument. - * - * SEEK_SET marks the start of the buffer. - * SEEK_CUR marks the current position. - * SEEK_END marks the end of the buffer. - * - * With an offset of zero, this function sets the buffer position to zero - * (SEEK_SET), the buffer size (SEEK_END) or leaves the buffer position - * unchanged (SEEK_CUR). - * - * @param buffer - * @param offset position offset relative to <code>whence</code> - * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END - * @return 0 on success, non-zero if the position is invalid - * - */ -int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence); - -/** - * Clears the buffer by resetting the position and deleting the data. - * - * The data is deleted by a zeroing it with call to <code>memset()</code>. - * - * @param buffer the buffer to be cleared - */ -#define ucx_buffer_clear(buffer) memset((buffer)->space, 0, (buffer)->size); \ - (buffer)->size = 0; (buffer)->pos = 0; - -/** - * Tests, if the buffer position has exceeded the buffer capacity. - * - * @param buffer the buffer to test - * @return non-zero, if the current buffer position has exceeded the last - * available byte of the buffer. - */ -int ucx_buffer_eof(UcxBuffer *buffer); - - -/** - * Extends the capacity of the buffer. - * - * <b>Note:</b> The buffer capacity increased by a power of two. I.e. - * the buffer capacity is doubled, as long as it would not hold the current - * content plus the additional required bytes. - * - * <b>Attention:</b> the argument provided is the number of <i>additional</i> - * bytes the buffer shall hold. It is <b>NOT</b> the total number of bytes the - * buffer shall hold. - * - * @param buffer the buffer to extend - * @param additional_bytes the number of additional bytes the buffer shall - * <i>at least</i> hold - * @return 0 on success or a non-zero value on failure - */ -int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes); - -/** - * Writes data to a UcxBuffer. - * - * The position of the buffer is increased by the number of bytes written. - * - * @param ptr a pointer to the memory area containing the bytes to be written - * @param size the length of one element - * @param nitems the element count - * @param buffer the UcxBuffer to write to - * @return the total count of bytes written - */ -size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, - UcxBuffer *buffer); - -/** - * Reads data from a UcxBuffer. - * - * The position of the buffer is increased by the number of bytes read. - * - * @param ptr a pointer to the memory area where to store the read data - * @param size the length of one element - * @param nitems the element count - * @param buffer the UcxBuffer to read from - * @return the total number of elements read - */ -size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems, - UcxBuffer *buffer); - -/** - * Writes a character to a buffer. - * - * The least significant byte of the argument is written to the buffer. If the - * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled, - * the buffer capacity is extended by ucx_buffer_extend(). If the feature is - * disabled or buffer extension fails, <code>EOF</code> is returned. - * - * On successful write the position of the buffer is increased. - * - * @param buffer the buffer to write to - * @param c the character to write as <code>int</code> value - * @return the byte that has bean written as <code>int</code> value or - * <code>EOF</code> when the end of the stream is reached and automatic - * extension is not enabled or not possible - */ -int ucx_buffer_putc(UcxBuffer *buffer, int c); - -/** - * Gets a character from a buffer. - * - * The current position of the buffer is increased after a successful read. - * - * @param buffer the buffer to read from - * @return the character as <code>int</code> value or <code>EOF</code>, if the - * end of the buffer is reached - */ -int ucx_buffer_getc(UcxBuffer *buffer); - -/** - * Writes a string to a buffer. - * - * @param buffer the buffer - * @param str the string - * @return the number of bytes written - */ -size_t ucx_buffer_puts(UcxBuffer *buffer, const char *str); - -/** - * Returns the complete buffer content as sstr_t. - * @param buffer the buffer - * @return the result of <code>sstrn()</code> with the buffer space and size - * as arguments - */ -#define ucx_buffer_to_sstr(buffer) sstrn((buffer)->space, (buffer)->size) - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_BUFFER_H */ -
--- a/ucx/ucx/list.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,512 +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. - */ -/** - * Doubly linked list implementation. - * - * @file list.h - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_LIST_H -#define UCX_LIST_H - -#include "ucx.h" -#include "allocator.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Loop statement for UCX lists. - * - * The first argument is the name of the iteration variable. The scope of - * this variable is limited to the <code>UCX_FOREACH</code> statement. - * - * The second argument is a pointer to the list. In most cases this will be the - * pointer to the first element of the list, but it may also be an arbitrary - * element of the list. The iteration will then start with that element. - * - * @param list The first element of the list - * @param elem The variable name of the element - */ -#define UCX_FOREACH(elem,list) \ - for (UcxList* elem = (UcxList*) list ; elem != NULL ; elem = elem->next) - -/** - * UCX list type. - * @see UcxList - */ -typedef struct UcxList UcxList; - -/** - * UCX list structure. - */ -struct UcxList { - /** - * List element payload. - */ - void *data; - /** - * Pointer to the next list element or <code>NULL</code>, if this is the - * last element. - */ - UcxList *next; - /** - * Pointer to the previous list element or <code>NULL</code>, if this is - * the first element. - */ - UcxList *prev; -}; - -/** - * Creates an element-wise copy of a list. - * - * This function clones the specified list by creating new list elements and - * copying the data with the specified copy_func(). If no copy_func() is - * specified, a shallow copy is created and the new list will reference the - * same data as the source list. - * - * @param list the list to copy - * @param cpyfnc a pointer to the function that shall copy an element (may be - * <code>NULL</code>) - * @param data additional data for the copy_func() - * @return a pointer to the copy - */ -UcxList *ucx_list_clone(const UcxList *list, copy_func cpyfnc, void* data); - -/** - * Creates an element-wise copy of a list using a UcxAllocator. - * - * See ucx_list_clone() for details. - * - * You might want to pass the allocator via the <code>data</code> parameter, - * to access it within the copy function for making deep copies. - * - * @param allocator the allocator to use - * @param list the list to copy - * @param cpyfnc a pointer to the function that shall copy an element (may be - * <code>NULL</code>) - * @param data additional data for the copy_func() - * @return a pointer to the copy - * @see ucx_list_clone() - */ -UcxList *ucx_list_clone_a(UcxAllocator *allocator, const UcxList *list, - copy_func cpyfnc, void* data); - -/** - * Compares two UCX lists element-wise by using a compare function. - * - * Each element of the two specified lists are compared by using the specified - * compare function and the additional data. The type and content of this - * additional data depends on the cmp_func() used. - * - * If the list pointers denote elements within a list, the lists are compared - * starting with the denoted elements. Thus any previous elements are not taken - * into account. This might be useful to check, if certain list tails match - * each other. - * - * @param list1 the first list - * @param list2 the second list - * @param cmpfnc the compare function - * @param data additional data for the compare function - * @return 1, if and only if the two lists equal element-wise, 0 otherwise - */ -int ucx_list_equals(const UcxList *list1, const UcxList *list2, - cmp_func cmpfnc, void* data); - -/** - * Destroys the entire list. - * - * The members of the list are not automatically freed, so ensure they are - * otherwise referenced or destroyed by ucx_list_free_contents(). - * Otherwise, a memory leak is likely to occur. - * - * <b>Caution:</b> the argument <b>MUST</b> denote an entire list (i.e. a call - * to ucx_list_first() on the argument must return the argument itself) - * - * @param list the list to free - * @see ucx_list_free_contents() - */ -void ucx_list_free(UcxList *list); - -/** - * Destroys the entire list using a UcxAllocator. - * - * See ucx_list_free() for details. - * - * @param allocator the allocator to use - * @param list the list to free - * @see ucx_list_free() - */ -void ucx_list_free_a(UcxAllocator *allocator, UcxList *list); - -/** - * Destroys the contents of the specified list by calling the specified - * destructor on each of them. - * - * Note, that the contents are not usable afterwards and the list should be - * destroyed with ucx_list_free(). - * - * If no destructor is specified (<code>NULL</code>), stdlib's free() is used. - * - * @param list the list for which the contents shall be freed - * @param destr optional destructor function - * @see ucx_list_free() - */ -void ucx_list_free_content(UcxList* list, ucx_destructor destr); - - -/** - * Inserts an element at the end of the list. - * - * This is generally an O(n) operation, as the end of the list is retrieved with - * ucx_list_last(). - * - * @param list the list where to append the data, or <code>NULL</code> to - * create a new list - * @param data the data to insert - * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to - * the newly created list otherwise - */ -UcxList *ucx_list_append(UcxList *list, void *data); - -/** - * Inserts an element at the end of the list using a UcxAllocator. - * - * See ucx_list_append() for details. - * - * @param allocator the allocator to use - * @param list the list where to append the data, or <code>NULL</code> to - * create a new list - * @param data the data to insert - * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to - * the newly created list otherwise - * @see ucx_list_append() - */ -UcxList *ucx_list_append_a(UcxAllocator *allocator, UcxList *list, void *data); - - -/** - * Inserts an element at the beginning of the list. - * - * You <i>should</i> overwrite the old list pointer by calling - * <code>mylist = ucx_list_prepend(mylist, mydata);</code>. However, you may - * also perform successive calls of ucx_list_prepend() on the same list pointer, - * as this function always searchs for the head of the list with - * ucx_list_first(). - * - * @param list the list where to insert the data or <code>NULL</code> to create - * a new list - * @param data the data to insert - * @return a pointer to the new list head - */ -UcxList *ucx_list_prepend(UcxList *list, void *data); - -/** - * Inserts an element at the beginning of the list using a UcxAllocator. - * - * See ucx_list_prepend() for details. - * - * @param allocator the allocator to use - * @param list the list where to insert the data or <code>NULL</code> to create - * a new list - * @param data the data to insert - * @return a pointer to the new list head - * @see ucx_list_prepend() - */ -UcxList *ucx_list_prepend_a(UcxAllocator *allocator, UcxList *list, void *data); - -/** - * Concatenates two lists. - * - * Either of the two arguments may be <code>NULL</code>. - * - * This function modifies the references to the next/previous element of - * the last/first element of <code>list1</code>/<code> - * list2</code>. - * - * @param list1 first list - * @param list2 second list - * @return if <code>list1</code> is <code>NULL</code>, <code>list2</code> is - * returned, otherwise <code>list1</code> is returned - */ -UcxList *ucx_list_concat(UcxList *list1, UcxList *list2); - -/** - * Returns the first element of a list. - * - * If the argument is the list pointer, it is directly returned. Otherwise - * this function traverses to the first element of the list and returns the - * list pointer. - * - * @param elem one element of the list - * @return the first element of the list, the specified element is a member of - */ -UcxList *ucx_list_first(const UcxList *elem); - -/** - * Returns the last element of a list. - * - * If the argument has no successor, it is the last element and therefore - * directly returned. Otherwise this function traverses to the last element of - * the list and returns it. - * - * @param elem one element of the list - * @return the last element of the list, the specified element is a member of - */ -UcxList *ucx_list_last(const UcxList *elem); - -/** - * Returns the list element at the specified index. - * - * @param list the list to retrieve the element from - * @param index index of the element to return - * @return the element at the specified index or <code>NULL</code>, if the - * index is greater than the list size - */ -UcxList *ucx_list_get(const UcxList *list, size_t index); - -/** - * Returns the index of an element. - * - * @param list the list where to search for the element - * @param elem the element to find - * @return the index of the element or -1 if the list does not contain the - * element - */ -ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem); - -/** - * Returns the element count of the list. - * - * @param list the list whose elements are counted - * @return the element count - */ -size_t ucx_list_size(const UcxList *list); - -/** - * Returns the index of an element containing the specified data. - * - * This function uses a cmp_func() to compare the data of each list element - * with the specified data. If no cmp_func is provided, the pointers are - * compared. - * - * If the list contains the data more than once, the index of the first - * occurrence is returned. - * - * @param list the list where to search for the data - * @param elem the element data - * @param cmpfnc the compare function - * @param data additional data for the compare function - * @return the index of the element containing the specified data or -1 if the - * data is not found in this list - */ -ssize_t ucx_list_find(const UcxList *list, void *elem, - cmp_func cmpfnc, void *data); - -/** - * Checks, if a list contains a specific element. - * - * An element is found, if ucx_list_find() returns a value greater than -1. - * - * @param list the list where to search for the data - * @param elem the element data - * @param cmpfnc the compare function - * @param data additional data for the compare function - * @return 1, if and only if the list contains the specified element data - * @see ucx_list_find() - */ -int ucx_list_contains(const UcxList *list, void *elem, - cmp_func cmpfnc, void *data); - -/** - * Sorts a UcxList with natural merge sort. - * - * This function uses O(n) additional temporary memory for merge operations - * that is automatically freed after each merge. - * - * As the head of the list might change, you <b>MUST</b> call this function - * as follows: <code>mylist = ucx_list_sort(mylist, mycmpfnc, mydata);</code>. - * - * @param list the list to sort - * @param cmpfnc the function that shall be used to compare the element data - * @param data additional data for the cmp_func() - * @return the sorted list - */ -UcxList *ucx_list_sort(UcxList *list, cmp_func cmpfnc, void *data); - -/** - * Removes an element from the list. - * - * If the first element is removed, the list pointer changes. So it is - * <i>highly recommended</i> to <i>always</i> update the pointer by calling - * <code>mylist = ucx_list_remove(mylist, myelem);</code>. - * - * @param list the list from which the element shall be removed - * @param element the element to remove - * @return returns the updated list pointer or <code>NULL</code>, if the list - * is now empty - */ -UcxList *ucx_list_remove(UcxList *list, UcxList *element); - -/** - * Removes an element from the list using a UcxAllocator. - * - * See ucx_list_remove() for details. - * - * @param allocator the allocator to use - * @param list the list from which the element shall be removed - * @param element the element to remove - * @return returns the updated list pointer or <code>NULL</code>, if the list - * @see ucx_list_remove() - */ -UcxList *ucx_list_remove_a(UcxAllocator *allocator, UcxList *list, - UcxList *element); - -/** - * Returns the union of two lists. - * - * The union is a list of unique elements regarding cmpfnc obtained from - * both source lists. - * - * @param left the left source list - * @param right the right source list - * @param cmpfnc a function to compare elements - * @param cmpdata additional data for the compare function - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the union - */ -UcxList* ucx_list_union(const UcxList *left, const UcxList *right, - cmp_func cmpfnc, void* cmpdata, - copy_func cpfnc, void* cpdata); - -/** - * Returns the union of two lists. - * - * The union is a list of unique elements regarding cmpfnc obtained from - * both source lists. - * - * @param allocator allocates the new list elements - * @param left the left source list - * @param right the right source list - * @param cmpfnc a function to compare elements - * @param cmpdata additional data for the compare function - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the union - */ -UcxList* ucx_list_union_a(UcxAllocator *allocator, - const UcxList *left, const UcxList *right, - cmp_func cmpfnc, void* cmpdata, - copy_func cpfnc, void* cpdata); - -/** - * Returns the intersection of two lists. - * - * The intersection contains all elements of the left list - * (including duplicates) that can be found in the right list. - * - * @param left the left source list - * @param right the right source list - * @param cmpfnc a function to compare elements - * @param cmpdata additional data for the compare function - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the intersection - */ -UcxList* ucx_list_intersection(const UcxList *left, const UcxList *right, - cmp_func cmpfnc, void* cmpdata, - copy_func cpfnc, void* cpdata); - -/** - * Returns the intersection of two lists. - * - * The intersection contains all elements of the left list - * (including duplicates) that can be found in the right list. - * - * @param allocator allocates the new list elements - * @param left the left source list - * @param right the right source list - * @param cmpfnc a function to compare elements - * @param cmpdata additional data for the compare function - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the intersection - */ -UcxList* ucx_list_intersection_a(UcxAllocator *allocator, - const UcxList *left, const UcxList *right, - cmp_func cmpfnc, void* cmpdata, - copy_func cpfnc, void* cpdata); - -/** - * Returns the difference of two lists. - * - * The difference contains all elements of the left list - * (including duplicates) that are not equal to any element of the right list. - * - * @param left the left source list - * @param right the right source list - * @param cmpfnc a function to compare elements - * @param cmpdata additional data for the compare function - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the difference - */ -UcxList* ucx_list_difference(const UcxList *left, const UcxList *right, - cmp_func cmpfnc, void* cmpdata, - copy_func cpfnc, void* cpdata); - -/** - * Returns the difference of two lists. - * - * The difference contains all elements of the left list - * (including duplicates) that are not equal to any element of the right list. - * - * @param allocator allocates the new list elements - * @param left the left source list - * @param right the right source list - * @param cmpfnc a function to compare elements - * @param cmpdata additional data for the compare function - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the difference - */ -UcxList* ucx_list_difference_a(UcxAllocator *allocator, - const UcxList *left, const UcxList *right, - cmp_func cmpfnc, void* cmpdata, - copy_func cpfnc, void* cpdata); - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_LIST_H */ -
--- a/ucx/ucx/logging.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,253 +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. - */ -/** - * Logging API. - * - * @file logging.h - * @author Mike Becker, Olaf Wintermann - */ -#ifndef UCX_LOGGING_H -#define UCX_LOGGING_H - -#include "ucx.h" -#include "map.h" -#include "string.h" -#include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* leave enough space for custom log levels */ - -/** Log level for error messages. */ -#define UCX_LOGGER_ERROR 0x00 - -/** Log level for warning messages. */ -#define UCX_LOGGER_WARN 0x10 - -/** Log level for information messages. */ -#define UCX_LOGGER_INFO 0x20 - -/** Log level for debug messages. */ -#define UCX_LOGGER_DEBUG 0x30 - -/** Log level for trace messages. */ -#define UCX_LOGGER_TRACE 0x40 - -/** - * Output flag for the log level. - * If this flag is set, the log message will contain the log level. - * @see UcxLogger.mask - */ -#define UCX_LOGGER_LEVEL 0x01 - -/** - * Output flag for the timestmap. - * If this flag is set, the log message will contain the timestmap. - * @see UcxLogger.mask - */ -#define UCX_LOGGER_TIMESTAMP 0x02 - -/** - * Output flag for the source. - * If this flag is set, the log message will contain the source file and line - * number. - * @see UcxLogger.mask - */ -#define UCX_LOGGER_SOURCE 0x04 - -/** - * The UCX Logger object. - */ -typedef struct { - /** The stream this logger writes its messages to.*/ - void *stream; - - /** - * The write function that shall be used. - * For standard file or stdout loggers this might be standard fwrite - * (default). - */ - write_func writer; - - /** - * The date format for timestamp outputs including the delimiter - * (default: <code>"%F %T %z "</code>). - * @see UCX_LOGGER_TIMESTAMP - */ - char *dateformat; - - /** - * The level, this logger operates on. - * If a log command is issued, the message will only be logged, if the log - * level of the message is less or equal than the log level of the logger. - */ - unsigned int level; - - /** - * A configuration mask for automatic output. - * For each flag that is set, the logger automatically outputs some extra - * information like the timestamp or the source file and line number. - * See the documentation for the flags for details. - */ - unsigned int mask; - - /** - * A map of valid log levels for this logger. - * - * The keys represent all valid log levels and the values provide string - * representations, that are used, if the UCX_LOGGER_LEVEL flag is set. - * - * The exact data types are <code>unsigned int</code> for the key and - * <code>const char*</code> for the value. - * - * @see UCX_LOGGER_LEVEL - */ - UcxMap* levels; -} UcxLogger; - -/** - * Creates a new logger. - * @param stream the stream, which the logger shall write to - * @param level the level on which the logger shall operate - * @param mask configuration mask (cf. UcxLogger.mask) - * @return a new logger object - */ -UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask); - -/** - * Destroys the logger. - * - * The map containing the valid log levels is also automatically destroyed. - * - * @param logger the logger to destroy - */ -void ucx_logger_free(UcxLogger* logger); - -/** - * Internal log function - use macros instead. - * - * This function uses the <code>format</code> and variadic arguments for a - * printf()-style output of the log message. - * - * Dependent on the UcxLogger.mask some information is prepended. The complete - * format is: - * - * <code>[LEVEL] [TIMESTAMP] [SOURCEFILE]:[LINENO] message</code> - * - * The source file name is reduced to the actual file name. This is necessary to - * get consistent behavior over different definitions of the __FILE__ macro. - * - * <b>Attention:</b> the message (including automatically generated information) - * is limited to 4096 characters. The level description is limited to - * 256 characters and the timestamp string is limited to 128 characters. - * - * @param logger the logger to use - * @param level the level to log on - * @param file information about the source file - * @param line information about the source line number - * @param format format string - * @param ... arguments - * @see ucx_logger_log() - */ -void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file, - const unsigned int line, const char* format, ...); - -/** - * Registers a custom log level. - * @param logger the logger - * @param level the log level as unsigned integer - * @param name a string literal describing the level - */ -#define ucx_logger_register_level(logger, level, name) {\ - unsigned int l; \ - l = level; \ - ucx_map_int_put(logger->levels, l, (void*) "[" name "]"); \ - } while (0); - -/** - * Logs a message at the specified level. - * @param logger the logger to use - * @param level the level to log the message on - * @param ... format string and arguments - * @see ucx_logger_logf() - */ -#define ucx_logger_log(logger, level, ...) \ - ucx_logger_logf(logger, level, __FILE__, __LINE__, __VA_ARGS__) - -/** - * Shortcut for logging an error message. - * @param logger the logger to use - * @param ... format string and arguments - * @see ucx_logger_logf() - */ -#define ucx_logger_error(logger, ...) \ - ucx_logger_log(logger, UCX_LOGGER_ERROR, __VA_ARGS__) - -/** - * Shortcut for logging an information message. - * @param logger the logger to use - * @param ... format string and arguments - * @see ucx_logger_logf() - */ -#define ucx_logger_info(logger, ...) \ - ucx_logger_log(logger, UCX_LOGGER_INFO, __VA_ARGS__) - -/** - * Shortcut for logging a warning message. - * @param logger the logger to use - * @param ... format string and arguments - * @see ucx_logger_logf() - */ -#define ucx_logger_warn(logger, ...) \ - ucx_logger_log(logger, UCX_LOGGER_WARN, __VA_ARGS__) - -/** - * Shortcut for logging a debug message. - * @param logger the logger to use - * @param ... format string and arguments - * @see ucx_logger_logf() - */ -#define ucx_logger_debug(logger, ...) \ - ucx_logger_log(logger, UCX_LOGGER_DEBUG, __VA_ARGS__) - -/** - * Shortcut for logging a trace message. - * @param logger the logger to use - * @param ... format string and arguments - * @see ucx_logger_logf() - */ -#define ucx_logger_trace(logger, ...) \ - ucx_logger_log(logger, UCX_LOGGER_TRACE, __VA_ARGS__) - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_LOGGING_H */
--- a/ucx/ucx/map.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,549 +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. - */ - -/** - * @file map.h - * - * Hash map implementation. - * - * This implementation uses murmur hash 2 and separate chaining with linked - * lists. - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_MAP_H -#define UCX_MAP_H - -#include "ucx.h" -#include "string.h" -#include "allocator.h" -#include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Loop statement for UCX maps. - * - * The <code>key</code> variable is implicitly defined, but the - * <code>value</code> variable must be already declared as type information - * cannot be inferred. - * - * @param key the variable name for the key - * @param value the variable name for the value - * @param iter a UcxMapIterator - * @see ucx_map_iterator() - */ -#define UCX_MAP_FOREACH(key,value,iter) \ - for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&value);) - -/** Type for the UCX map. @see UcxMap */ -typedef struct UcxMap UcxMap; - -/** Type for a key of a UcxMap. @see UcxKey */ -typedef struct UcxKey UcxKey; - -/** Type for an element of a UcxMap. @see UcxMapElement */ -typedef struct UcxMapElement UcxMapElement; - -/** Type for an iterator over a UcxMap. @see UcxMapIterator */ -typedef struct UcxMapIterator UcxMapIterator; - -/** Structure for the UCX map. */ -struct UcxMap { - /** An allocator that is used for the map elements. */ - UcxAllocator *allocator; - /** The array of map element lists. */ - UcxMapElement **map; - /** The size of the map is the length of the element list array. */ - size_t size; - /** The count of elements currently stored in this map. */ - size_t count; -}; - -/** Structure to publicly denote a key of a UcxMap. */ -struct UcxKey { - /** The key data. */ - const void *data; - /** The length of the key data. */ - size_t len; - /** A cache for the hash value of the key data. */ - int hash; -}; - -/** Internal structure for a key of a UcxMap. */ -struct UcxMapKey { - /** The key data. */ - void *data; - /** The length of the key data. */ - size_t len; - /** The hash value of the key data. */ - int hash; -}; - -/** Structure for an element of a UcxMap. */ -struct UcxMapElement { - /** The value data. */ - void *data; - - /** A pointer to the next element in the current list. */ - UcxMapElement *next; - - /** The corresponding key. */ - struct UcxMapKey key; -}; - -/** Structure for an iterator over a UcxMap. */ -struct UcxMapIterator { - /** The map to iterate over. */ - UcxMap const *map; - - /** The current map element. */ - UcxMapElement *cur; - - /** - * The current index of the element list array. - * <b>Attention: </b> this is <b>NOT</b> the element index! Do <b>NOT</b> - * manually iterate over the map by increasing this index. Use - * ucx_map_iter_next(). - * @see UcxMap.map*/ - size_t index; -}; - -/** - * Creates a new hash map with the specified size. - * @param size the size of the hash map - * @return a pointer to the new hash map - */ -UcxMap *ucx_map_new(size_t size); - -/** - * Creates a new hash map with the specified size using a UcxAllocator. - * @param allocator the allocator to use - * @param size the size of the hash map - * @return a pointer to the new hash map - */ -UcxMap *ucx_map_new_a(UcxAllocator *allocator, size_t size); - -/** - * Frees a hash map. - * - * <b>Note:</b> the contents are <b>not</b> freed, use ucx_map_free_content() - * before calling this function to achieve that. - * - * @param map the map to be freed - * @see ucx_map_free_content() - */ -void ucx_map_free(UcxMap *map); - -/** - * Frees the contents of a hash map. - * - * This is a convenience function that iterates over the map and passes all - * values to the specified destructor function. - * - * If no destructor is specified (<code>NULL</code>), the free() function of - * the map's own allocator is used. - * - * You must ensure, that it is valid to pass each value in the map to the same - * destructor function. - * - * You should free or clear the map afterwards, as the contents will be invalid. - * - * @param map for which the contents shall be freed - * @param destr optional pointer to a destructor function - * @see ucx_map_free() - * @see ucx_map_clear() - */ -void ucx_map_free_content(UcxMap *map, ucx_destructor destr); - -/** - * Clears a hash map. - * - * <b>Note:</b> the contents are <b>not</b> freed, use ucx_map_free_content() - * before calling this function to achieve that. - * - * @param map the map to be cleared - * @see ucx_map_free_content() - */ -void ucx_map_clear(UcxMap *map); - - -/** - * Copies contents from a map to another map using a copy function. - * - * <b>Note:</b> The destination map does not need to be empty. However, if it - * contains data with keys that are also present in the source map, the contents - * are overwritten. - * - * @param from the source map - * @param to the destination map - * @param fnc the copy function or <code>NULL</code> if the pointer address - * shall be copied - * @param data additional data for the copy function - * @return 0 on success or a non-zero value on memory allocation errors - */ -int ucx_map_copy(UcxMap const *from, UcxMap *to, copy_func fnc, void *data); - -/** - * Clones the map and rehashes if necessary. - * - * <b>Note:</b> In contrast to ucx_map_rehash() the load factor is irrelevant. - * This function <i>always</i> ensures a new UcxMap.size of at least - * 2.5*UcxMap.count. - * - * @param map the map to clone - * @param fnc the copy function to use or <code>NULL</code> if the new and - * the old map shall share the data pointers - * @param data additional data for the copy function - * @return the cloned map - * @see ucx_map_copy() - */ -UcxMap *ucx_map_clone(UcxMap const *map, copy_func fnc, void *data); - -/** - * Clones the map and rehashes if necessary. - * - * <b>Note:</b> In contrast to ucx_map_rehash() the load factor is irrelevant. - * This function <i>always</i> ensures a new UcxMap.size of at least - * 2.5*UcxMap.count. - * - * @param allocator the allocator to use for the cloned map - * @param map the map to clone - * @param fnc the copy function to use or <code>NULL</code> if the new and - * the old map shall share the data pointers - * @param data additional data for the copy function - * @return the cloned map - * @see ucx_map_copy() - */ -UcxMap *ucx_map_clone_a(UcxAllocator *allocator, - UcxMap const *map, copy_func fnc, void *data); - -/** - * Increases size of the hash map, if necessary. - * - * The load value is 0.75*UcxMap.size. If the element count exceeds the load - * value, the map needs to be rehashed. Otherwise no action is performed and - * this function simply returns 0. - * - * The rehashing process ensures, that the UcxMap.size is at least - * 2.5*UcxMap.count. So there is enough room for additional elements without - * the need of another soon rehashing. - * - * You can use this function to dramatically increase access performance. - * - * @param map the map to rehash - * @return 1, if a memory allocation error occurred, 0 otherwise - */ -int ucx_map_rehash(UcxMap *map); - -/** - * Puts a key/value-pair into the map. - * - * @param map the map - * @param key the key - * @param value the value - * @return 0 on success, non-zero value on failure - */ -int ucx_map_put(UcxMap *map, UcxKey key, void *value); - -/** - * Retrieves a value by using a key. - * - * @param map the map - * @param key the key - * @return the value - */ -void* ucx_map_get(UcxMap const *map, UcxKey key); - -/** - * Removes a key/value-pair from the map by using the key. - * - * @param map the map - * @param key the key - * @return the removed value - */ -void* ucx_map_remove(UcxMap *map, UcxKey key); - -/** - * Shorthand for putting data with a sstr_t key into the map. - * @param map the map - * @param key the key - * @param value the value - * @return 0 on success, non-zero value on failure - * @see ucx_map_put() - */ -#define ucx_map_sstr_put(map, key, value) \ - ucx_map_put(map, ucx_key(key.ptr, key.length), (void*)value) - -/** - * Shorthand for putting data with a C string key into the map. - * @param map the map - * @param key the key - * @param value the value - * @return 0 on success, non-zero value on failure - * @see ucx_map_put() - */ -#define ucx_map_cstr_put(map, key, value) \ - ucx_map_put(map, ucx_key(key, strlen(key)), (void*)value) - -/** - * Shorthand for putting data with an integer key into the map. - * @param map the map - * @param key the key - * @param value the value - * @return 0 on success, non-zero value on failure - * @see ucx_map_put() - */ -#define ucx_map_int_put(map, key, value) \ - ucx_map_put(map, ucx_key(&key, sizeof(key)), (void*)value) - -/** - * Shorthand for getting data from the map with a sstr_t key. - * @param map the map - * @param key the key - * @return the value - * @see ucx_map_get() - */ -#define ucx_map_sstr_get(map, key) \ - ucx_map_get(map, ucx_key(key.ptr, key.length)) - -/** - * Shorthand for getting data from the map with a C string key. - * @param map the map - * @param key the key - * @return the value - * @see ucx_map_get() - */ -#define ucx_map_cstr_get(map, key) \ - ucx_map_get(map, ucx_key(key, strlen(key))) - -/** - * Shorthand for getting data from the map with an integer key. - * @param map the map - * @param key the key - * @return the value - * @see ucx_map_get() - */ -#define ucx_map_int_get(map, key) \ - ucx_map_get(map, ucx_key(&key, sizeof(int))) - -/** - * Shorthand for removing data from the map with a sstr_t key. - * @param map the map - * @param key the key - * @return the removed value - * @see ucx_map_remove() - */ -#define ucx_map_sstr_remove(map, key) \ - ucx_map_remove(map, ucx_key(key.ptr, key.length)) - -/** - * Shorthand for removing data from the map with a C string key. - * @param map the map - * @param key the key - * @return the removed value - * @see ucx_map_remove() - */ -#define ucx_map_cstr_remove(map, key) \ - ucx_map_remove(map, ucx_key(key, strlen(key))) - -/** - * Shorthand for removing data from the map with an integer key. - * @param map the map - * @param key the key - * @return the removed value - * @see ucx_map_remove() - */ -#define ucx_map_int_remove(map, key) \ - ucx_map_remove(map, ucx_key(&key, sizeof(key))) - -/** - * Creates a UcxKey based on the given data. - * - * This function implicitly computes the hash. - * - * @param data the data for the key - * @param len the length of the data - * @return a UcxKey with implicitly computed hash - * @see ucx_hash() - */ -UcxKey ucx_key(const void *data, size_t len); - -/** - * Computes a murmur hash-2. - * - * @param data the data to hash - * @param len the length of the data - * @return the murmur hash-2 of the data - */ -int ucx_hash(const char *data, size_t len); - -/** - * Creates an iterator for a map. - * - * <b>Note:</b> A UcxMapIterator iterates over all elements in all element - * lists successively. Therefore the order highly depends on the key hashes and - * may vary under different map sizes. So generally you may <b>NOT</b> rely on - * the iteration order. - * - * <b>Note:</b> The iterator is <b>NOT</b> initialized. You need to call - * ucx_map_iter_next() at least once before accessing any information. However, - * it is not recommended to access the fields of a UcxMapIterator directly. - * - * @param map the map to create the iterator for - * @return an iterator initialized on the first element of the - * first element list - * @see ucx_map_iter_next() - */ -UcxMapIterator ucx_map_iterator(UcxMap const *map); - -/** - * Proceeds to the next element of the map (if any). - * - * Subsequent calls on the same iterator proceed to the next element and - * store the key/value-pair into the memory specified as arguments of this - * function. - * - * If no further elements are found, this function returns zero and leaves the - * last found key/value-pair in memory. - * - * @param iterator the iterator to use - * @param key a pointer to the memory where to store the key - * @param value a pointer to the memory where to store the value - * @return 1, if another element was found, 0 if all elements has been processed - * @see ucx_map_iterator() - */ -int ucx_map_iter_next(UcxMapIterator *iterator, UcxKey *key, void **value); - -/** - * Returns the union of two maps. - * - * The union is a fresh map which is filled by two successive calls of - * ucx_map_copy() on the two input maps. - * - * @param first the first source map - * @param second the second source map - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new map containing the union - */ -UcxMap* ucx_map_union(const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata); - -/** - * Returns the union of two maps. - * - * The union is a fresh map which is filled by two successive calls of - * ucx_map_copy() on the two input maps. - * - * @param allocator the allocator that shall be used by the new map - * @param first the first source map - * @param second the second source map - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new map containing the union - */ -UcxMap* ucx_map_union_a(UcxAllocator *allocator, - const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata); - -/** - * Returns the intersection of two maps. - * - * The intersection is defined as a copy of the first map with every element - * removed that has no valid key in the second map. - * - * @param first the first source map - * @param second the second source map - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new map containing the intersection - */ -UcxMap* ucx_map_intersection(const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata); - -/** - * Returns the intersection of two maps. - * - * The intersection is defined as a copy of the first map with every element - * removed that has no valid key in the second map. - * - * @param allocator the allocator that shall be used by the new map - * @param first the first source map - * @param second the second source map - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new map containing the intersection - */ -UcxMap* ucx_map_intersection_a(UcxAllocator *allocator, - const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata); - -/** - * Returns the difference of two maps. - * - * The difference contains a copy of all elements of the first map - * for which the corresponding keys cannot be found in the second map. - * - * @param first the first source map - * @param second the second source map - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the difference - */ -UcxMap* ucx_map_difference(const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata); - -/** - * Returns the difference of two maps. - * - * The difference contains a copy of all elements of the first map - * for which the corresponding keys cannot be found in the second map. - * - * @param allocator the allocator that shall be used by the new map - * @param first the first source map - * @param second the second source map - * @param cpfnc a function to copy the elements - * @param cpdata additional data for the copy function - * @return a new list containing the difference - */ -UcxMap* ucx_map_difference_a(UcxAllocator *allocator, - const UcxMap *first, const UcxMap *second, - copy_func cpfnc, void* cpdata); - - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_MAP_H */ -
--- a/ucx/ucx/mempool.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +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. - */ - -/** - * @file mempool.h - * - * Memory pool implementation. - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_MEMPOOL_H -#define UCX_MEMPOOL_H - -#include "ucx.h" -#include "allocator.h" -#include <stddef.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * UCX mempool structure. - */ -typedef struct { - /** UcxAllocator based on this pool */ - UcxAllocator *allocator; - - /** List of pointers to pooled memory. */ - void **data; - - /** Count of pooled memory items. */ - size_t ndata; - - /** Memory pool size. */ - size_t size; -} UcxMempool; - -/** Shorthand for a new default memory pool with a capacity of 16 elements. */ -#define ucx_mempool_new_default() ucx_mempool_new(16) - - -/** - * Creates a memory pool with the specified initial size. - * - * As the created memory pool automatically grows in size by factor two when - * trying to allocate memory on a full pool, it is recommended that you use - * a power of two for the initial size. - * - * @param n initial pool size (should be a power of two, e.g. 16) - * @return a pointer to the new memory pool - * @see ucx_mempool_new_default() - */ -UcxMempool *ucx_mempool_new(size_t n); - -/** - * Resizes a memory pool. - * - * This function will fail if the new capacity is not sufficient for the - * present data. - * - * @param pool the pool to resize - * @param newcap the new capacity - * @return zero on success or non-zero on failure - */ -int ucx_mempool_chcap(UcxMempool *pool, size_t newcap); - -/** - * Allocates pooled memory. - * - * @param pool the memory pool - * @param n amount of memory to allocate - * @return a pointer to the allocated memory - * @see ucx_allocator_malloc() - */ -void *ucx_mempool_malloc(UcxMempool *pool, size_t n); -/** - * Allocates a pooled memory array. - * - * The content of the allocated memory is set to zero. - * - * @param pool the memory pool - * @param nelem amount of elements to allocate - * @param elsize amount of memory per element - * @return a pointer to the allocated memory - * @see ucx_allocator_calloc() - */ -void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize); - -/** - * Reallocates pooled memory. - * - * If the memory to be reallocated is not contained by the specified pool, the - * behavior is undefined. - * - * @param pool the memory pool - * @param ptr a pointer to the memory that shall be reallocated - * @param n the new size of the memory - * @return a pointer to the new location of the memory - * @see ucx_allocator_realloc() - */ -void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n); - -/** - * Frees pooled memory. - * - * Before freeing the memory, the specified destructor function (if any) - * is called. - * - * If you specify memory, that is not pooled by the specified memory pool, the - * program will terminate with a call to <code>abort()</code>. - * - * @param pool the memory pool - * @param ptr a pointer to the memory that shall be freed - * @see ucx_mempool_set_destr() - */ -void ucx_mempool_free(UcxMempool *pool, void *ptr); - -/** - * Destroys a memory pool. - * - * For each element the destructor function (if any) is called and the element - * is freed. - * - * Each of the registered destructor function that has no corresponding element - * within the pool (namely those registered by ucx_mempool_reg_destr) is - * called interleaving with the element destruction, but with guarantee to the - * order in which they were registered (FIFO order). - * - * - * @param pool the mempool to destroy - */ -void ucx_mempool_destroy(UcxMempool *pool); - -/** - * Sets a destructor function for the specified memory. - * - * The destructor is automatically called when the memory is freed or the - * pool is destroyed. - * A destructor for pooled memory <b>MUST NOT</b> free the memory itself, - * as this is done by the pool. Use a destructor to free any resources - * managed by the pooled object. - * - * The only requirement for the specified memory is, that it <b>MUST</b> be - * pooled memory by a UcxMempool or an element-compatible mempool. The pointer - * to the destructor function is saved in a reserved area before the actual - * memory. - * - * @param ptr pooled memory - * @param func a pointer to the destructor function - * @see ucx_mempool_free() - * @see ucx_mempool_destroy() - */ -void ucx_mempool_set_destr(void *ptr, ucx_destructor func); - -/** - * Registers a destructor function for the specified (non-pooled) memory. - * - * This is useful, if you have memory that has not been allocated by a mempool, - * but shall be managed by a mempool. - * - * This function creates an entry in the specified mempool and the memory will - * therefore (logically) convert to pooled memory. - * <b>However, this does not cause the memory to be freed automatically!</b>. - * If you want to use this function, make the memory pool free non-pooled - * memory, the specified destructor function must call <code>free()</code> - * by itself. But keep in mind, that you then MUST NOT use this destructor - * function with pooled memory (e.g. in ucx_mempool_set_destr()), as it - * would cause a double-free. - * - * @param pool the memory pool - * @param ptr data the destructor is registered for - * @param destr a pointer to the destructor function - */ -void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr); - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_MEMPOOL_H */ -
--- a/ucx/ucx/properties.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +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. - */ -/** - * @file properties.h - * - * Load / store utilities for properties files. - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_PROPERTIES_H -#define UCX_PROPERTIES_H - -#include "ucx.h" -#include "map.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * UcxProperties object for parsing properties data. - * Most of the fields are for internal use only. You may configure the - * properties parser, e.g. by changing the used delimiter or specifying - * up to three different characters that shall introduce comments. - */ -typedef struct { - /** - * Input buffer (don't set manually). - * Automatically set by calls to ucx_properties_fill(). - */ - char *buffer; - - /** - * Length of the input buffer (don't set manually). - * Automatically set by calls to ucx_properties_fill(). - */ - size_t buflen; - - /** - * Current buffer position (don't set manually). - * Used by ucx_properties_next(). - */ - size_t pos; - - /** - * Internal temporary buffer (don't set manually). - * Used by ucx_properties_next(). - */ - char *tmp; - - /** - * Internal temporary buffer length (don't set manually). - * Used by ucx_properties_next(). - */ - size_t tmplen; - - /** - * Internal temporary buffer capacity (don't set manually). - * Used by ucx_properties_next(). - */ - size_t tmpcap; - - /** - * Parser error code. - * This is always 0 on success and a nonzero value on syntax errors. - * The value is set by ucx_properties_next(). - */ - int error; - - /** - * The delimiter that shall be used. - * This is '=' by default. - */ - char delimiter; - - /** - * The first comment character. - * This is '#' by default. - */ - char comment1; - - /** - * The second comment character. - * This is not set by default. - */ - char comment2; - - /** - * The third comment character. - * This is not set by default. - */ - char comment3; -} UcxProperties; - - -/** - * Constructs a new UcxProperties object. - * @return a pointer to the new UcxProperties object - */ -UcxProperties *ucx_properties_new(); - -/** - * Destroys a UcxProperties object. - * @param prop the UcxProperties object to destroy - */ -void ucx_properties_free(UcxProperties *prop); - -/** - * Sets the input buffer for the properties parser. - * - * After calling this function, you may parse the data by calling - * ucx_properties_next() until it returns 0. The function ucx_properties2map() - * is a convenience function that reads as much data as possible by using this - * function. - * - * - * @param prop the UcxProperties object - * @param buf a pointer to the new buffer - * @param len the payload length of the buffer - * @see ucx_properties_next() - * @see ucx_properties2map() - */ -void ucx_properties_fill(UcxProperties *prop, char *buf, size_t len); - -/** - * Retrieves the next key/value-pair. - * - * This function returns a nonzero value as long as there are key/value-pairs - * found. If no more key/value-pairs are found, you may refill the input buffer - * with ucx_properties_fill(). - * - * <b>Attention:</b> the sstr_t.ptr pointers of the output parameters point to - * memory within the input buffer of the parser and will get invalid some time. - * If you want long term copies of the key/value-pairs, use sstrdup() after - * calling this function. - * - * @param prop the UcxProperties object - * @param name a pointer to the sstr_t that shall contain the property name - * @param value a pointer to the sstr_t that shall contain the property value - * @return Nonzero, if a key/value-pair was successfully retrieved - * @see ucx_properties_fill() - */ -int ucx_properties_next(UcxProperties *prop, sstr_t *name, sstr_t *value); - -/** - * Retrieves all available key/value-pairs and puts them into a UcxMap. - * - * This is done by successive calls to ucx_properties_next() until no more - * key/value-pairs can be retrieved. - * - * The memory for the map values is allocated by the map's own allocator. - * - * @param prop the UcxProperties object - * @param map the target map - * @return The UcxProperties.error code (i.e. 0 on success). - * @see ucx_properties_fill() - * @see UcxMap.allocator - */ -int ucx_properties2map(UcxProperties *prop, UcxMap *map); - -/** - * Loads a properties file to a UcxMap. - * - * This is a convenience function that reads data from an input - * stream until the end of the stream is reached. - * - * @param map the map object to write the key/value-pairs to - * @param file the <code>FILE*</code> stream to read from - * @return 0 on success, or a non-zero value on error - * - * @see ucx_properties_fill() - * @see ucx_properties2map() - */ -int ucx_properties_load(UcxMap *map, FILE *file); - -/** - * Stores a UcxMap to a file. - * - * The key/value-pairs are written by using the following format: - * - * <code>[key] = [value]\\n</code> - * - * @param map the map to store - * @param file the <code>FILE*</code> stream to write to - * @return 0 on success, or a non-zero value on error - */ -int ucx_properties_store(UcxMap *map, FILE *file); - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_PROPERTIES_H */ -
--- a/ucx/ucx/stack.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,240 +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. - */ - -/** - * @file stack.h - * - * Default stack memory allocation implementation. - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_STACK_H -#define UCX_STACK_H - -#include "ucx.h" -#include "allocator.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * UCX stack structure. - */ -typedef struct { - /** UcxAllocator based on this stack */ - UcxAllocator allocator; - - /** Stack size. */ - size_t size; - - /** Pointer to the bottom of the stack */ - char *space; - - /** Pointer to the top of the stack */ - char *top; -} UcxStack; - -/** - * Metadata for each UCX stack element. - */ -struct ucx_stack_metadata { - /** - * Location of the previous element (<code>NULL</code> if this is the first) - */ - char *prev; - - /** Size of this element */ - size_t size; -}; - -/** - * Initializes UcxStack structure with memory. - * - * @param stack a pointer to an uninitialized stack structure - * @param space the memory area that shall be managed - * @param size size of the memory area - * @return a new UcxStack structure - */ -void ucx_stack_init(UcxStack *stack, char* space, size_t size); - -/** - * Allocates stack memory. - * - * @param stack a pointer to the stack - * @param n amount of memory to allocate - * @return a pointer to the allocated memory or <code>NULL</code> on stack - * overflow - * @see ucx_allocator_malloc() - */ -void *ucx_stack_malloc(UcxStack *stack, size_t n); - -/** - * Allocates memory with #ucx_stack_malloc() and copies the specified data if - * the allocation was successful. - * - * @param stack a pointer to the stack - * @param n amount of memory to allocate - * @param data a pointer to the data to copy - * @return a pointer to the allocated memory - * @see ucx_stack_malloc - */ -void *ucx_stack_push(UcxStack *stack, size_t n, const void *data); - -/** - * Allocates an array of stack memory - * - * The content of the allocated memory is set to zero. - * - * @param stack a pointer to the stack - * @param nelem amount of elements to allocate - * @param elsize amount of memory per element - * @return a pointer to the allocated memory - * @see ucx_allocator_calloc() - */ -void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize); - -/** - * Allocates memory with #ucx_stack_calloc() and copies the specified data if - * the allocation was successful. - * - * @param stack a pointer to the stack - * @param nelem amount of elements to allocate - * @param elsize amount of memory per element - * @param data a pointer to the data - * @return a pointer to the allocated memory - * @see ucx_stack_calloc - */ -void *ucx_stack_pusharr(UcxStack *stack, - size_t nelem, size_t elsize, const void *data); - -/** - * Reallocates memory on the stack. - * - * Shrinking memory is always safe. Extending memory can be very expensive. - * - * @param stack the stack - * @param ptr a pointer to the memory that shall be reallocated - * @param n the new size of the memory - * @return a pointer to the new location of the memory - * @see ucx_allocator_realloc() - */ -void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n); - -/** - * Frees memory on the stack. - * - * Freeing stack memory behaves in a special way. - * - * If the element, that should be freed, is the top most element of the stack, - * it is removed from the stack. Otherwise it is marked as freed. Marked - * elements are removed, when they become the top most elements of the stack. - * - * @param stack a pointer to the stack - * @param ptr a pointer to the memory that shall be freed - */ -void ucx_stack_free(UcxStack *stack, void *ptr); - - -/** - * Returns the size of the top most element. - * @param stack a pointer to the stack - * @return the size of the top most element - */ -#define ucx_stack_topsize(stack) ((stack)->top ? ((struct ucx_stack_metadata*)\ - (stack)->top - 1)->size : 0) - -/** - * Removes the top most element from the stack and copies the content to <code> - * dest</code>, if specified. - * - * Use #ucx_stack_topsize()# to get the amount of memory that must be available - * at the location of <code>dest</code>. - * - * @param stack a pointer to the stack - * @param dest the location where the contents shall be written to, or <code> - * NULL</code>, if the element shall only be removed. - * @see ucx_stack_free - * @see ucx_stack_popn - */ -#define ucx_stack_pop(stack, dest) ucx_stack_popn(stack, dest, (size_t)-1) - -/** - * Removes the top most element from the stack and copies the content to <code> - * dest</code>. - * - * This function copies at most <code>n</code> bytes to the destination, but - * the element is always freed as a whole. - * If the element was larger than <code>n</code>, the remaining data is lost. - * - * @param stack a pointer to the stack - * @param dest the location where the contents shall be written to - * @param n copies at most n bytes to <code>dest</code> - * @see ucx_stack_pop - */ -void ucx_stack_popn(UcxStack *stack, void *dest, size_t n); - -/** - * Returns the remaining available memory on the specified stack. - * - * @param stack a pointer to the stack - * @return the remaining available memory - */ -size_t ucx_stack_avail(UcxStack *stack); - -/** - * Checks, if the stack is empty. - * - * @param stack a pointer to the stack - * @return nonzero, if the stack is empty, zero otherwise - */ -#define ucx_stack_empty(stack) (!(stack)->top) - -/** - * Computes a recommended size for the stack memory area. Note, that - * reallocations have not been taken into account, so you might need to reserve - * twice as much memory to allow many reallocations. - * - * @param size the approximate payload - * @param elems the approximate count of element allocations - * @return a recommended size for the stack space based on the information - * provided - */ -#define ucx_stack_dim(size, elems) (size+sizeof(struct ucx_stack_metadata) * \ - (elems + 1)) - - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_STACK_H */ -
--- a/ucx/ucx/string.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1201 +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. - */ -/** - * Bounded string implementation. - * - * The UCX strings (<code>sstr_t</code>) provide an alternative to C strings. - * The main difference to C strings is, that <code>sstr_t</code> does <b>not - * need to be <code>NULL</code>-terminated</b>. Instead the length is stored - * within the structure. - * - * When using <code>sstr_t</code>, developers must be full aware of what type - * of string (<code>NULL</code>-terminated) or not) they are using, when - * accessing the <code>char* ptr</code> directly. - * - * The UCX string module provides some common string functions, known from - * standard libc, working with <code>sstr_t</code>. - * - * @file string.h - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_STRING_H -#define UCX_STRING_H - -#include "ucx.h" -#include "allocator.h" -#include <stddef.h> - -/* - * Use this macro to disable the shortcuts if you experience macro collision. - */ -#ifndef UCX_NO_SSTR_SHORTCUTS -/** - * Shortcut for a <code>sstr_t struct</code> - * or <code>scstr_t struct</code> literal. - */ -#define ST(s) { s, sizeof(s)-1 } - -/** Shortcut for the conversion of a C string to a <code>sstr_t</code>. */ -#define S(s) sstrn(s, sizeof(s)-1) - -/** Shortcut for the conversion of a C string to a <code>scstr_t</code>. */ -#define SC(s) scstrn(s, sizeof(s)-1) -#endif /* UCX_NO_SSTR_SHORTCUTS */ - -/* - * Use this macro to disable the format macros. - */ -#ifndef UCX_NO_SSTR_FORMAT_MACROS -/** Expands a sstr_t or scstr_t to printf arguments. */ -#define SFMT(s) (int) (s).length, (s).ptr - -/** Format specifier for a sstr_t or scstr_t. */ -#define PRIsstr ".*s" -#endif /* UCX_NO_SSTR_FORMAT_MACROS */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The UCX string structure. - */ -typedef struct { - /** A pointer to the string - * (<b>not necessarily <code>NULL</code>-terminated</b>) */ - char *ptr; - /** The length of the string */ - size_t length; -} sstr_t; - -/** - * The UCX string structure for immutable (constant) strings. - */ -typedef struct { - /** A constant pointer to the immutable string - * (<b>not necessarily <code>NULL</code>-terminated</b>) */ - const char *ptr; - /** The length of the string */ - size_t length; -} scstr_t; - -#ifdef __cplusplus -} -#endif - - -#ifdef __cplusplus -/** - * One of two type adjustment functions that return an scstr_t. - * - * Used <b>internally</b> to convert a UCX string to an immutable UCX string. - * - * <b>Do not use this function manually.</b> - * - * @param str some sstr_t - * @return an immutable (scstr_t) version of the provided string. - */ -inline scstr_t s2scstr(sstr_t s) { - scstr_t c; - c.ptr = s.ptr; - c.length = s.length; - return c; -} - -/** - * One of two type adjustment functions that return an scstr_t. - * - * Used <b>internally</b> to convert a UCX string to an immutable UCX string. - * This variant is used, when the string is already immutable and no operation - * needs to be performed. - * - * <b>Do not use this function manually.</b> - * - * @param str some scstr_t - * @return the argument itself - */ -inline scstr_t s2scstr(scstr_t str) { - return str; -} - -/** - * Converts a UCX string to an immutable UCX string (scstr_t). - * @param str some UCX string - * @return an immutable version of the provided string - */ -#define SCSTR(s) s2scstr(s) -#else - -/** - * One of two type adjustment functions that return an scstr_t. - * - * Used <b>internally</b> to convert a UCX string to an immutable UCX string. - * This variant is used, when the string is already immutable and no operation - * needs to be performed. - * - * <b>Do not use this function manually.</b> - * - * @param str some scstr_t - * @return the argument itself - */ -scstr_t ucx_sc2sc(scstr_t str); - -/** - * One of two type adjustment functions that return an scstr_t. - * - * Used <b>internally</b> to convert a UCX string to an immutable UCX string. - * - * <b>Do not use this function manually.</b> - * - * @param str some sstr_t - * @return an immutable (scstr_t) version of the provided string. - */ -scstr_t ucx_ss2sc(sstr_t str); - -#if __STDC_VERSION__ >= 201112L -/** - * Converts a UCX string to an immutable UCX string (scstr_t). - * @param str some UCX string - * @return an immutable version of the provided string - */ -#define SCSTR(str) _Generic(str, sstr_t: ucx_ss2sc, scstr_t: ucx_sc2sc)(str) - -#elif defined(__GNUC__) || defined(__clang__) - -/** - * Converts a UCX string to an immutable UCX string (scstr_t). - * @param str some UCX string - * @return an immutable version of the provided string - */ -#define SCSTR(str) __builtin_choose_expr( \ - __builtin_types_compatible_p(typeof(str), sstr_t), \ - ucx_ss2sc, \ - ucx_sc2sc)(str) - -#elif defined(__sun) - -/** - * Converts a UCX string to an immutable UCX string (scstr_t). - * @param str some UCX string - * @return the an immutable version of the provided string - */ -#define SCSTR(str) ({typeof(str) ucx_tmp_var_str = str; \ - scstr_t ucx_tmp_var_c; \ - ucx_tmp_var_c.ptr = ucx_tmp_var_str.ptr;\ - ucx_tmp_var_c.length = ucx_tmp_var_str.length;\ - ucx_tmp_var_c; }) -#else /* no generics and no builtins */ - -/** - * Converts a UCX string to an immutable UCX string (scstr_t). - * - * This <b>internal</b> function (ab)uses the C standard an expects one single - * argument which is then implicitly converted to scstr_t without a warning. - * - * <b>Do not use this function manually.</b> - * - * @return the an immutable version of the provided string - */ -scstr_t ucx_ss2c_s(); - -/** - * Converts a UCX string to an immutable UCX string (scstr_t). - * @param str some UCX string - * @return the an immutable version of the provided string - */ -#define SCSTR(str) ucx_ss2c_s(str) -#endif /* C11 feature test */ - -#endif /* C++ */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * Creates a new sstr_t based on a C string. - * - * The length is implicitly inferred by using a call to <code>strlen()</code>. - * - * <b>Note:</b> the sstr_t will share the specified pointer to the C string. - * If you do want a copy, use sstrdup() on the return value of this function. - * - * If you need to wrap a constant string, use scstr(). - * - * @param cstring the C string to wrap - * @return a new sstr_t containing the C string - * - * @see sstrn() - */ -sstr_t sstr(char *cstring); - -/** - * Creates a new sstr_t of the specified length based on a C string. - * - * <b>Note:</b> the sstr_t will share the specified pointer to the C string. - * If you do want a copy, use sstrdup() on the return value of this function. - * - * If you need to wrap a constant string, use scstrn(). - * - * @param cstring the C string to wrap - * @param length the length of the string - * @return a new sstr_t containing the C string - * - * @see sstr() - * @see S() - */ -sstr_t sstrn(char *cstring, size_t length); - -/** - * Creates a new scstr_t based on a constant C string. - * - * The length is implicitly inferred by using a call to <code>strlen()</code>. - * - * <b>Note:</b> the scstr_t will share the specified pointer to the C string. - * If you do want a copy, use scstrdup() on the return value of this function. - * - * @param cstring the C string to wrap - * @return a new scstr_t containing the C string - * - * @see scstrn() - */ -scstr_t scstr(const char *cstring); - - -/** - * Creates a new scstr_t of the specified length based on a constant C string. - * - * <b>Note:</b> the scstr_t will share the specified pointer to the C string. - * If you do want a copy, use scstrdup() on the return value of this function. * - * - * @param cstring the C string to wrap - * @param length the length of the string - * @return a new scstr_t containing the C string - * - * @see scstr() - */ -scstr_t scstrn(const char *cstring, size_t length); - -/** - * Returns the accumulated length of all specified strings. - * - * <b>Attention:</b> if the count argument is larger than the count of the - * specified strings, the behavior is undefined. - * - * @param count the total number of specified strings - * @param ... all strings - * @return the accumulated length of all strings - */ -size_t scstrnlen(size_t count, ...); - -/** - * Returns the accumulated length of all specified strings. - * - * <b>Attention:</b> if the count argument is larger than the count of the - * specified strings, the behavior is undefined. - * - * @param count the total number of specified strings - * @param ... all strings - * @return the cumulated length of all strings - */ -#define sstrnlen(count, ...) scstrnlen(count, __VA_ARGS__) - -/** - * Concatenates two or more strings. - * - * The resulting string will be allocated by standard <code>malloc()</code>. - * So developers <b>MUST</b> pass the sstr_t.ptr to <code>free()</code>. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated. - * - * @param count the total number of strings to concatenate - * @param s1 first string - * @param ... all remaining strings - * @return the concatenated string - */ -sstr_t scstrcat(size_t count, scstr_t s1, ...); - -/** - * Concatenates two or more strings. - * - * The resulting string will be allocated by standard <code>malloc()</code>. - * So developers <b>MUST</b> pass the sstr_t.ptr to <code>free()</code>. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated. - * - * @param count the total number of strings to concatenate - * @param s1 first string - * @param ... all remaining strings - * @return the concatenated string - */ -#define sstrcat(count, s1, ...) scstrcat(count, SCSTR(s1), __VA_ARGS__) - -/** - * Concatenates two or more strings using a UcxAllocator. - * - * The resulting string must be freed by the allocators <code>free()</code> - * implementation. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated. - * - * @param alloc the allocator to use - * @param count the total number of strings to concatenate - * @param s1 first string - * @param ... all remaining strings - * @return the concatenated string - * - * @see scstrcat() - */ -sstr_t scstrcat_a(UcxAllocator *alloc, size_t count, scstr_t s1, ...); - -/** - * Concatenates two or more strings using a UcxAllocator. - * - * The resulting string must be freed by the allocators <code>free()</code> - * implementation. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated. - * - * @param alloc the allocator to use - * @param count the total number of strings to concatenate - * @param s1 first string - * @param ... all remaining strings - * @return the concatenated string - * - * @see sstrcat() - */ -#define sstrcat_a(alloc, count, s1, ...) \ - scstrcat_a(alloc, count, SCSTR(s1), __VA_ARGS__) - -/** - * Returns a substring starting at the specified location. - * - * <b>Attention:</b> the new string references the same memory area as the - * input string and is <b>NOT</b> required to be <code>NULL</code>-terminated. - * Use sstrdup() to get a copy. - * - * @param string input string - * @param start start location of the substring - * @return a substring of <code>string</code> starting at <code>start</code> - * - * @see sstrsubsl() - * @see sstrchr() - */ -sstr_t sstrsubs(sstr_t string, size_t start); - -/** - * Returns a substring with the given length starting at the specified location. - * - * <b>Attention:</b> the new string references the same memory area as the - * input string and is <b>NOT</b> required to be <code>NULL</code>-terminated. - * Use sstrdup() to get a copy. - * - * @param string input string - * @param start start location of the substring - * @param length the maximum length of the substring - * @return a substring of <code>string</code> starting at <code>start</code> - * with a maximum length of <code>length</code> - * - * @see sstrsubs() - * @see sstrchr() - */ -sstr_t sstrsubsl(sstr_t string, size_t start, size_t length); - -/** - * Returns a substring of an immutable string starting at the specified - * location. - * - * <b>Attention:</b> the new string references the same memory area as the -* input string and is <b>NOT</b> required to be <code>NULL</code>-terminated. - * Use scstrdup() to get a copy. - * - * @param string input string - * @param start start location of the substring - * @return a substring of <code>string</code> starting at <code>start</code> - * - * @see scstrsubsl() - * @see scstrchr() - */ -scstr_t scstrsubs(scstr_t string, size_t start); - -/** - * Returns a substring of an immutable string with a maximum length starting - * at the specified location. - * - * <b>Attention:</b> the new string references the same memory area as the - * input string and is <b>NOT</b> required to be <code>NULL</code>-terminated. - * Use scstrdup() to get a copy. - * - * @param string input string - * @param start start location of the substring - * @param length the maximum length of the substring - * @return a substring of <code>string</code> starting at <code>start</code> - * with a maximum length of <code>length</code> - * - * @see scstrsubs() - * @see scstrchr() - */ -scstr_t scstrsubsl(scstr_t string, size_t start, size_t length); - -/** - * Returns a substring starting at the location of the first occurrence of the - * specified character. - * - * If the string does not contain the character, an empty string is returned. - * - * @param string the string where to locate the character - * @param chr the character to locate - * @return a substring starting at the first location of <code>chr</code> - * - * @see sstrsubs() - */ -sstr_t sstrchr(sstr_t string, int chr); - -/** - * Returns a substring starting at the location of the last occurrence of the - * specified character. - * - * If the string does not contain the character, an empty string is returned. - * - * @param string the string where to locate the character - * @param chr the character to locate - * @return a substring starting at the last location of <code>chr</code> - * - * @see sstrsubs() - */ -sstr_t sstrrchr(sstr_t string, int chr); - -/** - * Returns an immutable substring starting at the location of the first - * occurrence of the specified character. - * - * If the string does not contain the character, an empty string is returned. - * - * @param string the string where to locate the character - * @param chr the character to locate - * @return a substring starting at the first location of <code>chr</code> - * - * @see scstrsubs() - */ -scstr_t scstrchr(scstr_t string, int chr); - -/** - * Returns an immutable substring starting at the location of the last - * occurrence of the specified character. - * - * If the string does not contain the character, an empty string is returned. - * - * @param string the string where to locate the character - * @param chr the character to locate - * @return a substring starting at the last location of <code>chr</code> - * - * @see scstrsubs() - */ -scstr_t scstrrchr(scstr_t string, int chr); - -/** - * Returns a substring starting at the location of the first occurrence of the - * specified string. - * - * If the string does not contain the other string, an empty string is returned. - * - * If <code>match</code> is an empty string, the complete <code>string</code> is - * returned. - * - * @param string the string to be scanned - * @param match string containing the sequence of characters to match - * @return a substring starting at the first occurrence of - * <code>match</code>, or an empty string, if the sequence is not - * present in <code>string</code> - */ -sstr_t scstrsstr(sstr_t string, scstr_t match); - -/** - * Returns a substring starting at the location of the first occurrence of the - * specified string. - * - * If the string does not contain the other string, an empty string is returned. - * - * If <code>match</code> is an empty string, the complete <code>string</code> is - * returned. - * - * @param string the string to be scanned - * @param match string containing the sequence of characters to match - * @return a substring starting at the first occurrence of - * <code>match</code>, or an empty string, if the sequence is not - * present in <code>string</code> - */ -#define sstrstr(string, match) scstrsstr(string, SCSTR(match)) - -/** - * Returns an immutable substring starting at the location of the - * first occurrence of the specified immutable string. - * - * If the string does not contain the other string, an empty string is returned. - * - * If <code>match</code> is an empty string, the complete <code>string</code> is - * returned. - * - * @param string the string to be scanned - * @param match string containing the sequence of characters to match - * @return a substring starting at the first occurrence of - * <code>match</code>, or an empty string, if the sequence is not - * present in <code>string</code> - */ -scstr_t scstrscstr(scstr_t string, scstr_t match); - -/** - * Returns an immutable substring starting at the location of the - * first occurrence of the specified immutable string. - * - * If the string does not contain the other string, an empty string is returned. - * - * If <code>match</code> is an empty string, the complete <code>string</code> is - * returned. - * - * @param string the string to be scanned - * @param match string containing the sequence of characters to match - * @return a substring starting at the first occurrence of - * <code>match</code>, or an empty string, if the sequence is not - * present in <code>string</code> - */ -#define sstrscstr(string, match) scstrscstr(string, SCSTR(match)) - -/** - * Splits a string into parts by using a delimiter string. - * - * This function will return <code>NULL</code>, if one of the following happens: - * <ul> - * <li>the string length is zero</li> - * <li>the delimeter length is zero</li> - * <li>the string equals the delimeter</li> - * <li>memory allocation fails</li> - * </ul> - * - * The integer referenced by <code>count</code> is used as input and determines - * the maximum size of the resulting array, i.e. the maximum count of splits to - * perform + 1. - * - * The integer referenced by <code>count</code> is also used as output and is - * set to - * <ul> - * <li>-2, on memory allocation errors</li> - * <li>-1, if either the string or the delimiter is an empty string</li> - * <li>0, if the string equals the delimiter</li> - * <li>1, if the string does not contain the delimiter</li> - * <li>the count of array items, otherwise</li> - * </ul> - * - * If the string starts with the delimiter, the first item of the resulting - * array will be an empty string. - * - * If the string ends with the delimiter and the maximum list size is not - * exceeded, the last array item will be an empty string. - * In case the list size would be exceeded, the last array item will be the - * remaining string after the last split, <i>including</i> the terminating - * delimiter. - * - * <b>Attention:</b> The array pointer <b>AND</b> all sstr_t.ptr of the array - * items must be manually passed to <code>free()</code>. Use scstrsplit_a() with - * an allocator to managed memory, to avoid this. - * - * @param string the string to split - * @param delim the delimiter string - * @param count IN: the maximum size of the resulting array (0 = no limit), - * OUT: the actual size of the array - * @return a sstr_t array containing the split strings or - * <code>NULL</code> on error - * - * @see scstrsplit_a() - */ -sstr_t* scstrsplit(scstr_t string, scstr_t delim, ssize_t *count); - -/** - * Splits a string into parts by using a delimiter string. - * - * This function will return <code>NULL</code>, if one of the following happens: - * <ul> - * <li>the string length is zero</li> - * <li>the delimeter length is zero</li> - * <li>the string equals the delimeter</li> - * <li>memory allocation fails</li> - * </ul> - * - * The integer referenced by <code>count</code> is used as input and determines - * the maximum size of the resulting array, i.e. the maximum count of splits to - * perform + 1. - * - * The integer referenced by <code>count</code> is also used as output and is - * set to - * <ul> - * <li>-2, on memory allocation errors</li> - * <li>-1, if either the string or the delimiter is an empty string</li> - * <li>0, if the string equals the delimiter</li> - * <li>1, if the string does not contain the delimiter</li> - * <li>the count of array items, otherwise</li> - * </ul> - * - * If the string starts with the delimiter, the first item of the resulting - * array will be an empty string. - * - * If the string ends with the delimiter and the maximum list size is not - * exceeded, the last array item will be an empty string. - * In case the list size would be exceeded, the last array item will be the - * remaining string after the last split, <i>including</i> the terminating - * delimiter. - * - * <b>Attention:</b> The array pointer <b>AND</b> all sstr_t.ptr of the array - * items must be manually passed to <code>free()</code>. Use sstrsplit_a() with - * an allocator to managed memory, to avoid this. - * - * @param string the string to split - * @param delim the delimiter string - * @param count IN: the maximum size of the resulting array (0 = no limit), - * OUT: the actual size of the array - * @return a sstr_t array containing the split strings or - * <code>NULL</code> on error - * - * @see sstrsplit_a() - */ -#define sstrsplit(string, delim, count) \ - scstrsplit(SCSTR(string), SCSTR(delim), count) - -/** - * Performing scstrsplit() using a UcxAllocator. - * - * <i>Read the description of scstrsplit() for details.</i> - * - * The memory for the sstr_t.ptr pointers of the array items and the memory for - * the sstr_t array itself are allocated by using the UcxAllocator.malloc() - * function. - * - * @param allocator the UcxAllocator used for allocating memory - * @param string the string to split - * @param delim the delimiter string - * @param count IN: the maximum size of the resulting array (0 = no limit), - * OUT: the actual size of the array - * @return a sstr_t array containing the split strings or - * <code>NULL</code> on error - * - * @see scstrsplit() - */ -sstr_t* scstrsplit_a(UcxAllocator *allocator, scstr_t string, scstr_t delim, - ssize_t *count); - -/** - * Performing sstrsplit() using a UcxAllocator. - * - * <i>Read the description of sstrsplit() for details.</i> - * - * The memory for the sstr_t.ptr pointers of the array items and the memory for - * the sstr_t array itself are allocated by using the UcxAllocator.malloc() - * function. - * - * @param allocator the UcxAllocator used for allocating memory - * @param string the string to split - * @param delim the delimiter string - * @param count IN: the maximum size of the resulting array (0 = no limit), - * OUT: the actual size of the array - * @return a sstr_t array containing the split strings or - * <code>NULL</code> on error - * - * @see sstrsplit() - */ -#define sstrsplit_a(allocator, string, delim, count) \ - scstrsplit_a(allocator, SCSTR(string), SCSTR(delim), count) - -/** - * Compares two UCX strings with standard <code>memcmp()</code>. - * - * At first it compares the scstr_t.length attribute of the two strings. The - * <code>memcmp()</code> function is called, if and only if the lengths match. - * - * @param s1 the first string - * @param s2 the second string - * @return -1, if the length of s1 is less than the length of s2 or 1, if the - * length of s1 is greater than the length of s2 or the result of - * <code>memcmp()</code> otherwise (i.e. 0 if the strings match) - */ -int scstrcmp(scstr_t s1, scstr_t s2); - -/** - * Compares two UCX strings with standard <code>memcmp()</code>. - * - * At first it compares the sstr_t.length attribute of the two strings. The - * <code>memcmp()</code> function is called, if and only if the lengths match. - * - * @param s1 the first string - * @param s2 the second string - * @return -1, if the length of s1 is less than the length of s2 or 1, if the - * length of s1 is greater than the length of s2 or the result of - * <code>memcmp()</code> otherwise (i.e. 0 if the strings match) - */ -#define sstrcmp(s1, s2) scstrcmp(SCSTR(s1), SCSTR(s2)) - -/** - * Compares two UCX strings ignoring the case. - * - * At first it compares the scstr_t.length attribute of the two strings. If and - * only if the lengths match, both strings are compared char by char ignoring - * the case. - * - * @param s1 the first string - * @param s2 the second string - * @return -1, if the length of s1 is less than the length of s2 or 1, if the - * length of s1 is greater than the length of s2 or the result of the platform - * specific string comparison function ignoring the case. - */ -int scstrcasecmp(scstr_t s1, scstr_t s2); - -/** - * Compares two UCX strings ignoring the case. - * - * At first it compares the sstr_t.length attribute of the two strings. If and - * only if the lengths match, both strings are compared char by char ignoring - * the case. - * - * @param s1 the first string - * @param s2 the second string - * @return -1, if the length of s1 is less than the length of s2 or 1, if the - * length of s1 is greater than the length of s2 or the result of the platform - * specific string comparison function ignoring the case. - */ -#define sstrcasecmp(s1, s2) scstrcasecmp(SCSTR(s1), SCSTR(s2)) - -/** - * Creates a duplicate of the specified string. - * - * The new sstr_t will contain a copy allocated by standard - * <code>malloc()</code>. So developers <b>MUST</b> pass the sstr_t.ptr to - * <code>free()</code>. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated and mutable, regardless of the argument. - * - * @param string the string to duplicate - * @return a duplicate of the string - * @see scstrdup_a() - */ -sstr_t scstrdup(scstr_t string); - -/** - * Creates a duplicate of the specified string. - * - * The new sstr_t will contain a copy allocated by standard - * <code>malloc()</code>. So developers <b>MUST</b> pass the sstr_t.ptr to - * <code>free()</code>. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated, regardless of the argument. - * - * @param string the string to duplicate - * @return a duplicate of the string - * @see sstrdup_a() - */ -#define sstrdup(string) scstrdup(SCSTR(string)) - -/** - * Creates a duplicate of the specified string using a UcxAllocator. - * - * The new sstr_t will contain a copy allocated by the allocators - * UcxAllocator.malloc() function. So it is implementation depended, whether the - * returned sstr_t.ptr pointer must be passed to the allocators - * UcxAllocator.free() function manually. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated and mutable, regardless of the argument. - * - * @param allocator a valid instance of a UcxAllocator - * @param string the string to duplicate - * @return a duplicate of the string - * @see scstrdup() - */ -sstr_t scstrdup_a(UcxAllocator *allocator, scstr_t string); - -/** - * Creates a duplicate of the specified string using a UcxAllocator. - * - * The new sstr_t will contain a copy allocated by the allocators - * UcxAllocator.malloc() function. So it is implementation depended, whether the - * returned sstr_t.ptr pointer must be passed to the allocators - * UcxAllocator.free() function manually. - * - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>- - * terminated, regardless of the argument. - * - * @param allocator a valid instance of a UcxAllocator - * @param string the string to duplicate - * @return a duplicate of the string - * @see scstrdup() - */ -#define sstrdup_a(allocator, string) scstrdup_a(allocator, SCSTR(string)) - - -/** - * Omits leading and trailing spaces. - * - * This function returns a new sstr_t containing a trimmed version of the - * specified string. - * - * <b>Note:</b> the new sstr_t references the same memory, thus you - * <b>MUST NOT</b> pass the sstr_t.ptr of the return value to - * <code>free()</code>. It is also highly recommended to avoid assignments like - * <code>mystr = sstrtrim(mystr);</code> as you lose the reference to the - * source string. Assignments of this type are only permitted, if the - * sstr_t.ptr of the source string does not need to be freed or if another - * reference to the source string exists. - * - * @param string the string that shall be trimmed - * @return a new sstr_t containing the trimmed string - */ -sstr_t sstrtrim(sstr_t string); - -/** - * Omits leading and trailing spaces. - * - * This function returns a new scstr_t containing a trimmed version of the - * specified string. - * - * <b>Note:</b> the new scstr_t references the same memory, thus you - * <b>MUST NOT</b> pass the scstr_t.ptr of the return value to - * <code>free()</code>. It is also highly recommended to avoid assignments like - * <code>mystr = scstrtrim(mystr);</code> as you lose the reference to the - * source string. Assignments of this type are only permitted, if the - * scstr_t.ptr of the source string does not need to be freed or if another - * reference to the source string exists. - * - * @param string the string that shall be trimmed - * @return a new scstr_t containing the trimmed string - */ -scstr_t scstrtrim(scstr_t string); - -/** - * Checks, if a string has a specific prefix. - * - * @param string the string to check - * @param prefix the prefix the string should have - * @return 1, if and only if the string has the specified prefix, 0 otherwise - */ -int scstrprefix(scstr_t string, scstr_t prefix); - -/** - * Checks, if a string has a specific prefix. - * - * @param string the string to check - * @param prefix the prefix the string should have - * @return 1, if and only if the string has the specified prefix, 0 otherwise - */ -#define sstrprefix(string, prefix) scstrprefix(SCSTR(string), SCSTR(prefix)) - -/** - * Checks, if a string has a specific suffix. - * - * @param string the string to check - * @param suffix the suffix the string should have - * @return 1, if and only if the string has the specified suffix, 0 otherwise - */ -int scstrsuffix(scstr_t string, scstr_t suffix); - -/** - * Checks, if a string has a specific suffix. - * - * @param string the string to check - * @param suffix the suffix the string should have - * @return 1, if and only if the string has the specified suffix, 0 otherwise - */ -#define sstrsuffix(string, suffix) scstrsuffix(SCSTR(string), SCSTR(suffix)) - -/** - * Checks, if a string has a specific prefix, ignoring the case. - * - * @param string the string to check - * @param prefix the prefix the string should have - * @return 1, if and only if the string has the specified prefix, 0 otherwise - */ -int scstrcaseprefix(scstr_t string, scstr_t prefix); - -/** - * Checks, if a string has a specific prefix, ignoring the case. - * - * @param string the string to check - * @param prefix the prefix the string should have - * @return 1, if and only if the string has the specified prefix, 0 otherwise - */ -#define sstrcaseprefix(string, prefix) \ - scstrcaseprefix(SCSTR(string), SCSTR(prefix)) - -/** - * Checks, if a string has a specific suffix, ignoring the case. - * - * @param string the string to check - * @param suffix the suffix the string should have - * @return 1, if and only if the string has the specified suffix, 0 otherwise - */ -int scstrcasesuffix(scstr_t string, scstr_t suffix); - -/** - * Checks, if a string has a specific suffix, ignoring the case. - * - * @param string the string to check - * @param suffix the suffix the string should have - * @return 1, if and only if the string has the specified suffix, 0 otherwise - */ -#define sstrcasesuffix(string, suffix) \ - scstrcasesuffix(SCSTR(string), SCSTR(suffix)) - -/** - * Returns a lower case version of a string. - * - * This function creates a duplicate of the input string, first - * (see scstrdup()). - * - * @param string the input string - * @return the resulting lower case string - * @see scstrdup() - */ -sstr_t scstrlower(scstr_t string); - -/** - * Returns a lower case version of a string. - * - * This function creates a duplicate of the input string, first - * (see sstrdup()). - * - * @param string the input string - * @return the resulting lower case string - */ -#define sstrlower(string) scstrlower(SCSTR(string)) - -/** - * Returns a lower case version of a string. - * - * This function creates a duplicate of the input string, first - * (see scstrdup_a()). - * - * @param allocator the allocator used for duplicating the string - * @param string the input string - * @return the resulting lower case string - * @see scstrdup_a() - */ -sstr_t scstrlower_a(UcxAllocator *allocator, scstr_t string); - - -/** - * Returns a lower case version of a string. - * - * This function creates a duplicate of the input string, first - * (see sstrdup_a()). - * - * @param allocator the allocator used for duplicating the string - * @param string the input string - * @return the resulting lower case string - */ -#define sstrlower_a(allocator, string) scstrlower_a(allocator, SCSTR(string)) - -/** - * Returns a upper case version of a string. - * - * This function creates a duplicate of the input string, first - * (see scstrdup()). - * - * @param string the input string - * @return the resulting upper case string - * @see scstrdup() - */ -sstr_t scstrupper(scstr_t string); - -/** - * Returns a upper case version of a string. - * - * This function creates a duplicate of the input string, first - * (see sstrdup()). - * - * @param string the input string - * @return the resulting upper case string - */ -#define sstrupper(string) scstrupper(SCSTR(string)) - -/** - * Returns a upper case version of a string. - * - * This function creates a duplicate of the input string, first - * (see scstrdup_a()). - * - * @param allocator the allocator used for duplicating the string - * @param string the input string - * @return the resulting upper case string - * @see scstrdup_a() - */ -sstr_t scstrupper_a(UcxAllocator *allocator, scstr_t string); - -/** - * Returns a upper case version of a string. - * - * This function creates a duplicate of the input string, first - * (see sstrdup_a()). - * - * @param allocator the allocator used for duplicating the string - * @param string the input string - * @return the resulting upper case string - */ -#define sstrupper_a(allocator, string) scstrupper_a(allocator, string) - - -/** - * Replaces a pattern in a string with another string. - * - * The pattern is taken literally and is no regular expression. - * Replaces at most <code>replmax</code> occurrences. - * - * The resulting string is allocated by the specified allocator. I.e. it - * depends on the used allocator, whether the sstr_t.ptr must be freed - * manually. - * - * If allocation fails, the sstr_t.ptr of the return value is NULL. - * - * @param allocator the allocator to use - * @param str the string where replacements should be applied - * @param pattern the pattern to search for - * @param replacement the replacement string - * @param replmax maximum number of replacements - * @return the resulting string after applying the replacements - */ -sstr_t scstrreplacen_a(UcxAllocator *allocator, scstr_t str, - scstr_t pattern, scstr_t replacement, size_t replmax); - -/** - * Replaces a pattern in a string with another string. - * - * The pattern is taken literally and is no regular expression. - * Replaces at most <code>replmax</code> occurrences. - * - * The sstr_t.ptr of the resulting string must be freed manually. - * - * If allocation fails, the sstr_t.ptr of the return value is NULL. - * - * @param str the string where replacements should be applied - * @param pattern the pattern to search for - * @param replacement the replacement string - * @param replmax maximum number of replacements - * @return the resulting string after applying the replacements - */ -sstr_t scstrreplacen(scstr_t str, scstr_t pattern, - scstr_t replacement, size_t replmax); - -/** - * Replaces a pattern in a string with another string. - * - * The pattern is taken literally and is no regular expression. - * Replaces at most <code>replmax</code> occurrences. - * - * The resulting string is allocated by the specified allocator. I.e. it - * depends on the used allocator, whether the sstr_t.ptr must be freed - * manually. - * - * @param allocator the allocator to use - * @param str the string where replacements should be applied - * @param pattern the pattern to search for - * @param replacement the replacement string - * @param replmax maximum number of replacements - * @return the resulting string after applying the replacements - */ -#define sstrreplacen_a(allocator, str, pattern, replacement, replmax) \ - scstrreplacen_a(allocator, SCSTR(str), SCSTR(pattern), \ - SCSTR(replacement), replmax) - -/** - * Replaces a pattern in a string with another string. - * - * The pattern is taken literally and is no regular expression. - * Replaces at most <code>replmax</code> occurrences. - * - * The sstr_t.ptr of the resulting string must be freed manually. - * - * If allocation fails, the sstr_t.ptr of the return value is NULL. - * - * @param str the string where replacements should be applied - * @param pattern the pattern to search for - * @param replacement the replacement string - * @param replmax maximum number of replacements - * @return the resulting string after applying the replacements - */ -#define sstrreplacen(str, pattern, replacement, replmax) \ - scstrreplacen(SCSTR(str), SCSTR(pattern), SCSTR(replacement), replmax) - -/** - * Replaces a pattern in a string with another string. - * - * The pattern is taken literally and is no regular expression. - * Replaces at most <code>replmax</code> occurrences. - * - * The resulting string is allocated by the specified allocator. I.e. it - * depends on the used allocator, whether the sstr_t.ptr must be freed - * manually. - * - * If allocation fails, the sstr_t.ptr of the return value is NULL. - * - * @param allocator the allocator to use - * @param str the string where replacements should be applied - * @param pattern the pattern to search for - * @param replacement the replacement string - * @return the resulting string after applying the replacements - */ -#define sstrreplace_a(allocator, str, pattern, replacement) \ - scstrreplacen_a(allocator, SCSTR(str), SCSTR(pattern), \ - SCSTR(replacement), SIZE_MAX) - -/** - * Replaces a pattern in a string with another string. - * - * The pattern is taken literally and is no regular expression. - * Replaces at most <code>replmax</code> occurrences. - * - * The sstr_t.ptr of the resulting string must be freed manually. - * - * If allocation fails, the sstr_t.ptr of the return value is NULL. - * - * @param str the string where replacements should be applied - * @param pattern the pattern to search for - * @param replacement the replacement string - * @return the resulting string after applying the replacements - */ -#define sstrreplace(str, pattern, replacement) \ - scstrreplacen(SCSTR(str), SCSTR(pattern), SCSTR(replacement), SIZE_MAX) - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_STRING_H */
--- a/ucx/ucx/test.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +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. - */ - -/** - * @file: test.h - * - * UCX Test Framework. - * - * Usage of this test framework: - * - * **** IN HEADER FILE: **** - * - * <pre> - * UCX_TEST(function_name); - * UCX_TEST_SUBROUTINE(subroutine_name, paramlist); // optional - * </pre> - * - * **** IN SOURCE FILE: **** - * <pre> - * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) { - * // tests with UCX_TEST_ASSERT() - * } - * - * UCX_TEST(function_name) { - * // memory allocation and other stuff here - * #UCX_TEST_BEGIN - * // tests with UCX_TEST_ASSERT() and/or - * // calls with UCX_TEST_CALL_SUBROUTINE() here - * #UCX_TEST_END - * // cleanup of memory here - * } - * </pre> - * - * <b>Note:</b> if a test fails, a longjump is performed - * back to the #UCX_TEST_BEGIN macro! - * - * <b>Attention:</b> Do not call own functions within a test, that use - * UCX_TEST_ASSERT() macros and are not defined by using UCX_TEST_SUBROUTINE(). - * - * - * @author Mike Becker - * @author Olaf Wintermann - * - */ - -#ifndef UCX_TEST_H -#define UCX_TEST_H - -#include "ucx.h" -#include <stdio.h> -#include <string.h> -#include <setjmp.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __FUNCTION__ - -/** - * Alias for the <code>__func__</code> preprocessor macro. - * Some compilers use <code>__func__</code> and others use __FUNCTION__. - * We use __FUNCTION__ so we define it for those compilers which use - * <code>__func__</code>. - */ -#define __FUNCTION__ __func__ -#endif - -/** Type for the UcxTestSuite. */ -typedef struct UcxTestSuite UcxTestSuite; - -/** Pointer to a test function. */ -typedef void(*UcxTest)(UcxTestSuite*,FILE*); - -/** Type for the internal list of test cases. */ -typedef struct UcxTestList UcxTestList; - -/** Structure for the internal list of test cases. */ -struct UcxTestList { - - /** Test case. */ - UcxTest test; - - /** Pointer to the next list element. */ - UcxTestList *next; -}; - -/** - * A test suite containing multiple test cases. - */ -struct UcxTestSuite { - - /** The number of successful tests after the suite has been run. */ - unsigned int success; - - /** The number of failed tests after the suite has been run. */ - unsigned int failure; - - /** - * Internal list of test cases. - * Use ucx_test_register() to add tests to this list. - */ - UcxTestList *tests; -}; - -/** - * Creates a new test suite. - * @return a new test suite - */ -UcxTestSuite* ucx_test_suite_new(); - -/** - * Destroys a test suite. - * @param suite the test suite to destroy - */ -void ucx_test_suite_free(UcxTestSuite* suite); - -/** - * Registers a test function with the specified test suite. - * - * @param suite the suite, the test function shall be added to - * @param test the test function to register - * @return <code>EXIT_SUCCESS</code> on success or - * <code>EXIT_FAILURE</code> on failure - */ -int ucx_test_register(UcxTestSuite* suite, UcxTest test); - -/** - * Runs a test suite and writes the test log to the specified stream. - * @param suite the test suite to run - * @param outstream the stream the log shall be written to - */ -void ucx_test_run(UcxTestSuite* suite, FILE* outstream); - -/** - * Macro for a #UcxTest function header. - * - * Use this macro to declare and/or define a #UcxTest function. - * - * @param name the name of the test function - */ -#define UCX_TEST(name) void name(UcxTestSuite* _suite_,FILE *_output_) - -/** - * Marks the begin of a test. - * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>after</b> - * #UCX_TEST_BEGIN. - * - * @see #UCX_TEST_END - */ -#define UCX_TEST_BEGIN fwrite("Running ", 1, 8, _output_);\ - fwrite(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\ - fwrite("... ", 1, 4, _output_);\ - jmp_buf _env_; \ - if (!setjmp(_env_)) { - -/** - * Checks a test assertion. - * If the assertion is correct, the test carries on. If the assertion is not - * correct, the specified message (terminated by a dot and a line break) is - * written to the test suites output stream. - * @param condition the condition to check - * @param message the message that shall be printed out on failure - */ -#define UCX_TEST_ASSERT(condition,message) if (!(condition)) { \ - fwrite(message".\n", 1, 2+strlen(message), _output_); \ - _suite_->failure++; \ - longjmp(_env_, 1);\ - } - -/** - * Macro for a test subroutine function header. - * - * Use this to declare and/or define a subroutine that can be called by using - * UCX_TEST_CALL_SUBROUTINE(). - * - * @param name the name of the subroutine - * @param ... the parameter list - * - * @see UCX_TEST_CALL_SUBROUTINE() - */ -#define UCX_TEST_SUBROUTINE(name,...) void name(UcxTestSuite* _suite_,\ - FILE *_output_, jmp_buf _env_, __VA_ARGS__) - -/** - * Macro for calling a test subroutine. - * - * Subroutines declared with UCX_TEST_SUBROUTINE() can be called by using this - * macro. - * - * <b>Note:</b> You may <b>only</b> call subroutines within a #UCX_TEST_BEGIN- - * #UCX_TEST_END-block. - * - * @param name the name of the subroutine - * @param ... the argument list - * - * @see UCX_TEST_SUBROUTINE() - */ -#define UCX_TEST_CALL_SUBROUTINE(name,...) \ - name(_suite_,_output_,_env_,__VA_ARGS__); - -/** - * Marks the end of a test. - * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>before</b> - * #UCX_TEST_END. - * - * @see #UCX_TEST_BEGIN - */ -#define UCX_TEST_END fwrite("success.\n", 1, 9, _output_); _suite_->success++;} - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_TEST_H */ -
--- a/ucx/ucx/ucx.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +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. - */ -/** - * Main UCX Header providing most common definitions. - * - * @file ucx.h - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_H -#define UCX_H - -/** Major UCX version as integer constant. */ -#define UCX_VERSION_MAJOR 2 - -/** Minor UCX version as integer constant. */ -#define UCX_VERSION_MINOR 1 - -/** Version constant which ensures to increase monotonically. */ -#define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) - -#include <stdlib.h> -#include <stdint.h> - -#ifdef _WIN32 -#if !(defined __ssize_t_defined || defined _SSIZE_T_) -#include <BaseTsd.h> -typedef SSIZE_T ssize_t; -#define __ssize_t_defined -#define _SSIZE_T_ -#endif /* __ssize_t_defined and _SSIZE_T */ -#else /* !_WIN32 */ -#include <sys/types.h> -#endif /* _WIN32 */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * A function pointer to a destructor function. - * @see ucx_mempool_setdestr() - * @see ucx_mempool_regdestr() - */ -typedef void(*ucx_destructor)(void*); - -/** - * Function pointer to a compare function. - * - * The compare function shall take three arguments: the two values that shall be - * compared and optional additional data. - * The function shall then return -1 if the first argument is less than the - * second argument, 1 if the first argument is greater than the second argument - * and 0 if both arguments are equal. If the third argument is - * <code>NULL</code>, it shall be ignored. - */ -typedef int(*cmp_func)(const void*,const void*,void*); - -/** - * Function pointer to a distance function. - * - * The distance function shall take three arguments: the two values for which - * the distance shall be computed and optional additional data. - * The function shall then return the signed distance as integer value. - */ -typedef intmax_t(*distance_func)(const void*,const void*,void*); - -/** - * Function pointer to a copy function. - * - * The copy function shall create a copy of the first argument and may use - * additional data provided by the second argument. If the second argument is - * <code>NULL</code>, it shall be ignored. - - * <b>Attention:</b> if pointers returned by functions of this type may be - * passed to <code>free()</code> depends on the implementation of the - * respective <code>copy_func</code>. - */ -typedef void*(*copy_func)(const void*,void*); - -/** - * Function pointer to a write function. - * - * The signature of the write function shall be compatible to the signature - * of standard <code>fwrite</code>, though it may use arbitrary data types for - * source and destination. - * - * The arguments shall contain (in ascending order): a pointer to the source, - * the length of one element, the element count and a pointer to the - * destination. - */ -typedef size_t(*write_func)(const void*, size_t, size_t, void*); - -/** - * Function pointer to a read function. - * - * The signature of the read function shall be compatible to the signature - * of standard <code>fread</code>, though it may use arbitrary data types for - * source and destination. - * - * The arguments shall contain (in ascending order): a pointer to the - * destination, the length of one element, the element count and a pointer to - * the source. - */ -typedef size_t(*read_func)(void*, size_t, size_t, void*); - - - -#if __GNUC__ >= 5 || defined(__clang__) -#define UCX_MUL_BUILTIN - -#if __WORDSIZE == 32 -/** - * Alias for <code>__builtin_umul_overflow</code>. - * - * Performs a multiplication of size_t values and checks for overflow. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t, where the result should - * be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -#define ucx_szmul(a, b, result) __builtin_umul_overflow(a, b, result) -#else /* __WORDSIZE != 32 */ -/** - * Alias for <code>__builtin_umull_overflow</code>. - * - * Performs a multiplication of size_t values and checks for overflow. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t, where the result should - * be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -#define ucx_szmul(a, b, result) __builtin_umull_overflow(a, b, result) -#endif /* __WORDSIZE */ - -#else /* no GNUC or clang bultin */ - -/** - * Performs a multiplication of size_t values and checks for overflow. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t, where the result should - * be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -#define ucx_szmul(a, b, result) ucx_szmul_impl(a, b, result) - -/** - * Performs a multiplication of size_t values and checks for overflow. - * - * This is a custom implementation in case there is no compiler builtin - * available. - * - * @param a first operand - * @param b second operand - * @param result a pointer to a size_t where the result should be stored - * @return zero, if no overflow occurred and the result is correct, non-zero - * otherwise - */ -int ucx_szmul_impl(size_t a, size_t b, size_t *result); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_H */ -
--- a/ucx/ucx/utils.h Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,508 +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. - */ - -/** - * @file utils.h - * - * Compare, copy and printf functions. - * - * @author Mike Becker - * @author Olaf Wintermann - */ - -#ifndef UCX_UTILS_H -#define UCX_UTILS_H - -#include "ucx.h" -#include "string.h" -#include "allocator.h" -#include <inttypes.h> -#include <string.h> -#include <stdarg.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Default buffer size for ucx_stream_copy() and ucx_stream_ncopy(). - */ -#define UCX_STREAM_COPY_BUFSIZE 4096 - -/** - * Copies a string. - * @param s the string to copy - * @param data omitted - * @return a pointer to a copy of s1 that can be passed to free(void*) - */ -void *ucx_strcpy(const void *s, void *data); - -/** - * Copies a memory area. - * @param m a pointer to the memory area - * @param n a pointer to the size_t containing the size of the memory area - * @return a pointer to a copy of the specified memory area that can - * be passed to free(void*) - */ -void *ucx_memcpy(const void *m, void *n); - - -/** - * Reads data from a stream and writes it to another stream. - * - * @param src the source stream - * @param dest the destination stream - * @param rfnc the read function - * @param wfnc the write function - * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer - * shall be implicitly created on the heap - * @param bufsize the size of the copy buffer - if <code>NULL</code> was - * provided for <code>buf</code>, this is the size of the buffer that shall be - * implicitly created - * @param n the maximum number of bytes that shall be copied - * @return the total number of bytes copied - */ -size_t ucx_stream_bncopy(void *src, void *dest, read_func rfnc, write_func wfnc, - char* buf, size_t bufsize, size_t n); - -/** - * Shorthand for an unbounded ucx_stream_bncopy call using a default buffer. - * - * @param src the source stream - * @param dest the destination stream - * @param rfnc the read function - * @param wfnc the write function - * @return total number of bytes copied - * - * @see #UCX_STREAM_COPY_BUFSIZE - */ -#define ucx_stream_copy(src,dest,rfnc,wfnc) ucx_stream_bncopy(\ - src, dest, (read_func)rfnc, (write_func)wfnc, \ - NULL, UCX_STREAM_COPY_BUFSIZE, (size_t)-1) - -/** - * Shorthand for ucx_stream_bncopy using a default copy buffer. - * - * @param src the source stream - * @param dest the destination stream - * @param rfnc the read function - * @param wfnc the write function - * @param n maximum number of bytes that shall be copied - * @return total number of bytes copied - */ -#define ucx_stream_ncopy(src,dest,rfnc,wfnc, n) ucx_stream_bncopy(\ - src, dest, (read_func)rfnc, (write_func)wfnc, \ - NULL, UCX_STREAM_COPY_BUFSIZE, n) - -/** - * Shorthand for an unbounded ucx_stream_bncopy call using the specified buffer. - * - * @param src the source stream - * @param dest the destination stream - * @param rfnc the read function - * @param wfnc the write function - * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer - * shall be implicitly created on the heap - * @param bufsize the size of the copy buffer - if <code>NULL</code> was - * provided for <code>buf</code>, this is the size of the buffer that shall be - * implicitly created - * @return total number of bytes copied - */ -#define ucx_stream_bcopy(src,dest,rfnc,wfnc, buf, bufsize) ucx_stream_bncopy(\ - src, dest, (read_func)rfnc, (write_func)wfnc, \ - buf, bufsize, (size_t)-1) - -/** - * Wraps the strcmp function. - * @param s1 string one - * @param s2 string two - * @param data omitted - * @return the result of strcmp(s1, s2) - */ -int ucx_cmp_str(const void *s1, const void *s2, void *data); - -/** - * Wraps the strncmp function. - * @param s1 string one - * @param s2 string two - * @param n a pointer to the size_t containing the third strncmp parameter - * @return the result of strncmp(s1, s2, *n) - */ -int ucx_cmp_strn(const void *s1, const void *s2, void *n); - -/** - * Wraps the sstrcmp function. - * @param s1 sstr one - * @param s2 sstr two - * @param data ignored - * @return the result of sstrcmp(s1, s2) - */ -int ucx_cmp_sstr(const void *s1, const void *s2, void *data); - -/** - * Compares two integers of type int. - * @param i1 pointer to integer one - * @param i2 pointer to integer two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_int(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type long int. - * @param i1 pointer to long integer one - * @param i2 pointer to long integer two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_longint(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type long long. - * @param i1 pointer to long long one - * @param i2 pointer to long long two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_longlong(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type int16_t. - * @param i1 pointer to int16_t one - * @param i2 pointer to int16_t two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_int16(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type int32_t. - * @param i1 pointer to int32_t one - * @param i2 pointer to int32_t two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_int32(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type int64_t. - * @param i1 pointer to int64_t one - * @param i2 pointer to int64_t two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_int64(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type unsigned int. - * @param i1 pointer to unsigned integer one - * @param i2 pointer to unsigned integer two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_uint(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type unsigned long int. - * @param i1 pointer to unsigned long integer one - * @param i2 pointer to unsigned long integer two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_ulongint(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type unsigned long long. - * @param i1 pointer to unsigned long long one - * @param i2 pointer to unsigned long long two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_ulonglong(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type uint16_t. - * @param i1 pointer to uint16_t one - * @param i2 pointer to uint16_t two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_uint16(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type uint32_t. - * @param i1 pointer to uint32_t one - * @param i2 pointer to uint32_t two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_uint32(const void *i1, const void *i2, void *data); - -/** - * Compares two integers of type uint64_t. - * @param i1 pointer to uint64_t one - * @param i2 pointer to uint64_t two - * @param data omitted - * @return -1, if *i1 is less than *i2, 0 if both are equal, - * 1 if *i1 is greater than *i2 - */ -int ucx_cmp_uint64(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type int. - * @param i1 pointer to integer one - * @param i2 pointer to integer two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_int(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type long int. - * @param i1 pointer to long integer one - * @param i2 pointer to long integer two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_longint(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type long long. - * @param i1 pointer to long long one - * @param i2 pointer to long long two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_longlong(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type int16_t. - * @param i1 pointer to int16_t one - * @param i2 pointer to int16_t two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_int16(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type int32_t. - * @param i1 pointer to int32_t one - * @param i2 pointer to int32_t two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_int32(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type int64_t. - * @param i1 pointer to int64_t one - * @param i2 pointer to int64_t two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_int64(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type unsigned int. - * @param i1 pointer to unsigned integer one - * @param i2 pointer to unsigned integer two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_uint(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type unsigned long int. - * @param i1 pointer to unsigned long integer one - * @param i2 pointer to unsigned long integer two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_ulongint(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type unsigned long long. - * @param i1 pointer to unsigned long long one - * @param i2 pointer to unsigned long long two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_ulonglong(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type uint16_t. - * @param i1 pointer to uint16_t one - * @param i2 pointer to uint16_t two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_uint16(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type uint32_t. - * @param i1 pointer to uint32_t one - * @param i2 pointer to uint32_t two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_uint32(const void *i1, const void *i2, void *data); - -/** - * Distance function for integers of type uint64_t. - * @param i1 pointer to uint64_t one - * @param i2 pointer to uint64_t two - * @param data omitted - * @return i1 minus i2 - */ -intmax_t ucx_dist_uint64(const void *i1, const void *i2, void *data); - -/** - * Compares two real numbers of type float. - * @param f1 pointer to float one - * @param f2 pointer to float two - * @param data if provided: a pointer to precision (default: 1e-6f) - * @return -1, if *f1 is less than *f2, 0 if both are equal, - * 1 if *f1 is greater than *f2 - */ - -int ucx_cmp_float(const void *f1, const void *f2, void *data); - -/** - * Compares two real numbers of type double. - * @param d1 pointer to double one - * @param d2 pointer to double two - * @param data if provided: a pointer to precision (default: 1e-14) - * @return -1, if *d1 is less than *d2, 0 if both are equal, - * 1 if *d1 is greater than *d2 - */ -int ucx_cmp_double(const void *d1, const void *d2, void *data); - -/** - * Compares two pointers. - * @param ptr1 pointer one - * @param ptr2 pointer two - * @param data omitted - * @return -1 if ptr1 is less than ptr2, 0 if both are equal, - * 1 if ptr1 is greater than ptr2 - */ -int ucx_cmp_ptr(const void *ptr1, const void *ptr2, void *data); - -/** - * Compares two memory areas. - * @param ptr1 pointer one - * @param ptr2 pointer two - * @param n a pointer to the size_t containing the third parameter for memcmp - * @return the result of memcmp(ptr1, ptr2, *n) - */ -int ucx_cmp_mem(const void *ptr1, const void *ptr2, void *n); - -/** - * A <code>printf()</code> like function which writes the output to a stream by - * using a write_func(). - * @param stream the stream the data is written to - * @param wfc the write function - * @param fmt format string - * @param ... additional arguments - * @return the total number of bytes written - */ -int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...); - -/** - * <code>va_list</code> version of ucx_fprintf(). - * @param stream the stream the data is written to - * @param wfc the write function - * @param fmt format string - * @param ap argument list - * @return the total number of bytes written - * @see ucx_fprintf() - */ -int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap); - -/** - * A <code>printf()</code> like function which allocates space for a sstr_t - * the result is written to. - * - * <b>Attention</b>: The sstr_t data is allocated with the allocators - * ucx_allocator_malloc() function. So it is implementation dependent, if - * the returned sstr_t.ptr pointer must be passed to the allocators - * ucx_allocator_free() function manually. - * - * <b>Note</b>: The sstr_t.ptr of the return value will <i>always</i> be - * <code>NULL</code>-terminated. - * - * @param allocator the UcxAllocator used for allocating the result sstr_t - * @param fmt format string - * @param ... additional arguments - * @return a sstr_t containing the formatted string - */ -sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...); - -/** - * <code>va_list</code> version of ucx_asprintf(). - * - * @param allocator the UcxAllocator used for allocating the result sstr_t - * @param fmt format string - * @param ap argument list - * @return a sstr_t containing the formatted string - * @see ucx_asprintf() - */ -sstr_t ucx_vasprintf(UcxAllocator *allocator, const char *fmt, va_list ap); - -/** Shortcut for ucx_asprintf() with default allocator. */ -#define ucx_sprintf(...) \ - ucx_asprintf(ucx_default_allocator(), __VA_ARGS__) - -/** - * A <code>printf()</code> like function which writes the output to a - * UcxBuffer. - * - * @param buffer the buffer the data is written to - * @param ... format string and additional arguments - * @return the total number of bytes written - * @see ucx_fprintf() - */ -#define ucx_bprintf(buffer, ...) ucx_fprintf((UcxBuffer*)buffer, \ - (write_func)ucx_buffer_write, __VA_ARGS__) - -#ifdef __cplusplus -} -#endif - -#endif /* UCX_UTILS_H */ -
--- a/ucx/utils.c Sat Apr 15 15:42:31 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,448 +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/utils.h" - -#include <math.h> -#include <stdio.h> -#include <limits.h> -#include <errno.h> - -/* COPY FUCNTIONS */ -void* ucx_strcpy(const void* s, void* data) { - const char *str = (const char*) s; - size_t n = 1+strlen(str); - char *cpy = (char*) malloc(n); - memcpy(cpy, str, n); - return cpy; -} - -void* ucx_memcpy(const void* m, void* n) { - size_t k = *((size_t*)n); - void *cpy = malloc(k); - memcpy(cpy, m, k); - return cpy; -} - -size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc, - write_func writefnc, char* buf, size_t bufsize, size_t n) { - if(n == 0 || bufsize == 0) { - return 0; - } - - char *lbuf; - size_t ncp = 0; - - if(buf) { - lbuf = buf; - } else { - lbuf = (char*)malloc(bufsize); - if(lbuf == NULL) { - return 0; - } - } - - size_t r; - size_t rn = bufsize > n ? n : bufsize; - while((r = readfnc(lbuf, 1, rn, src)) != 0) { - r = writefnc(lbuf, 1, r, dest); - ncp += r; - n -= r; - rn = bufsize > n ? n : bufsize; - if(r == 0 || n == 0) { - break; - } - } - - if (lbuf != buf) { - free(lbuf); - } - - return ncp; -} - -/* COMPARE FUNCTIONS */ - -int ucx_cmp_str(const void *s1, const void *s2, void *data) { - return strcmp((const char*)s1, (const char*)s2); -} - -int ucx_cmp_strn(const void *s1, const void *s2, void *n) { - return strncmp((const char*)s1, (const char*)s2, *((size_t*) n)); -} - -int ucx_cmp_sstr(const void *s1, const void *s2, void *data) { - sstr_t a = *(const sstr_t*) s1; - sstr_t b = *(const sstr_t*) s2; - return sstrcmp(a, b); -} - -int ucx_cmp_int(const void *i1, const void *i2, void *data) { - int a = *((const int*) i1); - int b = *((const int*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_longint(const void *i1, const void *i2, void *data) { - long int a = *((const long int*) i1); - long int b = *((const long int*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_longlong(const void *i1, const void *i2, void *data) { - long long a = *((const long long*) i1); - long long b = *((const long long*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_int16(const void *i1, const void *i2, void *data) { - int16_t a = *((const int16_t*) i1); - int16_t b = *((const int16_t*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_int32(const void *i1, const void *i2, void *data) { - int32_t a = *((const int32_t*) i1); - int32_t b = *((const int32_t*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_int64(const void *i1, const void *i2, void *data) { - int64_t a = *((const int64_t*) i1); - int64_t b = *((const int64_t*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_uint(const void *i1, const void *i2, void *data) { - unsigned int a = *((const unsigned int*) i1); - unsigned int b = *((const unsigned int*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_ulongint(const void *i1, const void *i2, void *data) { - unsigned long int a = *((const unsigned long int*) i1); - unsigned long int b = *((const unsigned long int*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_ulonglong(const void *i1, const void *i2, void *data) { - unsigned long long a = *((const unsigned long long*) i1); - unsigned long long b = *((const unsigned long long*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_uint16(const void *i1, const void *i2, void *data) { - uint16_t a = *((const uint16_t*) i1); - uint16_t b = *((const uint16_t*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_uint32(const void *i1, const void *i2, void *data) { - uint32_t a = *((const uint32_t*) i1); - uint32_t b = *((const uint32_t*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_uint64(const void *i1, const void *i2, void *data) { - uint64_t a = *((const uint64_t*) i1); - uint64_t b = *((const uint64_t*) i2); - if (a == b) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -intmax_t ucx_dist_int(const void *i1, const void *i2, void *data) { - intmax_t a = *((const int*) i1); - intmax_t b = *((const int*) i2); - return a - b; -} - -intmax_t ucx_dist_longint(const void *i1, const void *i2, void *data) { - intmax_t a = *((const long int*) i1); - intmax_t b = *((const long int*) i2); - return a - b; -} - -intmax_t ucx_dist_longlong(const void *i1, const void *i2, void *data) { - intmax_t a = *((const long long*) i1); - intmax_t b = *((const long long*) i2); - return a - b; -} - -intmax_t ucx_dist_int16(const void *i1, const void *i2, void *data) { - intmax_t a = *((const int16_t*) i1); - intmax_t b = *((const int16_t*) i2); - return a - b; -} - -intmax_t ucx_dist_int32(const void *i1, const void *i2, void *data) { - intmax_t a = *((const int32_t*) i1); - intmax_t b = *((const int32_t*) i2); - return a - b; -} - -intmax_t ucx_dist_int64(const void *i1, const void *i2, void *data) { - intmax_t a = *((const int64_t*) i1); - intmax_t b = *((const int64_t*) i2); - return a - b; -} - -intmax_t ucx_dist_uint(const void *i1, const void *i2, void *data) { - uintmax_t a = *((const unsigned int*) i1); - uintmax_t b = *((const unsigned int*) i2); - return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); -} - -intmax_t ucx_dist_ulongint(const void *i1, const void *i2, void *data) { - uintmax_t a = *((const unsigned long int*) i1); - uintmax_t b = *((const unsigned long int*) i2); - return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); -} - -intmax_t ucx_dist_ulonglong(const void *i1, const void *i2, void *data) { - uintmax_t a = *((const unsigned long long*) i1); - uintmax_t b = *((const unsigned long long*) i2); - return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); -} - -intmax_t ucx_dist_uint16(const void *i1, const void *i2, void *data) { - uintmax_t a = *((const uint16_t*) i1); - uintmax_t b = *((const uint16_t*) i2); - return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); -} - -intmax_t ucx_dist_uint32(const void *i1, const void *i2, void *data) { - uintmax_t a = *((const uint32_t*) i1); - uintmax_t b = *((const uint32_t*) i2); - return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); -} - -intmax_t ucx_dist_uint64(const void *i1, const void *i2, void *data) { - uintmax_t a = *((const uint64_t*) i1); - uintmax_t b = *((const uint64_t*) i2); - return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); -} - -int ucx_cmp_float(const void *f1, const void *f2, void *epsilon) { - float a = *((const float*) f1); - float b = *((const float*) f2); - float e = !epsilon ? 1e-6f : *((float*)epsilon); - if (fabsf(a - b) < e) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_double(const void *d1, const void *d2, void *epsilon) { - double a = *((const double*) d1); - double b = *((const double*) d2); - double e = !epsilon ? 1e-14 : *((double*)epsilon); - if (fabs(a - b) < e) { - return 0; - } else { - return a < b ? -1 : 1; - } -} - -int ucx_cmp_ptr(const void *ptr1, const void *ptr2, void *data) { - const intptr_t p1 = (const intptr_t) ptr1; - const intptr_t p2 = (const intptr_t) ptr2; - if (p1 == p2) { - return 0; - } else { - return p1 < p2 ? -1 : 1; - } -} - -int ucx_cmp_mem(const void *ptr1, const void *ptr2, void *n) { - return memcmp(ptr1, ptr2, *((size_t*)n)); -} - -/* PRINTF FUNCTIONS */ - -#ifdef va_copy -#define UCX_PRINTF_BUFSIZE 256 -#else -#pragma message("WARNING: C99 va_copy macro not supported by this platform" \ - " - limiting ucx_*printf to 2 KiB") -#define UCX_PRINTF_BUFSIZE 0x800 -#endif - -int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) { - int ret; - va_list ap; - va_start(ap, fmt); - ret = ucx_vfprintf(stream, wfc, fmt, ap); - va_end(ap); - return ret; -} - -int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) { - char buf[UCX_PRINTF_BUFSIZE]; -#ifdef va_copy - va_list ap2; - va_copy(ap2, ap); - int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); - if (ret < 0) { - return ret; - } else if (ret < UCX_PRINTF_BUFSIZE) { - return (int)wfc(buf, 1, ret, stream); - } else { - if (ret == INT_MAX) { - errno = ENOMEM; - return -1; - } - - int len = ret + 1; - char *newbuf = (char*)malloc(len); - if (!newbuf) { - return -1; - } - - ret = vsnprintf(newbuf, len, fmt, ap2); - if (ret > 0) { - ret = (int)wfc(newbuf, 1, ret, stream); - } - free(newbuf); - } - return ret; -#else - int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); - if (ret < 0) { - return ret; - } else if (ret < UCX_PRINTF_BUFSIZE) { - return (int)wfc(buf, 1, ret, stream); - } else { - errno = ENOMEM; - return -1; - } -#endif -} - -sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) { - va_list ap; - sstr_t ret; - va_start(ap, fmt); - ret = ucx_vasprintf(allocator, fmt, ap); - va_end(ap); - return ret; -} - -sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) { - sstr_t s; - s.ptr = NULL; - s.length = 0; - char buf[UCX_PRINTF_BUFSIZE]; -#ifdef va_copy - va_list ap2; - va_copy(ap2, ap); - int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); - if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { - s.ptr = (char*)almalloc(a, ret + 1); - if (s.ptr) { - s.length = (size_t)ret; - memcpy(s.ptr, buf, ret); - s.ptr[s.length] = '\0'; - } - } else if (ret == INT_MAX) { - errno = ENOMEM; - } else { - int len = ret + 1; - s.ptr = (char*)almalloc(a, len); - if (s.ptr) { - ret = vsnprintf(s.ptr, len, fmt, ap2); - if (ret < 0) { - free(s.ptr); - s.ptr = NULL; - } else { - s.length = (size_t)ret; - } - } - } -#else - int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); - if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { - s.ptr = (char*)almalloc(a, ret + 1); - if (s.ptr) { - s.length = (size_t)ret; - memcpy(s.ptr, buf, ret); - s.ptr[s.length] = '\0'; - } - } else { - errno = ENOMEM; - } -#endif - return s; -}