changes source directory structure in preperation for autotools rollout

Tue, 17 Oct 2017 16:15:41 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 17 Oct 2017 16:15:41 +0200
changeset 251
fae240d633fc
parent 250
b7d1317b138e
child 252
6342cbbd1922

changes source directory structure in preperation for autotools rollout

Makefile file | annotate | diff | comparison | revisions
src/Makefile file | annotate | diff | comparison | revisions
src/allocator.c file | annotate | diff | comparison | revisions
src/avl.c file | annotate | diff | comparison | revisions
src/buffer.c file | annotate | diff | comparison | revisions
src/list.c file | annotate | diff | comparison | revisions
src/logging.c file | annotate | diff | comparison | revisions
src/map.c file | annotate | diff | comparison | revisions
src/mempool.c file | annotate | diff | comparison | revisions
src/properties.c file | annotate | diff | comparison | revisions
src/stack.c file | annotate | diff | comparison | revisions
src/string.c file | annotate | diff | comparison | revisions
src/test.c file | annotate | diff | comparison | revisions
src/ucx.c file | annotate | diff | comparison | revisions
src/ucx/allocator.h file | annotate | diff | comparison | revisions
src/ucx/avl.h file | annotate | diff | comparison | revisions
src/ucx/buffer.h file | annotate | diff | comparison | revisions
src/ucx/list.h file | annotate | diff | comparison | revisions
src/ucx/logging.h file | annotate | diff | comparison | revisions
src/ucx/map.h file | annotate | diff | comparison | revisions
src/ucx/mempool.h file | annotate | diff | comparison | revisions
src/ucx/properties.h file | annotate | diff | comparison | revisions
src/ucx/stack.h file | annotate | diff | comparison | revisions
src/ucx/string.h file | annotate | diff | comparison | revisions
src/ucx/test.h file | annotate | diff | comparison | revisions
src/ucx/ucx.h file | annotate | diff | comparison | revisions
src/ucx/utils.h file | annotate | diff | comparison | revisions
src/utils.c file | annotate | diff | comparison | revisions
test/Makefile file | annotate | diff | comparison | revisions
test/allocator_tests.h file | annotate | diff | comparison | revisions
test/avl_tests.c file | annotate | diff | comparison | revisions
test/avl_tests.h file | annotate | diff | comparison | revisions
test/buffer_tests.h file | annotate | diff | comparison | revisions
test/list_tests.c file | annotate | diff | comparison | revisions
test/list_tests.h file | annotate | diff | comparison | revisions
test/logging_tests.h file | annotate | diff | comparison | revisions
test/main.c file | annotate | diff | comparison | revisions
test/map_tests.h file | annotate | diff | comparison | revisions
test/mpool_tests.h file | annotate | diff | comparison | revisions
test/prop_tests.c file | annotate | diff | comparison | revisions
test/prop_tests.h file | annotate | diff | comparison | revisions
test/stack_tests.h file | annotate | diff | comparison | revisions
test/string_tests.h file | annotate | diff | comparison | revisions
test/utils_tests.c file | annotate | diff | comparison | revisions
test/utils_tests.h file | annotate | diff | comparison | revisions
ucx/Makefile file | annotate | diff | comparison | revisions
ucx/allocator.c file | annotate | diff | comparison | revisions
ucx/allocator.h file | annotate | diff | comparison | revisions
ucx/avl.c file | annotate | diff | comparison | revisions
ucx/avl.h file | annotate | diff | comparison | revisions
ucx/buffer.c file | annotate | diff | comparison | revisions
ucx/buffer.h file | annotate | diff | comparison | revisions
ucx/list.c file | annotate | diff | comparison | revisions
ucx/list.h file | annotate | diff | comparison | revisions
ucx/logging.c file | annotate | diff | comparison | revisions
ucx/logging.h file | annotate | diff | comparison | revisions
ucx/map.c file | annotate | diff | comparison | revisions
ucx/map.h file | annotate | diff | comparison | revisions
ucx/mempool.c file | annotate | diff | comparison | revisions
ucx/mempool.h file | annotate | diff | comparison | revisions
ucx/properties.c file | annotate | diff | comparison | revisions
ucx/properties.h file | annotate | diff | comparison | revisions
ucx/stack.c file | annotate | diff | comparison | revisions
ucx/stack.h file | annotate | diff | comparison | revisions
ucx/string.c file | annotate | diff | comparison | revisions
ucx/string.h file | annotate | diff | comparison | revisions
ucx/test.c file | annotate | diff | comparison | revisions
ucx/test.h file | annotate | diff | comparison | revisions
ucx/ucx.c file | annotate | diff | comparison | revisions
ucx/ucx.h file | annotate | diff | comparison | revisions
ucx/utils.c file | annotate | diff | comparison | revisions
ucx/utils.h file | annotate | diff | comparison | revisions
     1.1 --- a/Makefile	Tue Oct 17 15:15:54 2017 +0200
     1.2 +++ b/Makefile	Tue Oct 17 16:15:41 2017 +0200
     1.3 @@ -45,10 +45,10 @@
     1.4  all: ucx test
     1.5  
     1.6  ucx: FORCE
     1.7 -	cd ucx; $(MAKE) CONF=$(CONF)
     1.8 +	cd src; $(MAKE) CONF=$(CONF)
     1.9  
    1.10  ucx-debug: FORCE
    1.11 -	cd ucx; $(MAKE) CONF=$(CONF) debug
    1.12 +	cd src; $(MAKE) CONF=$(CONF) debug
    1.13  	
    1.14  test: ucx FORCE
    1.15  	cd test; $(MAKE) CONF=$(CONF)
    1.16 @@ -67,7 +67,7 @@
    1.17  install: ucx $(DESTDIR)$(PREFIX)/lib $(DESTDIR)$(PREFIX)/include/ucx
    1.18  	cp ./build/release/libucx$(LIB_EXT) $(DESTDIR)$(PREFIX)/lib && \
    1.19  	cp ./build/release/libucx$(SO_EXT) $(DESTDIR)$(PREFIX)/lib && \
    1.20 -        cp ./ucx/*.h $(DESTDIR)$(PREFIX)/include/ucx
    1.21 +        cp ./src/ucx/*.h $(DESTDIR)$(PREFIX)/include/ucx
    1.22  
    1.23  uninstall:
    1.24  	$(RM) $(RMFLAGS) $(DESTDIR)$(PREFIX)/include/ucx &&\
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/Makefile	Tue Oct 17 16:15:41 2017 +0200
     2.3 @@ -0,0 +1,79 @@
     2.4 +#
     2.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     2.6 +#
     2.7 +# Copyright 2017 Olaf Wintermann. All rights reserved.
     2.8 +#
     2.9 +# Redistribution and use in source and binary forms, with or without
    2.10 +# modification, are permitted provided that the following conditions are met:
    2.11 +#
    2.12 +#   1. Redistributions of source code must retain the above copyright
    2.13 +#      notice, this list of conditions and the following disclaimer.
    2.14 +#
    2.15 +#   2. Redistributions in binary form must reproduce the above copyright
    2.16 +#      notice, this list of conditions and the following disclaimer in the
    2.17 +#      documentation and/or other materials provided with the distribution.
    2.18 +#
    2.19 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    2.20 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    2.21 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    2.22 +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    2.23 +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    2.24 +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    2.25 +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    2.26 +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    2.27 +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    2.28 +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    2.29 +# POSSIBILITY OF SUCH DAMAGE.
    2.30 +#
    2.31 +
    2.32 +include ../$(CONF).mk
    2.33 +include ../cppcheck.mk
    2.34 +
    2.35 +# list of source files
    2.36 +SRC  = utils.c
    2.37 +SRC += list.c
    2.38 +SRC += map.c
    2.39 +SRC += avl.c
    2.40 +SRC += properties.c
    2.41 +SRC += mempool.c
    2.42 +SRC += string.c
    2.43 +SRC += test.c
    2.44 +SRC += allocator.c
    2.45 +SRC += logging.c
    2.46 +SRC += buffer.c
    2.47 +SRC += stack.c
    2.48 +
    2.49 +OBJ   = $(SRC:%.c=../build/release/ucx/%$(OBJ_EXT))
    2.50 +OBJ_D = $(SRC:%.c=../build/debug/ucx/%$(OBJ_EXT))
    2.51 +
    2.52 +all: ../build/release/ucx \
    2.53 +	../build/release/libucx$(LIB_EXT) ../build/release/libucx$(SO_EXT)
    2.54 +debug: ../build/debug/ucx \
    2.55 +	../build/debug/libucx$(LIB_EXT) ../build/debug/libucx$(SO_EXT)
    2.56 +
    2.57 +../build/release/libucx$(LIB_EXT): $(OBJ)
    2.58 +	$(AR) $(ARFLAGS) ../build/release/libucx$(LIB_EXT) $(OBJ)
    2.59 +
    2.60 +../build/release/libucx$(SO_EXT): $(OBJ)
    2.61 +	$(LD) $(SOLDFLAGS) -o ../build/release/libucx$(SO_EXT) $(OBJ)
    2.62 +
    2.63 +../build/release/ucx/%$(OBJ_EXT): %.c
    2.64 +	$(CC) $(CFLAGS) -I. -o $@ -c $<
    2.65 +
    2.66 +../build/release/ucx:
    2.67 +	$(MKDIR) $(MKDIRFLAGS) ../build/release/ucx
    2.68 +
    2.69 +../build/debug/libucx$(LIB_EXT): $(OBJ_D)
    2.70 +	$(AR) $(ARFLAGS) ../build/debug/libucx$(LIB_EXT) $(OBJ_D)
    2.71 +	
    2.72 +../build/debug/libucx$(SO_EXT): $(OBJ_D)
    2.73 +	$(LD) $(SOLDFLAGS) -o ../build/debug/libucx$(SO_EXT) $(OBJ_D)
    2.74 +
    2.75 +../build/debug/ucx/%$(OBJ_EXT): %.c
    2.76 +	$(CC) $(CFLAGS_D) -I. -o $@ -c $<
    2.77 +
    2.78 +../build/debug/ucx:
    2.79 +	$(MKDIR) $(MKDIRFLAGS) ../build/debug/ucx
    2.80 +
    2.81 +cppcheck: $(SRC)
    2.82 +	$(CPPCHECK) $(CPPCHECK_CONFIG) $(CPPCHECK_FLAGS) $+ 2>> ../$(CPPCHECK_LOG)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/allocator.c	Tue Oct 17 16:15:41 2017 +0200
     3.3 @@ -0,0 +1,60 @@
     3.4 +/*
     3.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3.6 + *
     3.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     3.8 + *
     3.9 + * Redistribution and use in source and binary forms, with or without
    3.10 + * modification, are permitted provided that the following conditions are met:
    3.11 + *
    3.12 + *   1. Redistributions of source code must retain the above copyright
    3.13 + *      notice, this list of conditions and the following disclaimer.
    3.14 + *
    3.15 + *   2. Redistributions in binary form must reproduce the above copyright
    3.16 + *      notice, this list of conditions and the following disclaimer in the
    3.17 + *      documentation and/or other materials provided with the distribution.
    3.18 + *
    3.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    3.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    3.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    3.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    3.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    3.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    3.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    3.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    3.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    3.29 + * POSSIBILITY OF SUCH DAMAGE.
    3.30 + */
    3.31 +
    3.32 +#include "ucx/allocator.h"
    3.33 +
    3.34 +#include <stdlib.h>
    3.35 +
    3.36 +UcxAllocator default_allocator = {
    3.37 +    NULL,
    3.38 +    ucx_default_malloc,
    3.39 +    ucx_default_calloc,
    3.40 +    ucx_default_realloc,
    3.41 +    ucx_default_free
    3.42 +};
    3.43 +
    3.44 +UcxAllocator *ucx_default_allocator() {
    3.45 +    UcxAllocator *allocator = &default_allocator;
    3.46 +    return allocator;
    3.47 +}
    3.48 +
    3.49 +void *ucx_default_malloc(void *ignore, size_t n) {
    3.50 +    return malloc(n);
    3.51 +}
    3.52 +
    3.53 +void *ucx_default_calloc(void *ignore, size_t n, size_t size) {
    3.54 +    return calloc(n, size);
    3.55 +}
    3.56 +
    3.57 +void *ucx_default_realloc(void *ignore, void *data, size_t n) {
    3.58 +    return realloc(data, n);
    3.59 +}
    3.60 +
    3.61 +void ucx_default_free(void *ignore, void *data) {
    3.62 +    free(data);
    3.63 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/avl.c	Tue Oct 17 16:15:41 2017 +0200
     4.3 @@ -0,0 +1,356 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     4.8 + *
     4.9 + * Redistribution and use in source and binary forms, with or without
    4.10 + * modification, are permitted provided that the following conditions are met:
    4.11 + *
    4.12 + *   1. Redistributions of source code must retain the above copyright
    4.13 + *      notice, this list of conditions and the following disclaimer.
    4.14 + *
    4.15 + *   2. Redistributions in binary form must reproduce the above copyright
    4.16 + *      notice, this list of conditions and the following disclaimer in the
    4.17 + *      documentation and/or other materials provided with the distribution.
    4.18 + *
    4.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    4.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    4.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    4.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    4.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    4.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    4.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    4.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    4.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    4.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    4.29 + * POSSIBILITY OF SUCH DAMAGE.
    4.30 + */
    4.31 +
    4.32 +#include "ucx/avl.h"
    4.33 +
    4.34 +#include <limits.h>
    4.35 +
    4.36 +#define ptrcast(ptr) ((void*)(ptr))
    4.37 +#define alloc_tree(al) (UcxAVLTree*) almalloc((al), sizeof(UcxAVLTree))
    4.38 +#define alloc_node(al) (UcxAVLNode*) almalloc((al), sizeof(UcxAVLNode))
    4.39 +
    4.40 +static void ucx_avl_connect(UcxAVLTree *tree,
    4.41 +        UcxAVLNode *node, UcxAVLNode *child, intptr_t nullkey) {
    4.42 +    if (child) {
    4.43 +        child->parent = node;
    4.44 +    }
    4.45 +    // if child is NULL, nullkey decides if left or right pointer is cleared
    4.46 +    if (tree->cmpfunc(
    4.47 +        ptrcast(child ? child->key : nullkey),
    4.48 +        ptrcast(node->key), tree->userdata) > 0) {
    4.49 +      node->right = child;
    4.50 +    } else {
    4.51 +      node->left = child;
    4.52 +    }
    4.53 +    size_t lh = node->left ? node->left->height : 0;
    4.54 +    size_t rh = node->right ? node->right->height : 0;
    4.55 +    node->height = 1 + (lh > rh ? lh : rh);
    4.56 +}
    4.57 +
    4.58 +#define avlheight(node) ((node) ? (node)->height : 0)
    4.59 +
    4.60 +static UcxAVLNode* avl_rotright(UcxAVLTree *tree, UcxAVLNode *l0) {
    4.61 +    UcxAVLNode *p = l0->parent;
    4.62 +    UcxAVLNode *l1 = l0->left;
    4.63 +    if (p) {
    4.64 +        ucx_avl_connect(tree, p, l1, 0);
    4.65 +    } else {
    4.66 +        l1->parent = NULL;
    4.67 +    }
    4.68 +    ucx_avl_connect(tree, l0, l1->right, l1->key);
    4.69 +    ucx_avl_connect(tree, l1, l0, 0);
    4.70 +    return l1;
    4.71 +}
    4.72 +
    4.73 +static UcxAVLNode* avl_rotleft(UcxAVLTree *tree, UcxAVLNode *l0) {
    4.74 +    UcxAVLNode *p = l0->parent;
    4.75 +    UcxAVLNode *l1 = l0->right;
    4.76 +    if (p) {
    4.77 +        ucx_avl_connect(tree, p, l1, 0);
    4.78 +    } else {
    4.79 +        l1->parent = NULL;
    4.80 +    }
    4.81 +    ucx_avl_connect(tree, l0, l1->left, l1->key);
    4.82 +    ucx_avl_connect(tree, l1, l0, 0);
    4.83 +    return l1;
    4.84 +}
    4.85 +
    4.86 +static void ucx_avl_balance(UcxAVLTree *tree, UcxAVLNode *n) {
    4.87 +    int lh = avlheight(n->left);
    4.88 +    int rh = avlheight(n->right);
    4.89 +    n->height = 1 + (lh > rh ? lh : rh);
    4.90 +    
    4.91 +    if (lh - rh == 2) {
    4.92 +      UcxAVLNode *c = n->left;
    4.93 +      if (avlheight(c->right) - avlheight(c->left) == 1) {
    4.94 +        avl_rotleft(tree, c);
    4.95 +      }
    4.96 +      n = avl_rotright(tree, n);
    4.97 +    } else if (rh - lh == 2) {  
    4.98 +      UcxAVLNode *c = n->right;
    4.99 +      if (avlheight(c->left) - avlheight(c->right) == 1) {
   4.100 +        avl_rotright(tree, c);
   4.101 +      }
   4.102 +      n = avl_rotleft(tree, n);
   4.103 +    }
   4.104 +
   4.105 +    if (n->parent) {
   4.106 +      ucx_avl_balance(tree, n->parent);
   4.107 +    } else {
   4.108 +      tree->root = n;
   4.109 +    }
   4.110 +}
   4.111 +
   4.112 +UcxAVLTree *ucx_avl_new(cmp_func cmpfunc) {
   4.113 +    return ucx_avl_new_a(cmpfunc, ucx_default_allocator());
   4.114 +}
   4.115 +
   4.116 +UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator) {
   4.117 +    UcxAVLTree* tree = alloc_tree(allocator);
   4.118 +    if (tree) {
   4.119 +        tree->allocator = allocator;
   4.120 +        tree->cmpfunc = cmpfunc;
   4.121 +        tree->root = NULL;
   4.122 +        tree->userdata = NULL;
   4.123 +    }
   4.124 +    
   4.125 +    return tree;
   4.126 +}
   4.127 +
   4.128 +static void ucx_avl_free_node(UcxAllocator *al, UcxAVLNode *node) {
   4.129 +    if (node) {
   4.130 +        ucx_avl_free_node(al, node->left);
   4.131 +        ucx_avl_free_node(al, node->right);
   4.132 +        alfree(al, node);
   4.133 +    }
   4.134 +}
   4.135 +
   4.136 +void ucx_avl_free(UcxAVLTree *tree) {
   4.137 +    UcxAllocator *al = tree->allocator;
   4.138 +    ucx_avl_free_node(al, tree->root);
   4.139 +    alfree(al, tree);
   4.140 +}
   4.141 +
   4.142 +UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key) {
   4.143 +    UcxAVLNode *n = tree->root;
   4.144 +    int cmpresult;
   4.145 +    while (n && (cmpresult = tree->cmpfunc(
   4.146 +            ptrcast(key), ptrcast(n->key), tree->userdata))) {
   4.147 +        n = cmpresult > 0 ? n->right : n->left;
   4.148 +    }
   4.149 +    return n;
   4.150 +}
   4.151 +
   4.152 +void *ucx_avl_get(UcxAVLTree *tree, intptr_t key) {
   4.153 +    UcxAVLNode *n = ucx_avl_get_node(tree, key);
   4.154 +    return n ? n->value : NULL;
   4.155 +}
   4.156 +
   4.157 +UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key,
   4.158 +        distance_func dfnc, int mode) {
   4.159 +    UcxAVLNode *n = tree->root;
   4.160 +    UcxAVLNode *closest = NULL;
   4.161 +
   4.162 +    intmax_t cmpresult;
   4.163 +    intmax_t closest_dist;
   4.164 +    closest_dist = mode == UCX_AVL_FIND_LOWER_BOUNDED ? INTMAX_MIN : INTMAX_MAX;
   4.165 +    
   4.166 +    while (n && (cmpresult = dfnc(
   4.167 +            ptrcast(key), ptrcast(n->key), tree->userdata))) {
   4.168 +        if (mode == UCX_AVL_FIND_CLOSEST) {
   4.169 +            intmax_t dist = cmpresult;
   4.170 +            if (dist < 0) dist *= -1;
   4.171 +            if (dist < closest_dist) {
   4.172 +                closest_dist = dist;
   4.173 +                closest = n;
   4.174 +            }
   4.175 +        } else if (mode == UCX_AVL_FIND_LOWER_BOUNDED && cmpresult <= 0) {
   4.176 +            if (cmpresult > closest_dist) {
   4.177 +                closest_dist = cmpresult;
   4.178 +                closest = n;
   4.179 +            }
   4.180 +        } else if (mode == UCX_AVL_FIND_UPPER_BOUNDED && cmpresult >= 0) {
   4.181 +            if (cmpresult < closest_dist) {
   4.182 +                closest_dist = cmpresult;
   4.183 +                closest = n;
   4.184 +            }
   4.185 +        }
   4.186 +        n = cmpresult > 0 ? n->right : n->left;
   4.187 +    }
   4.188 +    return n ? n : closest;
   4.189 +}
   4.190 +
   4.191 +void *ucx_avl_find(UcxAVLTree *tree, intptr_t key,
   4.192 +        distance_func dfnc, int mode) {
   4.193 +    UcxAVLNode *n = ucx_avl_find_node(tree, key, dfnc, mode);
   4.194 +    return n ? n->value : NULL;
   4.195 +}
   4.196 +
   4.197 +int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value) {
   4.198 +    return ucx_avl_put_s(tree, key, value, NULL);
   4.199 +}
   4.200 +
   4.201 +int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value,
   4.202 +        void **oldvalue) {
   4.203 +    if (tree->root) {
   4.204 +        UcxAVLNode *n = tree->root;
   4.205 +        int cmpresult;
   4.206 +        while ((cmpresult = tree->cmpfunc(
   4.207 +                ptrcast(key), ptrcast(n->key), tree->userdata))) {
   4.208 +            UcxAVLNode *m = cmpresult > 0 ? n->right : n->left;
   4.209 +            if (m) {
   4.210 +                n = m;
   4.211 +            } else {
   4.212 +                break;
   4.213 +            }
   4.214 +        }
   4.215 +
   4.216 +        if (cmpresult) {
   4.217 +            UcxAVLNode* e = alloc_node(tree->allocator);
   4.218 +            if (e) {
   4.219 +                e->key = key; e->value = value; e->height = 1;
   4.220 +                e->parent = e->left = e->right = NULL;
   4.221 +                ucx_avl_connect(tree, n, e, 0);
   4.222 +                ucx_avl_balance(tree, n);
   4.223 +                return 0;
   4.224 +            } else {
   4.225 +                return 1;
   4.226 +            }
   4.227 +        } else {
   4.228 +            if (oldvalue) {
   4.229 +                *oldvalue = n->value;
   4.230 +            }
   4.231 +            n->value = value;
   4.232 +            return 0;
   4.233 +        }
   4.234 +    } else {
   4.235 +        tree->root = alloc_node(tree->allocator);
   4.236 +        if (tree->root) {
   4.237 +            tree->root->key = key; tree->root->value = value;
   4.238 +            tree->root->height = 1;
   4.239 +            tree->root->parent = tree->root->left = tree->root->right = NULL;
   4.240 +            
   4.241 +            if (oldvalue) {
   4.242 +                *oldvalue = NULL;
   4.243 +            }
   4.244 +            
   4.245 +            return 0;
   4.246 +        } else {
   4.247 +            return 1;
   4.248 +        }
   4.249 +    }
   4.250 +}
   4.251 +
   4.252 +int ucx_avl_remove(UcxAVLTree *tree, intptr_t key) {
   4.253 +    return ucx_avl_remove_s(tree, key, NULL, NULL);
   4.254 +}
   4.255 +    
   4.256 +int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node) {
   4.257 +    return ucx_avl_remove_s(tree, node->key, NULL, NULL);
   4.258 +}
   4.259 +
   4.260 +int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key,
   4.261 +        intptr_t *oldkey, void **oldvalue) {
   4.262 +    
   4.263 +    UcxAVLNode *n = tree->root;
   4.264 +    int cmpresult;
   4.265 +    while (n && (cmpresult = tree->cmpfunc(
   4.266 +            ptrcast(key), ptrcast(n->key), tree->userdata))) {
   4.267 +        n = cmpresult > 0 ? n->right : n->left;
   4.268 +    }
   4.269 +    if (n) {
   4.270 +        if (oldkey) {
   4.271 +            *oldkey = n->key;
   4.272 +        }
   4.273 +        if (oldvalue) {
   4.274 +            *oldvalue = n->value;
   4.275 +        }
   4.276 +        
   4.277 +        UcxAVLNode *p = n->parent;
   4.278 +        if (n->left && n->right) {
   4.279 +            UcxAVLNode *s = n->right;
   4.280 +            while (s->left) {
   4.281 +                s = s->left;
   4.282 +            }
   4.283 +            ucx_avl_connect(tree, s->parent, s->right, s->key);
   4.284 +            n->key = s->key; n->value = s->value;
   4.285 +            p = s->parent;
   4.286 +            alfree(tree->allocator, s);
   4.287 +        } else {
   4.288 +            if (p) {
   4.289 +                ucx_avl_connect(tree, p, n->right ? n->right:n->left, n->key);
   4.290 +            } else {
   4.291 +                tree->root = n->right ? n->right : n->left;
   4.292 +                if (tree->root) {
   4.293 +                    tree->root->parent = NULL;
   4.294 +                }
   4.295 +            }
   4.296 +            alfree(tree->allocator, n);
   4.297 +        }
   4.298 +
   4.299 +        if (p) {
   4.300 +            ucx_avl_balance(tree, p);
   4.301 +        }
   4.302 +        
   4.303 +        return 0;
   4.304 +    } else {
   4.305 +        return 1;
   4.306 +    }
   4.307 +}
   4.308 +
   4.309 +static size_t ucx_avl_countn(UcxAVLNode *node) {
   4.310 +    if (node) {
   4.311 +        return 1 + ucx_avl_countn(node->left) + ucx_avl_countn(node->right);
   4.312 +    } else {
   4.313 +        return 0;
   4.314 +    }
   4.315 +}
   4.316 +
   4.317 +size_t ucx_avl_count(UcxAVLTree *tree) {
   4.318 +    return ucx_avl_countn(tree->root);
   4.319 +}
   4.320 +
   4.321 +UcxAVLNode* ucx_avl_pred(UcxAVLNode* node) {
   4.322 +    if (node->left) {
   4.323 +        UcxAVLNode* n = node->left;
   4.324 +        while (n->right) {
   4.325 +            n = n->right;
   4.326 +        }
   4.327 +        return n;
   4.328 +    } else {
   4.329 +        UcxAVLNode* n = node;
   4.330 +        while (n->parent) {
   4.331 +            if (n->parent->right == n) {
   4.332 +                return n->parent;
   4.333 +            } else {
   4.334 +                n = n->parent;
   4.335 +            }
   4.336 +        }
   4.337 +        return NULL;
   4.338 +    }
   4.339 +}
   4.340 +
   4.341 +UcxAVLNode* ucx_avl_succ(UcxAVLNode* node) {
   4.342 +    if (node->right) {
   4.343 +        UcxAVLNode* n = node->right;
   4.344 +        while (n->left) {
   4.345 +            n = n->left;
   4.346 +        }
   4.347 +        return n;
   4.348 +    } else {
   4.349 +        UcxAVLNode* n = node;
   4.350 +        while (n->parent) {
   4.351 +            if (n->parent->left == n) {
   4.352 +                return n->parent;
   4.353 +            } else {
   4.354 +                n = n->parent;
   4.355 +            }
   4.356 +        }
   4.357 +        return NULL;
   4.358 +    }
   4.359 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/buffer.c	Tue Oct 17 16:15:41 2017 +0200
     5.3 @@ -0,0 +1,236 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     5.8 + *
     5.9 + * Redistribution and use in source and binary forms, with or without
    5.10 + * modification, are permitted provided that the following conditions are met:
    5.11 + *
    5.12 + *   1. Redistributions of source code must retain the above copyright
    5.13 + *      notice, this list of conditions and the following disclaimer.
    5.14 + *
    5.15 + *   2. Redistributions in binary form must reproduce the above copyright
    5.16 + *      notice, this list of conditions and the following disclaimer in the
    5.17 + *      documentation and/or other materials provided with the distribution.
    5.18 + *
    5.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    5.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    5.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    5.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    5.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    5.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    5.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    5.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    5.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    5.29 + * POSSIBILITY OF SUCH DAMAGE.
    5.30 + */
    5.31 +
    5.32 +#include "ucx/buffer.h"
    5.33 +
    5.34 +#include <stdarg.h>
    5.35 +#include <stdlib.h>
    5.36 +#include <string.h>
    5.37 +
    5.38 +UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) {
    5.39 +    UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
    5.40 +    if (buffer) {
    5.41 +        buffer->flags = flags;
    5.42 +        if (!space) {
    5.43 +            buffer->space = (char*)malloc(capacity);
    5.44 +            if (!buffer->space) {
    5.45 +                free(buffer);
    5.46 +                return NULL;
    5.47 +            }
    5.48 +            memset(buffer->space, 0, capacity);
    5.49 +            buffer->flags |= UCX_BUFFER_AUTOFREE;
    5.50 +        } else {
    5.51 +            buffer->space = (char*)space;
    5.52 +        }
    5.53 +        buffer->capacity = capacity;
    5.54 +        buffer->size = 0;
    5.55 +
    5.56 +        buffer->pos = 0;
    5.57 +    }
    5.58 +
    5.59 +    return buffer;
    5.60 +}
    5.61 +
    5.62 +void ucx_buffer_free(UcxBuffer *buffer) {
    5.63 +    if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) {
    5.64 +        free(buffer->space);
    5.65 +    }
    5.66 +    free(buffer);
    5.67 +}
    5.68 +
    5.69 +UcxBuffer* ucx_buffer_extract(
    5.70 +        UcxBuffer *src, size_t start, size_t length, int flags) {
    5.71 +    if (src->size == 0 || length == 0 ||
    5.72 +        ((size_t)-1) - start < length || start+length > src->capacity)
    5.73 +    {
    5.74 +        return NULL;
    5.75 +    }
    5.76 +
    5.77 +    UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
    5.78 +    if (dst) {
    5.79 +        dst->space = (char*)malloc(length);
    5.80 +        if (!dst->space) {
    5.81 +            free(dst);
    5.82 +            return NULL;
    5.83 +        }
    5.84 +        dst->capacity = length;
    5.85 +        dst->size = length;
    5.86 +        dst->flags = flags | UCX_BUFFER_AUTOFREE;
    5.87 +        dst->pos = 0;
    5.88 +        memcpy(dst->space, src->space+start, length);
    5.89 +    }
    5.90 +    return dst;
    5.91 +}
    5.92 +
    5.93 +int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
    5.94 +    size_t npos;
    5.95 +    switch (whence) {
    5.96 +    case SEEK_CUR:
    5.97 +        npos = buffer->pos;
    5.98 +        break;
    5.99 +    case SEEK_END:
   5.100 +        npos = buffer->size;
   5.101 +        break;
   5.102 +    case SEEK_SET:
   5.103 +        npos = 0;
   5.104 +        break;
   5.105 +    default:
   5.106 +        return -1;
   5.107 +    }
   5.108 +
   5.109 +    size_t opos = npos;
   5.110 +    npos += offset;
   5.111 +    
   5.112 +    if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
   5.113 +        return -1;
   5.114 +    }
   5.115 +    
   5.116 +    if (npos >= buffer->size) {
   5.117 +        return -1;
   5.118 +    } else {
   5.119 +        buffer->pos = npos;
   5.120 +        return 0;
   5.121 +    }
   5.122 +
   5.123 +}
   5.124 +
   5.125 +int ucx_buffer_eof(UcxBuffer *buffer) {
   5.126 +    return buffer->pos >= buffer->size;
   5.127 +}
   5.128 +
   5.129 +int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
   5.130 +    size_t newcap = buffer->capacity;
   5.131 +    
   5.132 +    if (buffer->capacity + len < buffer->capacity) {
   5.133 +        return -1;
   5.134 +    }
   5.135 +    
   5.136 +    while (buffer->capacity + len > newcap) {
   5.137 +        newcap <<= 1;
   5.138 +        if (newcap < buffer->capacity) {
   5.139 +            return -1;
   5.140 +        }
   5.141 +    }
   5.142 +    
   5.143 +    char *newspace = (char*)realloc(buffer->space, newcap);
   5.144 +    if (newspace) {
   5.145 +        memset(newspace+buffer->size, 0, newcap-buffer->size);
   5.146 +        buffer->space = newspace;
   5.147 +        buffer->capacity = newcap;
   5.148 +    } else {
   5.149 +        return -1;
   5.150 +    }
   5.151 +    
   5.152 +    return 0;
   5.153 +}
   5.154 +
   5.155 +size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
   5.156 +        UcxBuffer *buffer) {
   5.157 +    size_t len = size * nitems;
   5.158 +    size_t required = buffer->pos + len;
   5.159 +    if (buffer->pos > required) {
   5.160 +        return 0;
   5.161 +    }
   5.162 +    
   5.163 +    if (required > buffer->capacity) {
   5.164 +        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
   5.165 +            if (ucx_buffer_extend(buffer, required - buffer->capacity)) {
   5.166 +                return 0;
   5.167 +            }
   5.168 +        } else {
   5.169 +            len = buffer->capacity - buffer->pos;
   5.170 +            if (size > 1) {
   5.171 +                len -= len%size;
   5.172 +            }
   5.173 +        }
   5.174 +    }
   5.175 +    
   5.176 +    if (len == 0) {
   5.177 +        return len;
   5.178 +    }
   5.179 +    
   5.180 +    memcpy(buffer->space + buffer->pos, ptr, len);
   5.181 +    buffer->pos += len;
   5.182 +    if(buffer->pos > buffer->size) {
   5.183 +        buffer->size = buffer->pos;
   5.184 +    }
   5.185 +    
   5.186 +    return len / size;
   5.187 +}
   5.188 +
   5.189 +size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
   5.190 +        UcxBuffer *buffer) {
   5.191 +    size_t len = size * nitems;
   5.192 +    if (buffer->pos + len > buffer->size) {
   5.193 +        len = buffer->size - buffer->pos;
   5.194 +        if (size > 1) len -= len%size;
   5.195 +    }
   5.196 +    
   5.197 +    if (len <= 0) {
   5.198 +        return len;
   5.199 +    }
   5.200 +    
   5.201 +    memcpy(ptr, buffer->space + buffer->pos, len);
   5.202 +    buffer->pos += len;
   5.203 +    
   5.204 +    return len / size;
   5.205 +}
   5.206 +
   5.207 +int ucx_buffer_putc(UcxBuffer *buffer, int c) {
   5.208 +    if(buffer->pos >= buffer->capacity) {
   5.209 +        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
   5.210 +            if(ucx_buffer_extend(buffer, 1)) {
   5.211 +                return EOF;
   5.212 +            }
   5.213 +        } else {
   5.214 +            return EOF;
   5.215 +        }
   5.216 +    }
   5.217 +    
   5.218 +    c &= 0xFF;
   5.219 +    buffer->space[buffer->pos] = (char) c;
   5.220 +    buffer->pos++;
   5.221 +    if(buffer->pos > buffer->size) {
   5.222 +        buffer->size = buffer->pos;
   5.223 +    }
   5.224 +    return c;
   5.225 +}
   5.226 +
   5.227 +int ucx_buffer_getc(UcxBuffer *buffer) {
   5.228 +    if (ucx_buffer_eof(buffer)) {
   5.229 +        return EOF;
   5.230 +    } else {
   5.231 +        int c = buffer->space[buffer->pos];
   5.232 +        buffer->pos++;
   5.233 +        return c;
   5.234 +    }
   5.235 +}
   5.236 +
   5.237 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) {
   5.238 +    return ucx_buffer_write((const void*)str, 1, strlen(str), buffer);
   5.239 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/list.c	Tue Oct 17 16:15:41 2017 +0200
     6.3 @@ -0,0 +1,370 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     6.8 + *
     6.9 + * Redistribution and use in source and binary forms, with or without
    6.10 + * modification, are permitted provided that the following conditions are met:
    6.11 + *
    6.12 + *   1. Redistributions of source code must retain the above copyright
    6.13 + *      notice, this list of conditions and the following disclaimer.
    6.14 + *
    6.15 + *   2. Redistributions in binary form must reproduce the above copyright
    6.16 + *      notice, this list of conditions and the following disclaimer in the
    6.17 + *      documentation and/or other materials provided with the distribution.
    6.18 + *
    6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    6.29 + * POSSIBILITY OF SUCH DAMAGE.
    6.30 + */
    6.31 +
    6.32 +#include "ucx/list.h"
    6.33 +
    6.34 +UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
    6.35 +    return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data);
    6.36 +}
    6.37 +
    6.38 +UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l,
    6.39 +        copy_func fnc, void *data) {
    6.40 +    UcxList *ret = NULL;
    6.41 +    while (l) {
    6.42 +        if (fnc) {
    6.43 +            ret = ucx_list_append_a(alloc, ret, fnc(l->data, data));
    6.44 +        } else {
    6.45 +            ret = ucx_list_append_a(alloc, ret, l->data);
    6.46 +        }
    6.47 +        l = l->next;
    6.48 +    }
    6.49 +    return ret;
    6.50 +}
    6.51 +
    6.52 +int ucx_list_equals(const UcxList *l1, const UcxList *l2,
    6.53 +        cmp_func fnc, void* data) {
    6.54 +    if (l1 == l2) return 1;
    6.55 +    
    6.56 +    while (l1 != NULL && l2 != NULL) {
    6.57 +        if (fnc == NULL) {
    6.58 +            if (l1->data != l2->data) return 0;
    6.59 +        } else {
    6.60 +            if (fnc(l1->data, l2->data, data) != 0) return 0;
    6.61 +        }
    6.62 +        l1 = l1->next;
    6.63 +        l2 = l2->next;
    6.64 +    }
    6.65 +    
    6.66 +    return (l1 == NULL && l2 == NULL);
    6.67 +}
    6.68 +
    6.69 +void ucx_list_free(UcxList *l) {
    6.70 +    ucx_list_free_a(ucx_default_allocator(), l);
    6.71 +}
    6.72 +
    6.73 +void ucx_list_free_a(UcxAllocator *alloc, UcxList *l) {
    6.74 +    UcxList *e = l, *f;
    6.75 +    while (e != NULL) {
    6.76 +        f = e;
    6.77 +        e = e->next;
    6.78 +        alfree(alloc, f);
    6.79 +    }
    6.80 +}
    6.81 +
    6.82 +void ucx_list_free_content(UcxList* list, ucx_destructor destr) {
    6.83 +    while (list != NULL) {
    6.84 +        destr(list->data);
    6.85 +        list = list->next;
    6.86 +    }
    6.87 +}
    6.88 +
    6.89 +UcxList *ucx_list_append(UcxList *l, void *data)  {
    6.90 +    return ucx_list_append_a(ucx_default_allocator(), l, data);
    6.91 +}
    6.92 +
    6.93 +UcxList *ucx_list_append_a(UcxAllocator *alloc, UcxList *l, void *data)  {
    6.94 +    UcxList *nl = (UcxList*) almalloc(alloc, sizeof(UcxList));
    6.95 +    if (!nl) {
    6.96 +        return NULL;
    6.97 +    }
    6.98 +    
    6.99 +    nl->data = data;
   6.100 +    nl->next = NULL;
   6.101 +    if (l) {
   6.102 +        UcxList *t = ucx_list_last(l);
   6.103 +        t->next = nl;
   6.104 +        nl->prev = t;
   6.105 +        return l;
   6.106 +    } else {
   6.107 +        nl->prev = NULL;
   6.108 +        return nl;
   6.109 +    }
   6.110 +}
   6.111 +
   6.112 +UcxList *ucx_list_append_once(UcxList *l, void *data,
   6.113 +        cmp_func cmpfnc, void *cmpdata) {
   6.114 +    return ucx_list_append_once_a(ucx_default_allocator(), l,
   6.115 +            data, cmpfnc, cmpdata);
   6.116 +}
   6.117 +
   6.118 +UcxList *ucx_list_append_once_a(UcxAllocator *alloc, UcxList *l, void *data,
   6.119 +        cmp_func cmpfnc, void *cmpdata) {
   6.120 +
   6.121 +    UcxList *last = NULL;
   6.122 +    {
   6.123 +        UcxList *e = l;
   6.124 +        while (e) {
   6.125 +            if (cmpfnc(e->data, data, cmpdata) == 0) {
   6.126 +                return l;
   6.127 +            }
   6.128 +            last = e;
   6.129 +            e = e->next;
   6.130 +        }
   6.131 +    }
   6.132 +    
   6.133 +    UcxList *nl = ucx_list_append_a(alloc, NULL, data);
   6.134 +    if (!nl) {
   6.135 +        return NULL;
   6.136 +    }
   6.137 +
   6.138 +    if (last == NULL) {
   6.139 +        return nl;
   6.140 +    } else {
   6.141 +        nl->prev = last;
   6.142 +        last->next = nl;
   6.143 +        return l;
   6.144 +    }
   6.145 +}
   6.146 +
   6.147 +UcxList *ucx_list_prepend(UcxList *l, void *data) {
   6.148 +    return ucx_list_prepend_a(ucx_default_allocator(), l, data);
   6.149 +}
   6.150 +
   6.151 +UcxList *ucx_list_prepend_a(UcxAllocator *alloc, UcxList *l, void *data) {
   6.152 +    UcxList *nl = ucx_list_append_a(alloc, NULL, data);
   6.153 +    if (!nl) {
   6.154 +        return NULL;
   6.155 +    }
   6.156 +    l = ucx_list_first(l);
   6.157 +    
   6.158 +    if (l) {
   6.159 +        nl->next = l;
   6.160 +        l->prev = nl;
   6.161 +    }
   6.162 +    return nl;
   6.163 +}
   6.164 +
   6.165 +UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
   6.166 +    if (l1) {
   6.167 +        UcxList *last = ucx_list_last(l1);
   6.168 +        last->next = l2;
   6.169 +        if (l2) {
   6.170 +            l2->prev = last;
   6.171 +        }
   6.172 +        return l1;
   6.173 +    } else {
   6.174 +        return l2;
   6.175 +    }
   6.176 +}
   6.177 +
   6.178 +UcxList *ucx_list_last(const UcxList *l) {
   6.179 +    if (l == NULL) return NULL;
   6.180 +    
   6.181 +    const UcxList *e = l;
   6.182 +    while (e->next != NULL) {
   6.183 +        e = e->next;
   6.184 +    }
   6.185 +    return (UcxList*)e;
   6.186 +}
   6.187 +
   6.188 +ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) {
   6.189 +    ssize_t index = 0;
   6.190 +    while (list) {
   6.191 +        if (list == elem) {
   6.192 +            return index;
   6.193 +        }
   6.194 +        list = list->next;
   6.195 +        index++;
   6.196 +    }
   6.197 +    return -1;
   6.198 +}
   6.199 +
   6.200 +UcxList *ucx_list_get(const UcxList *l, size_t index) {
   6.201 +    if (l == NULL) return NULL;
   6.202 +
   6.203 +    const UcxList *e = l;
   6.204 +    while (e->next && index > 0) {
   6.205 +        e = e->next;
   6.206 +        index--;
   6.207 +    }
   6.208 +    
   6.209 +    return (UcxList*)(index == 0 ? e : NULL);
   6.210 +}
   6.211 +
   6.212 +ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
   6.213 +    ssize_t index = 0;
   6.214 +    UCX_FOREACH(e, l) {
   6.215 +        if (fnc) {
   6.216 +            if (fnc(elem, e->data, cmpdata) == 0) {
   6.217 +                return index;
   6.218 +            }
   6.219 +        } else {
   6.220 +            if (elem == e->data) {
   6.221 +                return index;
   6.222 +            }
   6.223 +        }
   6.224 +        index++;
   6.225 +    }
   6.226 +    return -1;
   6.227 +}
   6.228 +
   6.229 +int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
   6.230 +    return ucx_list_find(l, elem, fnc, cmpdata) > -1;
   6.231 +}
   6.232 +
   6.233 +size_t ucx_list_size(const UcxList *l) {
   6.234 +    if (l == NULL) return 0;
   6.235 +    
   6.236 +    const UcxList *e = l;
   6.237 +    size_t s = 1;
   6.238 +    while (e->next != NULL) {
   6.239 +        e = e->next;
   6.240 +        s++;
   6.241 +    }
   6.242 +
   6.243 +    return s;
   6.244 +}
   6.245 +
   6.246 +static UcxList *ucx_list_sort_merge(int length,
   6.247 +        UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
   6.248 +        cmp_func fnc, void* data) {
   6.249 +
   6.250 +    UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
   6.251 +    UcxList *rc, *lc;
   6.252 +
   6.253 +    lc = ls; rc = le;
   6.254 +    int n = 0;
   6.255 +    while (lc && lc != le && rc != re) {
   6.256 +        if (fnc(lc->data, rc->data, data) <= 0) {
   6.257 +            sorted[n] = lc;
   6.258 +            lc = lc->next;
   6.259 +        } else {
   6.260 +            sorted[n] = rc;
   6.261 +            rc = rc->next;
   6.262 +        }
   6.263 +        n++;
   6.264 +    }
   6.265 +    while (lc && lc != le) {
   6.266 +        sorted[n] = lc;
   6.267 +        lc = lc->next;
   6.268 +        n++;
   6.269 +    }
   6.270 +    while (rc && rc != re) {
   6.271 +        sorted[n] = rc;
   6.272 +        rc = rc->next;
   6.273 +        n++;
   6.274 +    }
   6.275 +
   6.276 +    // Update pointer
   6.277 +    sorted[0]->prev = NULL;
   6.278 +    for (int i = 0 ; i < length-1 ; i++) {
   6.279 +        sorted[i]->next = sorted[i+1];
   6.280 +        sorted[i+1]->prev = sorted[i];
   6.281 +    }
   6.282 +    sorted[length-1]->next = NULL;
   6.283 +
   6.284 +    UcxList *ret = sorted[0];
   6.285 +    free(sorted);
   6.286 +    return ret;
   6.287 +}
   6.288 +
   6.289 +UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
   6.290 +    if (l == NULL) {
   6.291 +        return NULL;
   6.292 +    }
   6.293 +
   6.294 +    UcxList *lc;
   6.295 +    int ln = 1;
   6.296 +
   6.297 +    UcxList *restrict ls = l, *restrict le, *restrict re;
   6.298 +    
   6.299 +    // check how many elements are already sorted
   6.300 +    lc = ls;
   6.301 +    while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
   6.302 +        lc = lc->next;
   6.303 +        ln++;
   6.304 +    }
   6.305 +    le = lc->next;
   6.306 +
   6.307 +    if (le == NULL) {
   6.308 +        return l; // this list is already sorted :)
   6.309 +    } else {
   6.310 +        UcxList *rc;
   6.311 +        int rn = 1;
   6.312 +        rc = le;
   6.313 +        // skip already sorted elements
   6.314 +        while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
   6.315 +            rc = rc->next;
   6.316 +            rn++;
   6.317 +        }
   6.318 +        re = rc->next;
   6.319 +
   6.320 +        // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   6.321 +        UcxList *sorted = ucx_list_sort_merge(ln+rn,
   6.322 +                ls, le, re,
   6.323 +                fnc, data);
   6.324 +        
   6.325 +        // Something left? Sort it!
   6.326 +        size_t remainder_length = ucx_list_size(re);
   6.327 +        if (remainder_length > 0) {
   6.328 +            UcxList *remainder = ucx_list_sort(re, fnc, data);
   6.329 +
   6.330 +            // merge sorted list with (also sorted) remainder
   6.331 +            l = ucx_list_sort_merge(ln+rn+remainder_length,
   6.332 +                    sorted, remainder, NULL, fnc, data);
   6.333 +        } else {
   6.334 +            // no remainder - we've got our sorted list
   6.335 +            l = sorted;
   6.336 +        }
   6.337 +
   6.338 +        return l;
   6.339 +    }
   6.340 +}
   6.341 +
   6.342 +UcxList *ucx_list_first(const UcxList *l) {
   6.343 +    if (!l) {
   6.344 +        return NULL;
   6.345 +    }
   6.346 +    
   6.347 +    const UcxList *e = l;
   6.348 +    while (e->prev) {
   6.349 +        e = e->prev;
   6.350 +    }
   6.351 +    return (UcxList *)e;
   6.352 +}
   6.353 +
   6.354 +UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
   6.355 +    return ucx_list_remove_a(ucx_default_allocator(), l, e);
   6.356 +}
   6.357 +    
   6.358 +UcxList *ucx_list_remove_a(UcxAllocator *alloc, UcxList *l, UcxList *e) {
   6.359 +    if (l == e) {
   6.360 +        l = e->next;
   6.361 +    }
   6.362 +    
   6.363 +    if (e->next) {
   6.364 +        e->next->prev = e->prev;
   6.365 +    }
   6.366 +    
   6.367 +    if (e->prev) {
   6.368 +        e->prev->next = e->next;
   6.369 +    }
   6.370 +    
   6.371 +    alfree(alloc, e);
   6.372 +    return l;
   6.373 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/logging.c	Tue Oct 17 16:15:41 2017 +0200
     7.3 @@ -0,0 +1,106 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     7.8 + *
     7.9 + * Redistribution and use in source and binary forms, with or without
    7.10 + * modification, are permitted provided that the following conditions are met:
    7.11 + *
    7.12 + *   1. Redistributions of source code must retain the above copyright
    7.13 + *      notice, this list of conditions and the following disclaimer.
    7.14 + *
    7.15 + *   2. Redistributions in binary form must reproduce the above copyright
    7.16 + *      notice, this list of conditions and the following disclaimer in the
    7.17 + *      documentation and/or other materials provided with the distribution.
    7.18 + *
    7.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    7.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    7.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    7.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    7.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    7.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    7.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    7.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    7.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    7.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    7.29 + * POSSIBILITY OF SUCH DAMAGE.
    7.30 + */
    7.31 +
    7.32 +#include "ucx/logging.h"
    7.33 +
    7.34 +#include <stdlib.h>
    7.35 +#include <string.h>
    7.36 +#include <stdarg.h>
    7.37 +#include <time.h>
    7.38 +
    7.39 +UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask) {
    7.40 +    UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger));
    7.41 +    if (logger != NULL) {
    7.42 +        logger->stream = stream;
    7.43 +        logger->writer = (write_func)fwrite;
    7.44 +        logger->dateformat = (char*) "%F %T %z ";
    7.45 +        logger->level = level;
    7.46 +        logger->mask = mask;
    7.47 +        logger->levels = ucx_map_new(8);
    7.48 +        
    7.49 +        unsigned int l;
    7.50 +        l = UCX_LOGGER_ERROR;
    7.51 +        ucx_map_int_put(logger->levels, l, (void*) "[ERROR]");
    7.52 +        l = UCX_LOGGER_WARN;
    7.53 +        ucx_map_int_put(logger->levels, l, (void*) "[WARNING]");
    7.54 +        l = UCX_LOGGER_INFO;
    7.55 +        ucx_map_int_put(logger->levels, l, (void*) "[INFO]");
    7.56 +        l = UCX_LOGGER_TRACE;
    7.57 +        ucx_map_int_put(logger->levels, l, (void*) "[TRACE]");
    7.58 +    }
    7.59 +
    7.60 +    return logger;
    7.61 +}
    7.62 +
    7.63 +void ucx_logger_free(UcxLogger *logger) {
    7.64 +    ucx_map_free(logger->levels);
    7.65 +    free(logger);
    7.66 +}
    7.67 +
    7.68 +// estimated max. message length (documented)
    7.69 +#define UCX_LOGGER_MSGMAX 4096
    7.70 +
    7.71 +void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
    7.72 +        const unsigned int line, const char *format, ...) {
    7.73 +    if (level <= logger->level) {
    7.74 +        char msg[UCX_LOGGER_MSGMAX];
    7.75 +        char *text;
    7.76 +        size_t k = 0;
    7.77 +        size_t n;
    7.78 +        
    7.79 +        if ((logger->mask & UCX_LOGGER_LEVEL) > 0) {
    7.80 +            text = (char*) ucx_map_int_get(logger->levels, level);
    7.81 +            n = strlen(text);
    7.82 +            n = n > 256 ? 256 : n;
    7.83 +            memcpy(msg+k, text, n);
    7.84 +            k += n;
    7.85 +            msg[k++] = ' ';
    7.86 +        }
    7.87 +        if ((logger->mask & UCX_LOGGER_TIMESTAMP) > 0) {
    7.88 +            time_t now = time(NULL);
    7.89 +            k += strftime(msg+k, 128, logger->dateformat, localtime(&now));
    7.90 +        }
    7.91 +        if ((logger->mask & UCX_LOGGER_SOURCE) > 0) {
    7.92 +            n = strlen(file);
    7.93 +            memcpy(msg+k, file, n);
    7.94 +            k += n;
    7.95 +            k += sprintf(msg+k, ":%u ", line);
    7.96 +        }
    7.97 +        
    7.98 +        msg[k++] = '-'; msg[k++] = ' ';
    7.99 +        
   7.100 +        va_list args;
   7.101 +        va_start (args, format);
   7.102 +        k += vsnprintf(msg+k, UCX_LOGGER_MSGMAX-k-1, format, args);
   7.103 +        va_end (args);        
   7.104 +        
   7.105 +        msg[k++] = '\n';
   7.106 +        
   7.107 +        logger->writer(msg, 1, k, logger->stream);
   7.108 +    }
   7.109 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/map.c	Tue Oct 17 16:15:41 2017 +0200
     8.3 @@ -0,0 +1,328 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     8.8 + *
     8.9 + * Redistribution and use in source and binary forms, with or without
    8.10 + * modification, are permitted provided that the following conditions are met:
    8.11 + *
    8.12 + *   1. Redistributions of source code must retain the above copyright
    8.13 + *      notice, this list of conditions and the following disclaimer.
    8.14 + *
    8.15 + *   2. Redistributions in binary form must reproduce the above copyright
    8.16 + *      notice, this list of conditions and the following disclaimer in the
    8.17 + *      documentation and/or other materials provided with the distribution.
    8.18 + *
    8.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    8.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    8.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    8.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    8.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    8.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    8.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    8.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    8.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    8.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    8.29 + * POSSIBILITY OF SUCH DAMAGE.
    8.30 + */
    8.31 +
    8.32 +#include "ucx/map.h"
    8.33 +
    8.34 +#include <stdlib.h>
    8.35 +#include <string.h>
    8.36 +
    8.37 +UcxMap *ucx_map_new(size_t size) {
    8.38 +    return ucx_map_new_a(NULL, size);
    8.39 +}
    8.40 +
    8.41 +UcxMap *ucx_map_new_a(UcxAllocator *allocator, size_t size) {
    8.42 +    if(size == 0) {
    8.43 +        size = 16;
    8.44 +    }
    8.45 +       
    8.46 +    if(!allocator) {
    8.47 +        allocator = ucx_default_allocator();
    8.48 +    }
    8.49 +    
    8.50 +    UcxMap *map = (UcxMap*)almalloc(allocator, sizeof(UcxMap));
    8.51 +    if (!map) {
    8.52 +        return NULL;
    8.53 +    }
    8.54 +    
    8.55 +    map->allocator = allocator;
    8.56 +    map->map = (UcxMapElement**)alcalloc(
    8.57 +            allocator, size, sizeof(UcxMapElement*));
    8.58 +    if(map->map == NULL) {
    8.59 +        alfree(allocator, map);
    8.60 +        return NULL;
    8.61 +    }
    8.62 +    map->size = size;
    8.63 +    map->count = 0;
    8.64 +
    8.65 +    return map;
    8.66 +}
    8.67 +
    8.68 +static void ucx_map_free_elmlist_contents(UcxMap *map) {
    8.69 +    for (size_t n = 0 ; n < map->size ; n++) {
    8.70 +        UcxMapElement *elem = map->map[n];
    8.71 +        if (elem != NULL) {
    8.72 +            do {
    8.73 +                UcxMapElement *next = elem->next;
    8.74 +                alfree(map->allocator, elem->key.data);
    8.75 +                alfree(map->allocator, elem);
    8.76 +                elem = next;
    8.77 +            } while (elem != NULL);
    8.78 +        }
    8.79 +    }
    8.80 +}
    8.81 +
    8.82 +void ucx_map_free(UcxMap *map) {
    8.83 +    ucx_map_free_elmlist_contents(map);
    8.84 +    alfree(map->allocator, map->map);
    8.85 +    alfree(map->allocator, map);
    8.86 +}
    8.87 +
    8.88 +void ucx_map_free_content(UcxMap *map, ucx_destructor destr) {
    8.89 +    UcxMapIterator iter = ucx_map_iterator(map);
    8.90 +    void *val;
    8.91 +    UCX_MAP_FOREACH(key, val, iter) {
    8.92 +        destr(val);
    8.93 +    }
    8.94 +}
    8.95 +
    8.96 +void ucx_map_clear(UcxMap *map) {
    8.97 +    if (map->count == 0) {
    8.98 +        return; // nothing to do
    8.99 +    }
   8.100 +    ucx_map_free_elmlist_contents(map);
   8.101 +    memset(map->map, 0, map->size*sizeof(UcxMapElement*));
   8.102 +    map->count = 0;
   8.103 +}
   8.104 +
   8.105 +int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
   8.106 +        copy_func fnc, void *data) {
   8.107 +    UcxMapIterator i = ucx_map_iterator(from);
   8.108 +    void *value;
   8.109 +    UCX_MAP_FOREACH(key, value, i) {
   8.110 +        if (ucx_map_put(to, key, fnc ? fnc(value, data) : value)) {
   8.111 +            return 1;
   8.112 +        }
   8.113 +    }
   8.114 +    return 0;
   8.115 +}
   8.116 +
   8.117 +UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data) {
   8.118 +    size_t bs = (map->count * 5) >> 1;
   8.119 +    UcxMap *newmap = ucx_map_new(bs > map->size ? bs : map->size);
   8.120 +    if (!newmap) {
   8.121 +        return NULL;
   8.122 +    }
   8.123 +    ucx_map_copy(map, newmap, fnc, data);
   8.124 +    return newmap;
   8.125 +}
   8.126 +
   8.127 +int ucx_map_rehash(UcxMap *map) {
   8.128 +    size_t load = (map->size * 3) >> 2;
   8.129 +    if (map->count > load) {
   8.130 +        UcxMap oldmap;
   8.131 +        oldmap.map = map->map;
   8.132 +        oldmap.size = map->size;
   8.133 +        oldmap.count = map->count;
   8.134 +        oldmap.allocator = map->allocator;
   8.135 +        
   8.136 +        map->size = (map->count * 5) >> 1;
   8.137 +        map->map = (UcxMapElement**)alcalloc(
   8.138 +                map->allocator, map->size, sizeof(UcxMapElement*));
   8.139 +        if (!map->map) {
   8.140 +            *map = oldmap;
   8.141 +            return 1;
   8.142 +        }
   8.143 +        map->count = 0;
   8.144 +        ucx_map_copy(&oldmap, map, NULL, NULL);
   8.145 +        
   8.146 +        /* free the UcxMapElement list of oldmap */
   8.147 +        ucx_map_free_elmlist_contents(&oldmap);
   8.148 +        alfree(map->allocator, oldmap.map);
   8.149 +    }
   8.150 +    return 0;
   8.151 +}
   8.152 +
   8.153 +int ucx_map_put(UcxMap *map, UcxKey key, void *data) {
   8.154 +    UcxAllocator *allocator = map->allocator;
   8.155 +    
   8.156 +    if (key.hash == 0) {
   8.157 +        key.hash = ucx_hash((char*)key.data, key.len);
   8.158 +    }
   8.159 +
   8.160 +    size_t slot = key.hash%map->size;
   8.161 +    UcxMapElement *restrict elm = map->map[slot];
   8.162 +    UcxMapElement *restrict prev = NULL;
   8.163 +
   8.164 +    while (elm && elm->key.hash < key.hash) {
   8.165 +        prev = elm;
   8.166 +        elm = elm->next;
   8.167 +    }
   8.168 +    
   8.169 +    if (!elm || elm->key.hash != key.hash) {
   8.170 +        UcxMapElement *e = (UcxMapElement*)almalloc(
   8.171 +                allocator, sizeof(UcxMapElement));
   8.172 +        if (!e) {
   8.173 +            return -1;
   8.174 +        }
   8.175 +        e->key.data = NULL;
   8.176 +        if (prev) {
   8.177 +            prev->next = e;
   8.178 +        } else {
   8.179 +            map->map[slot] = e;
   8.180 +        }
   8.181 +        e->next = elm;
   8.182 +        elm = e;
   8.183 +    }
   8.184 +    
   8.185 +    if (!elm->key.data) {
   8.186 +        void *kd = almalloc(allocator, key.len);
   8.187 +        if (!kd) {
   8.188 +            return -1;
   8.189 +        }
   8.190 +        memcpy(kd, key.data, key.len);
   8.191 +        key.data = kd;
   8.192 +        elm->key = key;
   8.193 +        map->count++;
   8.194 +    }
   8.195 +    elm->data = data;
   8.196 +
   8.197 +    return 0;
   8.198 +}
   8.199 +
   8.200 +void* ucx_map_get_and_remove(UcxMap *map, UcxKey key, _Bool remove) {
   8.201 +    if(key.hash == 0) {
   8.202 +        key.hash = ucx_hash((char*)key.data, key.len);
   8.203 +    }
   8.204 +    
   8.205 +    size_t slot = key.hash%map->size;
   8.206 +    UcxMapElement *restrict elm = map->map[slot];
   8.207 +    UcxMapElement *restrict pelm = NULL;
   8.208 +    while (elm && elm->key.hash <= key.hash) {
   8.209 +        if(elm->key.hash == key.hash) {
   8.210 +            int n = (key.len > elm->key.len) ? elm->key.len : key.len;
   8.211 +            if (memcmp(elm->key.data, key.data, n) == 0) {
   8.212 +                void *data = elm->data;
   8.213 +                if (remove) {
   8.214 +                    if (pelm) {
   8.215 +                        pelm->next = elm->next;
   8.216 +                    } else {
   8.217 +                        map->map[slot] = elm->next;
   8.218 +                    }
   8.219 +                    alfree(map->allocator, elm->key.data);
   8.220 +                    alfree(map->allocator, elm);
   8.221 +                    map->count--;
   8.222 +                }
   8.223 +
   8.224 +                return data;
   8.225 +            }
   8.226 +        }
   8.227 +        pelm = elm;
   8.228 +        elm = pelm->next;
   8.229 +    }
   8.230 +
   8.231 +    return NULL;
   8.232 +}
   8.233 +
   8.234 +void *ucx_map_get(UcxMap *map, UcxKey key) {
   8.235 +    return ucx_map_get_and_remove(map, key, 0);
   8.236 +}
   8.237 +
   8.238 +void *ucx_map_remove(UcxMap *map, UcxKey key) {
   8.239 +    return ucx_map_get_and_remove(map, key, 1);
   8.240 +}
   8.241 +
   8.242 +UcxKey ucx_key(void *data, size_t len) {
   8.243 +    UcxKey key;
   8.244 +    key.data = data;
   8.245 +    key.len = len;
   8.246 +    key.hash = ucx_hash((const char*) data, len);
   8.247 +    return key;
   8.248 +}
   8.249 +
   8.250 +
   8.251 +int ucx_hash(const char *data, size_t len) {
   8.252 +    /* murmur hash 2 */
   8.253 +
   8.254 +    int m = 0x5bd1e995;
   8.255 +    int r = 24;
   8.256 +
   8.257 +    int h = 25 ^ len;
   8.258 +
   8.259 +    int i = 0;
   8.260 +    while (len >= 4) {
   8.261 +        int k = data[i + 0] & 0xFF;
   8.262 +        k |= (data[i + 1] & 0xFF) << 8;
   8.263 +        k |= (data[i + 2] & 0xFF) << 16;
   8.264 +        k |= (data[i + 3] & 0xFF) << 24;
   8.265 +
   8.266 +        k *= m;
   8.267 +        k ^= k >> r;
   8.268 +        k *= m;
   8.269 +
   8.270 +        h *= m;
   8.271 +        h ^= k;
   8.272 +
   8.273 +        i += 4;
   8.274 +        len -= 4;
   8.275 +    }
   8.276 +
   8.277 +    switch (len) {
   8.278 +        case 3: h ^= (data[i + 2] & 0xFF) << 16;
   8.279 +        /* no break */
   8.280 +        case 2: h ^= (data[i + 1] & 0xFF) << 8;
   8.281 +        /* no break */
   8.282 +        case 1: h ^= (data[i + 0] & 0xFF); h *= m;
   8.283 +        /* no break */
   8.284 +    }
   8.285 +
   8.286 +    h ^= h >> 13;
   8.287 +    h *= m;
   8.288 +    h ^= h >> 15;
   8.289 +
   8.290 +    return h;
   8.291 +}
   8.292 +
   8.293 +UcxMapIterator ucx_map_iterator(UcxMap *map) {
   8.294 +    UcxMapIterator i;
   8.295 +    i.map = map;
   8.296 +    i.cur = NULL;
   8.297 +    i.index = 0;
   8.298 +    return i;
   8.299 +}
   8.300 +
   8.301 +int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm) {
   8.302 +    UcxMapElement *e = i->cur;
   8.303 +    
   8.304 +    if (e) {
   8.305 +        e = e->next;
   8.306 +    } else {
   8.307 +        e = i->map->map[0];
   8.308 +    }
   8.309 +    
   8.310 +    while (i->index < i->map->size) {
   8.311 +        if (e) {
   8.312 +            if (e->data) {
   8.313 +                i->cur = e;
   8.314 +                *elm = e->data;
   8.315 +                *key = e->key;
   8.316 +                return 1;
   8.317 +            }
   8.318 +
   8.319 +            e = e->next;
   8.320 +        } else {
   8.321 +            i->index++;
   8.322 +            
   8.323 +            if (i->index < i->map->size) {
   8.324 +                e = i->map->map[i->index];
   8.325 +            }
   8.326 +        }
   8.327 +    }
   8.328 +    
   8.329 +    return 0;
   8.330 +}
   8.331 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/mempool.c	Tue Oct 17 16:15:41 2017 +0200
     9.3 @@ -0,0 +1,211 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
     9.8 + *
     9.9 + * Redistribution and use in source and binary forms, with or without
    9.10 + * modification, are permitted provided that the following conditions are met:
    9.11 + *
    9.12 + *   1. Redistributions of source code must retain the above copyright
    9.13 + *      notice, this list of conditions and the following disclaimer.
    9.14 + *
    9.15 + *   2. Redistributions in binary form must reproduce the above copyright
    9.16 + *      notice, this list of conditions and the following disclaimer in the
    9.17 + *      documentation and/or other materials provided with the distribution.
    9.18 + *
    9.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    9.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    9.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    9.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    9.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    9.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    9.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    9.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    9.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    9.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    9.29 + * POSSIBILITY OF SUCH DAMAGE.
    9.30 + */
    9.31 +
    9.32 +#include "ucx/mempool.h"
    9.33 +
    9.34 +#include <stdlib.h>
    9.35 +#include <string.h>
    9.36 +#include <stdio.h>
    9.37 +#ifdef __cplusplus
    9.38 +#define __STDC_FORMAT_MACROS
    9.39 +#endif
    9.40 +#include <inttypes.h>
    9.41 +
    9.42 +/** Capsule for destructible memory chunks. */
    9.43 +typedef struct {
    9.44 +    /** The destructor for the memory chunk. */
    9.45 +    ucx_destructor destructor;
    9.46 +    /**
    9.47 +     * First byte of the memory chunk.
    9.48 +     * Note, that the address <code>&amp;c</code> is also the address
    9.49 +     * of the whole memory chunk.
    9.50 +     */
    9.51 +    char c;
    9.52 +} ucx_memchunk;
    9.53 +
    9.54 +/** Capsule for data and its destructor. */
    9.55 +typedef struct {
    9.56 +    /** The destructor for the data. */
    9.57 +    ucx_destructor destructor;
    9.58 +    /** A pointer to the data. */
    9.59 +    void           *ptr;
    9.60 +} ucx_regdestr;
    9.61 +
    9.62 +UCX_EXTERN void ucx_mempool_shared_destr(void* ptr) {
    9.63 +    ucx_regdestr *rd = (ucx_regdestr*)ptr;
    9.64 +    rd->destructor(rd->ptr);
    9.65 +}
    9.66 +
    9.67 +UcxMempool *ucx_mempool_new(size_t n) {
    9.68 +    UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool));
    9.69 +    if (!pool) {
    9.70 +        return NULL;
    9.71 +    }
    9.72 +    
    9.73 +    pool->data = (void**) malloc(n * sizeof(void*));
    9.74 +    if (pool->data == NULL) {
    9.75 +        free(pool);
    9.76 +        return NULL;
    9.77 +    }
    9.78 +    
    9.79 +    pool->ndata = 0;
    9.80 +    pool->size = n;
    9.81 +    
    9.82 +    UcxAllocator *allocator = (UcxAllocator*)malloc(sizeof(UcxAllocator));
    9.83 +    if(!allocator) {
    9.84 +        free(pool->data);
    9.85 +        free(pool);
    9.86 +        return NULL;
    9.87 +    }
    9.88 +    allocator->malloc = (ucx_allocator_malloc)ucx_mempool_malloc;
    9.89 +    allocator->calloc = (ucx_allocator_calloc)ucx_mempool_calloc;
    9.90 +    allocator->realloc = (ucx_allocator_realloc)ucx_mempool_realloc;
    9.91 +    allocator->free = (ucx_allocator_free)ucx_mempool_free;
    9.92 +    allocator->pool = pool;
    9.93 +    pool->allocator = allocator;
    9.94 +    
    9.95 +    return pool;
    9.96 +}
    9.97 +
    9.98 +int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) {
    9.99 +    if (newcap < pool->ndata) {
   9.100 +        return 1;
   9.101 +    }
   9.102 +    
   9.103 +    void **data = (void**) realloc(pool->data, newcap*sizeof(void*));
   9.104 +    if (data) {
   9.105 +        pool->data = data; 
   9.106 +        pool->size = newcap;
   9.107 +        return 0;
   9.108 +    } else {
   9.109 +        return 1;
   9.110 +    }
   9.111 +}
   9.112 +
   9.113 +void *ucx_mempool_malloc(UcxMempool *pool, size_t n) {
   9.114 +    if (pool->ndata >= pool->size) {
   9.115 +        size_t newcap = pool->size*2;
   9.116 +        if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) {
   9.117 +            return NULL;
   9.118 +        }
   9.119 +    }
   9.120 +
   9.121 +    void *p = malloc(sizeof(ucx_destructor) + n);
   9.122 +    ucx_memchunk *mem = (ucx_memchunk*)p;
   9.123 +    if (!mem) {
   9.124 +        return NULL;
   9.125 +    }
   9.126 +
   9.127 +    mem->destructor = NULL;
   9.128 +    pool->data[pool->ndata] = mem;
   9.129 +    pool->ndata++;
   9.130 +
   9.131 +    return &(mem->c);
   9.132 +}
   9.133 +
   9.134 +void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) {
   9.135 +    void *ptr = ucx_mempool_malloc(pool, nelem*elsize);
   9.136 +    if (!ptr) {
   9.137 +        return NULL;
   9.138 +    }
   9.139 +    memset(ptr, 0, nelem * elsize);
   9.140 +    return ptr;
   9.141 +}
   9.142 +
   9.143 +void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) {
   9.144 +    char *mem = ((char*)ptr) - sizeof(ucx_destructor);
   9.145 +    char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor));
   9.146 +    if (!newm) {
   9.147 +        return NULL;
   9.148 +    }
   9.149 +    if (mem != newm) {
   9.150 +        for(size_t i=0 ; i < pool->ndata ; i++) {
   9.151 +            if(pool->data[i] == mem) {
   9.152 +                pool->data[i] = newm;
   9.153 +                return newm + sizeof(ucx_destructor);
   9.154 +            }
   9.155 +        }
   9.156 +        fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
   9.157 +          (intptr_t)ptr, (intptr_t)pool);
   9.158 +        abort();
   9.159 +    } else {
   9.160 +        return newm + sizeof(ucx_destructor);
   9.161 +    }
   9.162 +}
   9.163 +
   9.164 +void ucx_mempool_free(UcxMempool *pool, void *ptr) {
   9.165 +    ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor));
   9.166 +    for(size_t i=0 ; i<pool->ndata ; i++) {
   9.167 +        if(chunk == pool->data[i]) {
   9.168 +            if(chunk->destructor != NULL) {
   9.169 +                chunk->destructor(&(chunk->c));
   9.170 +            }
   9.171 +            free(chunk);
   9.172 +            size_t last_index = pool->ndata - 1;
   9.173 +            if(i != last_index) {
   9.174 +                pool->data[i] = pool->data[last_index];
   9.175 +                pool->data[last_index] = NULL;
   9.176 +            }
   9.177 +            pool->ndata--;
   9.178 +            return;
   9.179 +        }
   9.180 +    }
   9.181 +    fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
   9.182 +            (intptr_t)ptr, (intptr_t)pool);
   9.183 +    abort();
   9.184 +}
   9.185 +
   9.186 +void ucx_mempool_destroy(UcxMempool *pool) {
   9.187 +    ucx_memchunk *chunk;
   9.188 +    for(size_t i=0 ; i<pool->ndata ; i++) {
   9.189 +        chunk = (ucx_memchunk*) pool->data[i];
   9.190 +        if(chunk) {
   9.191 +            if(chunk->destructor) {
   9.192 +                chunk->destructor(&(chunk->c));
   9.193 +            }
   9.194 +            free(chunk);
   9.195 +        }
   9.196 +    }
   9.197 +    free(pool->data);
   9.198 +    free(pool->allocator);
   9.199 +    free(pool);
   9.200 +}
   9.201 +
   9.202 +void ucx_mempool_set_destr(void *ptr, ucx_destructor func) {
   9.203 +    *(ucx_destructor*)((char*)ptr-sizeof(ucx_destructor)) = func;
   9.204 +}
   9.205 +
   9.206 +void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr) {
   9.207 +    ucx_regdestr *rd = (ucx_regdestr*)ucx_mempool_malloc(
   9.208 +            pool,
   9.209 +            sizeof(ucx_regdestr));
   9.210 +    rd->destructor = destr;
   9.211 +    rd->ptr = ptr;
   9.212 +    ucx_mempool_set_destr(rd, ucx_mempool_shared_destr);
   9.213 +}
   9.214 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/properties.c	Tue Oct 17 16:15:41 2017 +0200
    10.3 @@ -0,0 +1,264 @@
    10.4 +/*
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    10.8 + *
    10.9 + * Redistribution and use in source and binary forms, with or without
   10.10 + * modification, are permitted provided that the following conditions are met:
   10.11 + *
   10.12 + *   1. Redistributions of source code must retain the above copyright
   10.13 + *      notice, this list of conditions and the following disclaimer.
   10.14 + *
   10.15 + *   2. Redistributions in binary form must reproduce the above copyright
   10.16 + *      notice, this list of conditions and the following disclaimer in the
   10.17 + *      documentation and/or other materials provided with the distribution.
   10.18 + *
   10.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   10.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   10.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   10.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   10.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   10.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   10.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   10.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   10.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   10.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   10.29 + * POSSIBILITY OF SUCH DAMAGE.
   10.30 + */
   10.31 +
   10.32 +#include "ucx/properties.h"
   10.33 +
   10.34 +#include <stdio.h>
   10.35 +#include <stdlib.h>
   10.36 +#include <string.h>
   10.37 +
   10.38 +UcxProperties *ucx_properties_new() {
   10.39 +    UcxProperties *parser = (UcxProperties*)malloc(
   10.40 +            sizeof(UcxProperties));
   10.41 +    if(!parser) {
   10.42 +        return NULL;
   10.43 +    }
   10.44 +    
   10.45 +    parser->buffer = NULL;
   10.46 +    parser->buflen = 0;
   10.47 +    parser->pos = 0;
   10.48 +    parser->tmp = NULL;
   10.49 +    parser->tmplen = 0;
   10.50 +    parser->tmpcap = 0;
   10.51 +    parser->error = 0;
   10.52 +    parser->delimiter = '=';
   10.53 +    parser->comment1 = '#';
   10.54 +    parser->comment2 = 0;
   10.55 +    parser->comment3 = 0;   
   10.56 +    
   10.57 +    return parser;
   10.58 +}
   10.59 +
   10.60 +void ucx_properties_free(UcxProperties *parser) {
   10.61 +    if(parser->tmp) {
   10.62 +        free(parser->tmp);
   10.63 +    }
   10.64 +    free(parser);
   10.65 +}
   10.66 +
   10.67 +void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len) {
   10.68 +    parser->buffer = buf;
   10.69 +    parser->buflen = len;
   10.70 +    parser->pos = 0;
   10.71 +}
   10.72 +
   10.73 +static void parser_tmp_append(UcxProperties *parser, char *buf, size_t len) {
   10.74 +    if(parser->tmpcap - parser->tmplen < len) {
   10.75 +        size_t newcap = parser->tmpcap + len + 64;
   10.76 +        parser->tmp = (char*)realloc(parser->tmp, newcap);
   10.77 +        parser->tmpcap = newcap;
   10.78 +    }
   10.79 +    memcpy(parser->tmp + parser->tmplen, buf, len);
   10.80 +    parser->tmplen += len;
   10.81 +}
   10.82 +
   10.83 +int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value)  {   
   10.84 +    if(parser->tmplen > 0) {
   10.85 +        char *buf = parser->buffer + parser->pos;
   10.86 +        size_t len = parser->buflen - parser->pos;
   10.87 +        sstr_t str = sstrn(buf, len);
   10.88 +        sstr_t nl = sstrchr(str, '\n');
   10.89 +        if(nl.ptr) {
   10.90 +            size_t newlen = (size_t)(nl.ptr - buf) + 1;
   10.91 +            parser_tmp_append(parser, buf, newlen);
   10.92 +            // the tmp buffer contains exactly one line now
   10.93 +            
   10.94 +            char *orig_buf = parser->buffer;
   10.95 +            size_t orig_len = parser->buflen;
   10.96 +            
   10.97 +            parser->buffer = parser->tmp;
   10.98 +            parser->buflen = parser->tmplen;
   10.99 +            parser->pos = 0;    
  10.100 +            parser->tmp = NULL;
  10.101 +            parser->tmpcap = 0;
  10.102 +            parser->tmplen = 0;
  10.103 +            // run ucx_properties_next with the tmp buffer as main buffer
  10.104 +            int ret = ucx_properties_next(parser, name, value);
  10.105 +            
  10.106 +            // restore original buffer
  10.107 +            parser->tmp = parser->buffer;
  10.108 +            parser->buffer = orig_buf;
  10.109 +            parser->buflen = orig_len;
  10.110 +            parser->pos = newlen;
  10.111 +            
  10.112 +            /*
  10.113 +             * if ret == 0 the tmp buffer contained just space or a comment
  10.114 +             * we parse again with the original buffer to get a name/value
  10.115 +             * or a new tmp buffer
  10.116 +             */
  10.117 +            return ret ? ret : ucx_properties_next(parser, name, value);
  10.118 +        } else {
  10.119 +            parser_tmp_append(parser, buf, len);
  10.120 +            return 0;
  10.121 +        }
  10.122 +    } else if(parser->tmp) {
  10.123 +        free(parser->tmp);
  10.124 +        parser->tmp = NULL;
  10.125 +    }
  10.126 +    
  10.127 +    char comment1 = parser->comment1;
  10.128 +    char comment2 = parser->comment2;
  10.129 +    char comment3 = parser->comment3;
  10.130 +    char delimiter = parser->delimiter;
  10.131 +    
  10.132 +    // get one line and parse it
  10.133 +    while(parser->pos < parser->buflen) {
  10.134 +        char *buf = parser->buffer + parser->pos;
  10.135 +        size_t len = parser->buflen - parser->pos;
  10.136 +        
  10.137 +        /*
  10.138 +         * First we check if we have at least one line. We also get indices of
  10.139 +         * delimiter and comment chars
  10.140 +         */
  10.141 +        size_t delimiter_index = 0;
  10.142 +        size_t comment_index = 0;
  10.143 +        int has_comment = 0;
  10.144 +
  10.145 +        size_t i = 0;
  10.146 +        char c = 0;
  10.147 +        for(;i<len;i++) {
  10.148 +            c = buf[i];
  10.149 +            if(c == comment1 || c == comment2 || c == comment3) {
  10.150 +                if(comment_index == 0) {
  10.151 +                    comment_index = i;
  10.152 +                    has_comment = 1;
  10.153 +                }
  10.154 +            } else if(c == delimiter) {
  10.155 +                if(delimiter_index == 0 && !has_comment) {
  10.156 +                    delimiter_index = i;
  10.157 +                }
  10.158 +            } else if(c == '\n') {
  10.159 +                break;
  10.160 +            }
  10.161 +        }
  10.162 +
  10.163 +        if(c != '\n') {
  10.164 +            // we don't have enough data for a line
  10.165 +            // store remaining bytes in temporary buffer for next round
  10.166 +            parser->tmpcap = len + 128;
  10.167 +            parser->tmp = (char*)malloc(parser->tmpcap);
  10.168 +            parser->tmplen = len;
  10.169 +            memcpy(parser->tmp, buf, len);
  10.170 +            return 0;
  10.171 +        }
  10.172 +        
  10.173 +        sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i);
  10.174 +        // check line
  10.175 +        if(delimiter_index == 0) {
  10.176 +            line = sstrtrim(line);
  10.177 +            if(line.length != 0) {
  10.178 +                parser->error = 1;
  10.179 +            }
  10.180 +        } else {
  10.181 +            sstr_t n = sstrn(buf, delimiter_index);
  10.182 +            sstr_t v = sstrn(
  10.183 +                    buf + delimiter_index + 1,
  10.184 +                    line.length - delimiter_index - 1); 
  10.185 +            n = sstrtrim(n);
  10.186 +            v = sstrtrim(v);
  10.187 +            if(n.length != 0 || v.length != 0) {
  10.188 +                *name = n;
  10.189 +                *value = v;
  10.190 +                parser->pos += i + 1;
  10.191 +                return 1;
  10.192 +            } else {
  10.193 +                parser->error = 1;
  10.194 +            }
  10.195 +        }
  10.196 +        
  10.197 +        parser->pos += i + 1;
  10.198 +    }
  10.199 +    
  10.200 +    return 0;
  10.201 +}
  10.202 +
  10.203 +int ucx_properties2map(UcxProperties *parser, UcxMap *map) {
  10.204 +    sstr_t name;
  10.205 +    sstr_t value;
  10.206 +    while(ucx_properties_next(parser, &name, &value)) {
  10.207 +        value = sstrdup_a(map->allocator, value);
  10.208 +        if(!value.ptr) {
  10.209 +            return 1;
  10.210 +        }
  10.211 +        if(ucx_map_sstr_put(map, name, value.ptr)) {
  10.212 +            alfree(map->allocator, value.ptr);
  10.213 +            return 1;
  10.214 +        }
  10.215 +    }
  10.216 +    if (parser->error) {
  10.217 +        return parser->error;
  10.218 +    } else {
  10.219 +        return 0;
  10.220 +    }
  10.221 +}
  10.222 +
  10.223 +// buffer size is documented - change doc, when you change bufsize!
  10.224 +#define UCX_PROPLOAD_BUFSIZE  1024
  10.225 +int ucx_properties_load(UcxMap *map, FILE *file) {
  10.226 +    UcxProperties *parser = ucx_properties_new();
  10.227 +    if(!(parser && map && file)) {
  10.228 +        return 1;
  10.229 +    }
  10.230 +    
  10.231 +    int error = 0;
  10.232 +    size_t r;
  10.233 +    char buf[UCX_PROPLOAD_BUFSIZE];
  10.234 +    while((r = fread(buf, 1, UCX_PROPLOAD_BUFSIZE, file)) != 0) {
  10.235 +        ucx_properties_fill(parser, buf, r);
  10.236 +        error = ucx_properties2map(parser, map);
  10.237 +        if (error) {
  10.238 +            break;
  10.239 +        }
  10.240 +    }
  10.241 +    ucx_properties_free(parser);
  10.242 +    return error;
  10.243 +}
  10.244 +
  10.245 +int ucx_properties_store(UcxMap *map, FILE *file) {
  10.246 +    UcxMapIterator iter = ucx_map_iterator(map);
  10.247 +    void *v;
  10.248 +    sstr_t value;
  10.249 +    size_t written;
  10.250 +
  10.251 +    UCX_MAP_FOREACH(k, v, iter) {
  10.252 +        value = sstr((char*)v);
  10.253 +
  10.254 +        written = 0;
  10.255 +        written += fwrite(k.data, 1, k.len, file);
  10.256 +        written += fwrite(" = ", 1, 3, file);
  10.257 +        written += fwrite(value.ptr, 1, value.length, file);
  10.258 +        written += fwrite("\n", 1, 1, file);
  10.259 +
  10.260 +        if (written != k.len + value.length + 4) {
  10.261 +            return 1;
  10.262 +        }
  10.263 +    }
  10.264 +
  10.265 +    return 0;
  10.266 +}
  10.267 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/stack.c	Tue Oct 17 16:15:41 2017 +0200
    11.3 @@ -0,0 +1,144 @@
    11.4 +/*
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    11.8 + *
    11.9 + * Redistribution and use in source and binary forms, with or without
   11.10 + * modification, are permitted provided that the following conditions are met:
   11.11 + *
   11.12 + *   1. Redistributions of source code must retain the above copyright
   11.13 + *      notice, this list of conditions and the following disclaimer.
   11.14 + *
   11.15 + *   2. Redistributions in binary form must reproduce the above copyright
   11.16 + *      notice, this list of conditions and the following disclaimer in the
   11.17 + *      documentation and/or other materials provided with the distribution.
   11.18 + *
   11.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   11.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   11.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   11.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   11.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   11.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   11.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   11.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   11.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   11.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   11.29 + * POSSIBILITY OF SUCH DAMAGE.
   11.30 + */
   11.31 +
   11.32 +#include "ucx/stack.h"
   11.33 +
   11.34 +#include <string.h>
   11.35 +
   11.36 +static size_t ucx_stack_align(size_t n) {
   11.37 +    int align = n % sizeof(void*);
   11.38 +    if (align) {
   11.39 +        n += sizeof(void*) - align;
   11.40 +    }
   11.41 +    return n;
   11.42 +}
   11.43 +
   11.44 +void ucx_stack_init(UcxStack *stack, char* space, size_t size) {
   11.45 +    stack->size = size - size % sizeof(void*);
   11.46 +    stack->space = space;
   11.47 +    stack->top = NULL;
   11.48 +    
   11.49 +    stack->allocator.pool = stack;
   11.50 +    stack->allocator.malloc = (ucx_allocator_malloc) ucx_stack_malloc;
   11.51 +    stack->allocator.calloc = (ucx_allocator_calloc) ucx_stack_calloc;
   11.52 +    stack->allocator.realloc = (ucx_allocator_realloc) ucx_stack_realloc;
   11.53 +    stack->allocator.free = (ucx_allocator_free) ucx_stack_free;
   11.54 +}
   11.55 +
   11.56 +void *ucx_stack_malloc(UcxStack *stack, size_t n) {
   11.57 +
   11.58 +    if (ucx_stack_avail(stack) < ucx_stack_align(n)) {
   11.59 +        return NULL;
   11.60 +    } else {
   11.61 +        char *prev = stack->top;
   11.62 +        if (stack->top) {
   11.63 +            stack->top += ucx_stack_align(ucx_stack_topsize(stack));
   11.64 +        } else {
   11.65 +            stack->top = stack->space;
   11.66 +        }
   11.67 +        
   11.68 +        ((struct ucx_stack_metadata*)stack->top)->prev = prev;
   11.69 +        ((struct ucx_stack_metadata*)stack->top)->size = n;
   11.70 +        stack->top += sizeof(struct ucx_stack_metadata);
   11.71 +        
   11.72 +        return stack->top;
   11.73 +    }
   11.74 +}
   11.75 +
   11.76 +void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize) {
   11.77 +    void *mem = ucx_stack_malloc(stack, nelem*elsize);
   11.78 +    memset(mem, 0, nelem*elsize);
   11.79 +    return mem;
   11.80 +}
   11.81 +
   11.82 +void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) {
   11.83 +    if (ptr == stack->top) {
   11.84 +        if (stack->size - (stack->top - stack->space) < ucx_stack_align(n)) {
   11.85 +            return NULL;
   11.86 +        } else {
   11.87 +            ((struct ucx_stack_metadata*)stack->top - 1)->size = n;
   11.88 +            return ptr;
   11.89 +        }
   11.90 +    } else {
   11.91 +        if (ucx_stack_align(((struct ucx_stack_metadata*)ptr - 1)->size) <
   11.92 +                ucx_stack_align(n)) {
   11.93 +            void *nptr = ucx_stack_malloc(stack, n);
   11.94 +            if (nptr) {
   11.95 +                memcpy(nptr, ptr, n);
   11.96 +                ucx_stack_free(stack, ptr);
   11.97 +                
   11.98 +                return nptr;
   11.99 +            } else {
  11.100 +                return NULL;
  11.101 +            }
  11.102 +        } else {
  11.103 +            ((struct ucx_stack_metadata*)ptr - 1)->size = n;
  11.104 +            return ptr;
  11.105 +        }
  11.106 +    }
  11.107 +}
  11.108 +
  11.109 +void ucx_stack_free(UcxStack *stack, void *ptr) {
  11.110 +    if (ptr == stack->top) {
  11.111 +        stack->top = ((struct ucx_stack_metadata*) stack->top - 1)->prev;
  11.112 +    } else {
  11.113 +        struct ucx_stack_metadata *next = (struct ucx_stack_metadata*)(
  11.114 +            (char*)ptr +
  11.115 +            ucx_stack_align(((struct ucx_stack_metadata*) ptr - 1)->size)
  11.116 +        );
  11.117 +        next->prev = ((struct ucx_stack_metadata*) ptr - 1)->prev;
  11.118 +    }
  11.119 +}
  11.120 +
  11.121 +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) {
  11.122 +    if (ucx_stack_empty(stack)) {
  11.123 +        return;
  11.124 +    }
  11.125 +    
  11.126 +    size_t len = ucx_stack_topsize(stack);
  11.127 +    if (len > n) {
  11.128 +        len = n;
  11.129 +    }
  11.130 +    
  11.131 +    memcpy(dest, stack->top, len);
  11.132 +    
  11.133 +    ucx_stack_free(stack, stack->top);
  11.134 +}
  11.135 +
  11.136 +size_t ucx_stack_avail(UcxStack *stack) {
  11.137 +    size_t avail = ((stack->top ? (stack->size
  11.138 +                    - (stack->top - stack->space)
  11.139 +                    - ucx_stack_align(ucx_stack_topsize(stack)))
  11.140 +                    : stack->size));
  11.141 +    
  11.142 +    if (avail > sizeof(struct ucx_stack_metadata)) {
  11.143 +        return avail - sizeof(struct ucx_stack_metadata);
  11.144 +    } else {
  11.145 +        return 0;
  11.146 +    }
  11.147 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/string.c	Tue Oct 17 16:15:41 2017 +0200
    12.3 @@ -0,0 +1,463 @@
    12.4 +/*
    12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    12.6 + *
    12.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    12.8 + *
    12.9 + * Redistribution and use in source and binary forms, with or without
   12.10 + * modification, are permitted provided that the following conditions are met:
   12.11 + *
   12.12 + *   1. Redistributions of source code must retain the above copyright
   12.13 + *      notice, this list of conditions and the following disclaimer.
   12.14 + *
   12.15 + *   2. Redistributions in binary form must reproduce the above copyright
   12.16 + *      notice, this list of conditions and the following disclaimer in the
   12.17 + *      documentation and/or other materials provided with the distribution.
   12.18 + *
   12.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   12.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   12.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   12.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   12.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   12.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   12.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   12.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   12.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   12.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   12.29 + * POSSIBILITY OF SUCH DAMAGE.
   12.30 + */
   12.31 +
   12.32 +#include "ucx/string.h"
   12.33 +
   12.34 +#include "ucx/allocator.h"
   12.35 +
   12.36 +#include <stdlib.h>
   12.37 +#include <string.h>
   12.38 +#include <stdarg.h>
   12.39 +#include <stdint.h>
   12.40 +#include <ctype.h>
   12.41 +
   12.42 +sstr_t sstr(char *cstring) {
   12.43 +    sstr_t string;
   12.44 +    string.ptr = cstring;
   12.45 +    string.length = strlen(cstring);
   12.46 +    return string;
   12.47 +}
   12.48 +
   12.49 +sstr_t sstrn(char *cstring, size_t length) {
   12.50 +    sstr_t string;
   12.51 +    string.ptr = cstring;
   12.52 +    string.length = length;
   12.53 +    return string;
   12.54 +}
   12.55 +
   12.56 +size_t sstrnlen(size_t n, sstr_t s, ...) {
   12.57 +    va_list ap;
   12.58 +    size_t size = s.length;
   12.59 +    va_start(ap, s);
   12.60 +
   12.61 +    for (size_t i = 1 ; i < n ; i++) {
   12.62 +        sstr_t str = va_arg(ap, sstr_t);
   12.63 +        size += str.length;
   12.64 +    }
   12.65 +    va_end(ap);
   12.66 +
   12.67 +    return size;
   12.68 +}
   12.69 +
   12.70 +static sstr_t sstrvcat_a(
   12.71 +        UcxAllocator *a,
   12.72 +        size_t count,
   12.73 +        sstr_t s1,
   12.74 +        sstr_t s2,
   12.75 +        va_list ap) {
   12.76 +    sstr_t str;
   12.77 +    str.ptr = NULL;
   12.78 +    str.length = 0;
   12.79 +    if(count < 2) {
   12.80 +        return str;
   12.81 +    }
   12.82 +    
   12.83 +    sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t));
   12.84 +    if(!strings) {
   12.85 +        return str;
   12.86 +    }
   12.87 +    
   12.88 +    // get all args and overall length
   12.89 +    strings[0] = s1;
   12.90 +    strings[1] = s2;
   12.91 +    size_t strlen = s1.length + s2.length;
   12.92 +    for (size_t i=2;i<count;i++) {
   12.93 +        sstr_t s = va_arg (ap, sstr_t);
   12.94 +        strings[i] = s;
   12.95 +        strlen += s.length;
   12.96 +    }
   12.97 +    
   12.98 +    // create new string
   12.99 +    str.ptr = (char*) almalloc(a, strlen + 1);
  12.100 +    str.length = strlen;
  12.101 +    if(!str.ptr) {
  12.102 +        free(strings);
  12.103 +        str.length = 0;
  12.104 +        return str;
  12.105 +    }
  12.106 +    
  12.107 +    // concatenate strings
  12.108 +    size_t pos = 0;
  12.109 +    for (size_t i=0;i<count;i++) {
  12.110 +        sstr_t s = strings[i];
  12.111 +        memcpy(str.ptr + pos, s.ptr, s.length);
  12.112 +        pos += s.length;
  12.113 +    }
  12.114 +    
  12.115 +    str.ptr[str.length] = '\0';
  12.116 +    
  12.117 +    free(strings);
  12.118 +    
  12.119 +    return str;
  12.120 +}
  12.121 +
  12.122 +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) {
  12.123 +    va_list ap;
  12.124 +    va_start(ap, s2);
  12.125 +    sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap);
  12.126 +    va_end(ap);
  12.127 +    return s;
  12.128 +}
  12.129 +
  12.130 +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) {
  12.131 +    va_list ap;
  12.132 +    va_start(ap, s2);
  12.133 +    sstr_t s = sstrvcat_a(a, count, s1, s2, ap);
  12.134 +    va_end(ap);
  12.135 +    return s;
  12.136 +}
  12.137 +
  12.138 +sstr_t sstrsubs(sstr_t s, size_t start) {
  12.139 +    return sstrsubsl (s, start, s.length-start);
  12.140 +}
  12.141 +
  12.142 +sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) {
  12.143 +    sstr_t new_sstr;
  12.144 +    if (start >= s.length) {
  12.145 +        new_sstr.ptr = NULL;
  12.146 +        new_sstr.length = 0;
  12.147 +    } else {
  12.148 +        if (length > s.length-start) {
  12.149 +            length = s.length-start;
  12.150 +        }
  12.151 +        new_sstr.ptr = &s.ptr[start];
  12.152 +        new_sstr.length = length;
  12.153 +    }
  12.154 +    return new_sstr;
  12.155 +}
  12.156 +
  12.157 +sstr_t sstrchr(sstr_t s, int c) {
  12.158 +    for(size_t i=0;i<s.length;i++) {
  12.159 +        if(s.ptr[i] == c) {
  12.160 +            return sstrsubs(s, i);
  12.161 +        }
  12.162 +    }
  12.163 +    sstr_t n;
  12.164 +    n.ptr = NULL;
  12.165 +    n.length = 0;
  12.166 +    return n;
  12.167 +}
  12.168 +
  12.169 +sstr_t sstrrchr(sstr_t s, int c) {
  12.170 +    if (s.length > 0) {
  12.171 +        for(size_t i=s.length;i>0;i--) {
  12.172 +            if(s.ptr[i-1] == c) {
  12.173 +                return sstrsubs(s, i-1);
  12.174 +            }
  12.175 +        }
  12.176 +    }
  12.177 +    sstr_t n;
  12.178 +    n.ptr = NULL;
  12.179 +    n.length = 0;
  12.180 +    return n;
  12.181 +}
  12.182 +
  12.183 +#define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \
  12.184 +    ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index])
  12.185 +
  12.186 +#define ptable_w(useheap, ptable, index, src) do {\
  12.187 +    if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\
  12.188 +    else ((size_t*)ptable)[index] = src;\
  12.189 +    } while (0);
  12.190 +
  12.191 +sstr_t sstrstr(sstr_t string, sstr_t match) {
  12.192 +    if (match.length == 0) {
  12.193 +        return string;
  12.194 +    }
  12.195 +    
  12.196 +    /* prepare default return value in case of no match */
  12.197 +    sstr_t result = sstrn(NULL, 0);
  12.198 +    
  12.199 +    /*
  12.200 +     * IMPORTANT:
  12.201 +     * our prefix table contains the prefix length PLUS ONE
  12.202 +     * this is our decision, because we want to use the full range of size_t
  12.203 +     * the original algorithm needs a (-1) at one single place
  12.204 +     * and we want to avoid that
  12.205 +     */
  12.206 +    
  12.207 +    /* static prefix table */
  12.208 +    static uint8_t s_prefix_table[256];
  12.209 +    
  12.210 +    /* check pattern length and use appropriate prefix table */
  12.211 +    /* if the pattern exceeds static prefix table, allocate on the heap */
  12.212 +    register int useheap = match.length > 255;
  12.213 +    register void* ptable = useheap ?
  12.214 +        calloc(match.length+1, sizeof(size_t)): s_prefix_table;
  12.215 +    
  12.216 +    /* keep counter in registers */
  12.217 +    register size_t i, j;
  12.218 +    
  12.219 +    /* fill prefix table */
  12.220 +    i = 0; j = 0;
  12.221 +    ptable_w(useheap, ptable, i, j);
  12.222 +    while (i < match.length) {
  12.223 +        while (j >= 1 && match.ptr[j-1] != match.ptr[i]) {
  12.224 +            ptable_r(j, useheap, ptable, j-1);
  12.225 +        }
  12.226 +        i++; j++;
  12.227 +        ptable_w(useheap, ptable, i, j);
  12.228 +    }
  12.229 +
  12.230 +    /* search */
  12.231 +    i = 0; j = 1;
  12.232 +    while (i < string.length) {
  12.233 +        while (j >= 1 && string.ptr[i] != match.ptr[j-1]) {
  12.234 +            ptable_r(j, useheap, ptable, j-1);
  12.235 +        }
  12.236 +        i++; j++;
  12.237 +        if (j-1 == match.length) {
  12.238 +            size_t start = i - match.length;
  12.239 +            result.ptr = string.ptr + start;
  12.240 +            result.length = string.length - start;
  12.241 +            break;
  12.242 +        }
  12.243 +    }
  12.244 +
  12.245 +    /* if prefix table was allocated on the heap, free it */
  12.246 +    if (ptable != s_prefix_table) {
  12.247 +        free(ptable);
  12.248 +    }
  12.249 +    
  12.250 +    return result;
  12.251 +}
  12.252 +
  12.253 +#undef ptable_r
  12.254 +#undef ptable_w
  12.255 +
  12.256 +sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) {
  12.257 +    return sstrsplit_a(ucx_default_allocator(), s, d, n);
  12.258 +}
  12.259 +
  12.260 +sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) {
  12.261 +    if (s.length == 0 || d.length == 0) {
  12.262 +        *n = -1;
  12.263 +        return NULL;
  12.264 +    }
  12.265 +    
  12.266 +    /* special cases: delimiter is at least as large as the string */
  12.267 +    if (d.length >= s.length) {
  12.268 +        /* exact match */
  12.269 +        if (sstrcmp(s, d) == 0) {
  12.270 +            *n = 0;
  12.271 +            return NULL;
  12.272 +        } else /* no match possible */ {
  12.273 +            *n = 1;
  12.274 +            sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t));
  12.275 +            *result = sstrdup_a(allocator, s);
  12.276 +            return result;
  12.277 +        }
  12.278 +    }
  12.279 +    
  12.280 +    ssize_t nmax = *n;
  12.281 +    size_t arrlen = 16;
  12.282 +    sstr_t* result = (sstr_t*) almalloc(allocator, arrlen*sizeof(sstr_t));
  12.283 +
  12.284 +    if (result) {
  12.285 +        sstr_t curpos = s;
  12.286 +        ssize_t j = 1;
  12.287 +        while (1) {
  12.288 +            sstr_t match;
  12.289 +            /* optimize for one byte delimiters */
  12.290 +            if (d.length == 1) {
  12.291 +                match = curpos;
  12.292 +                for (size_t i = 0 ; i < curpos.length ; i++) {
  12.293 +                    if (curpos.ptr[i] == *(d.ptr)) {
  12.294 +                        match.ptr = curpos.ptr + i;
  12.295 +                        break;
  12.296 +                    }
  12.297 +                    match.length--;
  12.298 +                }
  12.299 +            } else {
  12.300 +                match = sstrstr(curpos, d);
  12.301 +            }
  12.302 +            if (match.length > 0) {
  12.303 +                /* is this our last try? */
  12.304 +                if (nmax == 0 || j < nmax) {
  12.305 +                    /* copy the current string to the array */
  12.306 +                    sstr_t item = sstrn(curpos.ptr, match.ptr - curpos.ptr);
  12.307 +                    result[j-1] = sstrdup_a(allocator, item);
  12.308 +                    size_t processed = item.length + d.length;
  12.309 +                    curpos.ptr += processed;
  12.310 +                    curpos.length -= processed;
  12.311 +
  12.312 +                    /* allocate memory for the next string */
  12.313 +                    j++;
  12.314 +                    if (j > arrlen) {
  12.315 +                        arrlen *= 2;
  12.316 +                        sstr_t* reallocated = (sstr_t*) alrealloc(
  12.317 +                                allocator, result, arrlen*sizeof(sstr_t));
  12.318 +                        if (reallocated) {
  12.319 +                            result = reallocated;
  12.320 +                        } else {
  12.321 +                            for (ssize_t i = 0 ; i < j-1 ; i++) {
  12.322 +                                alfree(allocator, result[i].ptr);
  12.323 +                            }
  12.324 +                            alfree(allocator, result);
  12.325 +                            *n = -2;
  12.326 +                            return NULL;
  12.327 +                        }
  12.328 +                    }
  12.329 +                } else {
  12.330 +                    /* nmax reached, copy the _full_ remaining string */
  12.331 +                    result[j-1] = sstrdup_a(allocator, curpos);
  12.332 +                    break;
  12.333 +                }
  12.334 +            } else {
  12.335 +                /* no more matches, copy last string */
  12.336 +                result[j-1] = sstrdup_a(allocator, curpos);
  12.337 +                break;
  12.338 +            }
  12.339 +        }
  12.340 +        *n = j;
  12.341 +    } else {
  12.342 +        *n = -2;
  12.343 +    }
  12.344 +
  12.345 +    return result;
  12.346 +}
  12.347 +
  12.348 +int sstrcmp(sstr_t s1, sstr_t s2) {
  12.349 +    if (s1.length == s2.length) {
  12.350 +        return memcmp(s1.ptr, s2.ptr, s1.length);
  12.351 +    } else if (s1.length > s2.length) {
  12.352 +        return 1;
  12.353 +    } else {
  12.354 +        return -1;
  12.355 +    }
  12.356 +}
  12.357 +
  12.358 +int sstrcasecmp(sstr_t s1, sstr_t s2) {
  12.359 +    if (s1.length == s2.length) {
  12.360 +#ifdef _WIN32
  12.361 +        return _strnicmp(s1.ptr, s2.ptr, s1.length);
  12.362 +#else
  12.363 +        return strncasecmp(s1.ptr, s2.ptr, s1.length);
  12.364 +#endif
  12.365 +    } else if (s1.length > s2.length) {
  12.366 +        return 1;
  12.367 +    } else {
  12.368 +        return -1;
  12.369 +    }
  12.370 +}
  12.371 +
  12.372 +sstr_t sstrdup(sstr_t s) {
  12.373 +    return sstrdup_a(ucx_default_allocator(), s);
  12.374 +}
  12.375 +
  12.376 +sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) {
  12.377 +    sstr_t newstring;
  12.378 +    newstring.ptr = (char*)almalloc(allocator, s.length + 1);
  12.379 +    if (newstring.ptr) {
  12.380 +        newstring.length = s.length;
  12.381 +        newstring.ptr[newstring.length] = 0;
  12.382 +        
  12.383 +        memcpy(newstring.ptr, s.ptr, s.length);
  12.384 +    } else {
  12.385 +        newstring.length = 0;
  12.386 +    }
  12.387 +    
  12.388 +    return newstring;
  12.389 +}
  12.390 +
  12.391 +sstr_t sstrtrim(sstr_t string) {
  12.392 +    sstr_t newstr = string;
  12.393 +    
  12.394 +    while (newstr.length > 0 && isspace(*newstr.ptr)) {
  12.395 +        newstr.ptr++;
  12.396 +        newstr.length--;
  12.397 +    }
  12.398 +    while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) {
  12.399 +        newstr.length--;
  12.400 +    }
  12.401 +    
  12.402 +    return newstr;
  12.403 +}
  12.404 +
  12.405 +int sstrprefix(sstr_t string, sstr_t prefix) {
  12.406 +    if (string.length == 0) {
  12.407 +        return prefix.length == 0;
  12.408 +    }
  12.409 +    if (prefix.length == 0) {
  12.410 +        return 1;
  12.411 +    }
  12.412 +    
  12.413 +    if (prefix.length > string.length) {
  12.414 +        return 0;
  12.415 +    } else {
  12.416 +        return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
  12.417 +    }
  12.418 +}
  12.419 +
  12.420 +int sstrsuffix(sstr_t string, sstr_t suffix) {
  12.421 +    if (string.length == 0) {
  12.422 +        return suffix.length == 0;
  12.423 +    }
  12.424 +    if (suffix.length == 0) {
  12.425 +        return 1;
  12.426 +    }
  12.427 +    
  12.428 +    if (suffix.length > string.length) {
  12.429 +        return 0;
  12.430 +    } else {
  12.431 +        return memcmp(string.ptr+string.length-suffix.length,
  12.432 +            suffix.ptr, suffix.length) == 0;
  12.433 +    }
  12.434 +}
  12.435 +
  12.436 +sstr_t sstrlower(sstr_t string) {
  12.437 +    sstr_t ret = sstrdup(string);
  12.438 +    for (size_t i = 0; i < ret.length ; i++) {
  12.439 +        ret.ptr[i] = tolower(ret.ptr[i]);
  12.440 +    }
  12.441 +    return ret;
  12.442 +}
  12.443 +
  12.444 +sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) {
  12.445 +    sstr_t ret = sstrdup_a(allocator, string);
  12.446 +    for (size_t i = 0; i < ret.length ; i++) {
  12.447 +        ret.ptr[i] = tolower(ret.ptr[i]);
  12.448 +    }
  12.449 +    return ret;
  12.450 +}
  12.451 +
  12.452 +sstr_t sstrupper(sstr_t string) {
  12.453 +    sstr_t ret = sstrdup(string);
  12.454 +    for (size_t i = 0; i < ret.length ; i++) {
  12.455 +        ret.ptr[i] = toupper(ret.ptr[i]);
  12.456 +    }
  12.457 +    return ret;
  12.458 +}
  12.459 +
  12.460 +sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) {
  12.461 +    sstr_t ret = sstrdup_a(allocator, string);
  12.462 +    for (size_t i = 0; i < ret.length ; i++) {
  12.463 +        ret.ptr[i] = toupper(ret.ptr[i]);
  12.464 +    }
  12.465 +    return ret;
  12.466 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/test.c	Tue Oct 17 16:15:41 2017 +0200
    13.3 @@ -0,0 +1,91 @@
    13.4 +/*
    13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    13.6 + *
    13.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    13.8 + *
    13.9 + * Redistribution and use in source and binary forms, with or without
   13.10 + * modification, are permitted provided that the following conditions are met:
   13.11 + *
   13.12 + *   1. Redistributions of source code must retain the above copyright
   13.13 + *      notice, this list of conditions and the following disclaimer.
   13.14 + *
   13.15 + *   2. Redistributions in binary form must reproduce the above copyright
   13.16 + *      notice, this list of conditions and the following disclaimer in the
   13.17 + *      documentation and/or other materials provided with the distribution.
   13.18 + *
   13.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   13.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   13.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   13.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   13.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   13.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   13.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   13.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   13.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   13.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   13.29 + * POSSIBILITY OF SUCH DAMAGE.
   13.30 + */
   13.31 +
   13.32 +#include "ucx/test.h"
   13.33 +
   13.34 +UcxTestSuite* ucx_test_suite_new() {
   13.35 +    UcxTestSuite* suite = (UcxTestSuite*) malloc(sizeof(UcxTestSuite));
   13.36 +    if (suite != NULL) {
   13.37 +        suite->success = 0;
   13.38 +        suite->failure = 0;
   13.39 +        suite->tests = NULL;
   13.40 +    }
   13.41 +
   13.42 +    return suite;
   13.43 +}
   13.44 +
   13.45 +void ucx_test_suite_free(UcxTestSuite* suite) {
   13.46 +    UcxTestList *l = suite->tests;
   13.47 +    while (l != NULL) {
   13.48 +        UcxTestList *e = l;
   13.49 +        l = l->next;
   13.50 +        free(e);
   13.51 +    }
   13.52 +    free(suite);
   13.53 +}
   13.54 +
   13.55 +int ucx_test_register(UcxTestSuite* suite, UcxTest test) {
   13.56 +    if (suite->tests) {
   13.57 +        UcxTestList *newelem = (UcxTestList*) malloc(sizeof(UcxTestList));
   13.58 +        if (newelem) {
   13.59 +            newelem->test = test;
   13.60 +            newelem->next = NULL;
   13.61 +            
   13.62 +            UcxTestList *last = suite->tests;
   13.63 +            while (last->next) {
   13.64 +                last = last->next;
   13.65 +            }
   13.66 +            last->next = newelem;
   13.67 +            
   13.68 +            return EXIT_SUCCESS;
   13.69 +        } else {
   13.70 +            return EXIT_FAILURE;
   13.71 +        }
   13.72 +    } else {
   13.73 +        suite->tests = (UcxTestList*) malloc(sizeof(UcxTestList));
   13.74 +        if (suite->tests) {
   13.75 +            suite->tests->test = test;
   13.76 +            suite->tests->next = NULL;
   13.77 +            
   13.78 +            return EXIT_SUCCESS;
   13.79 +        } else {
   13.80 +            return EXIT_FAILURE;
   13.81 +        }
   13.82 +    }
   13.83 +}
   13.84 +
   13.85 +void ucx_test_run(UcxTestSuite* suite, FILE* output) {
   13.86 +    suite->success = 0;
   13.87 +    suite->failure = 0;
   13.88 +    for (UcxTestList* elem = suite->tests ; elem ; elem = elem->next) {
   13.89 +        elem->test(suite, output);
   13.90 +    }
   13.91 +    fwrite("\nAll test completed.\n", 1, 21, output);
   13.92 +    fprintf(output, "  Total:   %u\n  Success: %u\n  Failure: %u\n",
   13.93 +            suite->success+suite->failure, suite->success, suite->failure);
   13.94 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/ucx.c	Tue Oct 17 16:15:41 2017 +0200
    14.3 @@ -0,0 +1,37 @@
    14.4 +/**
    14.5 + * @mainpage UAP Common Extensions
    14.6 + * Library with common and useful functions, macros and data structures.
    14.7 + * <p>
    14.8 + * Latest available source:<br/>
    14.9 + * <a href="https://develop.uap-core.de/hg/ucx">
   14.10 + * https://develop.uap-core.de/hg/ucx</a>
   14.11 + * </p>
   14.12 + * 
   14.13 + * <h2>LICENCE</h2>
   14.14 + * 
   14.15 + * Copyright 2017 Olaf Wintermann. All rights reserved.
   14.16 + *
   14.17 + * Redistribution and use in source and binary forms, with or without
   14.18 + * modification, are permitted provided that the following conditions are met:
   14.19 + *
   14.20 + *   1. Redistributions of source code must retain the above copyright
   14.21 + *      notice, this list of conditions and the following disclaimer.
   14.22 + *
   14.23 + *   2. Redistributions in binary form must reproduce the above copyright
   14.24 + *      notice, this list of conditions and the following disclaimer in the
   14.25 + *      documentation and/or other materials provided with the distribution.
   14.26 + *
   14.27 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   14.28 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   14.29 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   14.30 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   14.31 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   14.32 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   14.33 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   14.34 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   14.35 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   14.36 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   14.37 + * POSSIBILITY OF SUCH DAMAGE.
   14.38 + */
   14.39 +
   14.40 +#include "ucx/ucx.h"
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/ucx/allocator.h	Tue Oct 17 16:15:41 2017 +0200
    15.3 @@ -0,0 +1,206 @@
    15.4 +/*
    15.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    15.6 + *
    15.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    15.8 + *
    15.9 + * Redistribution and use in source and binary forms, with or without
   15.10 + * modification, are permitted provided that the following conditions are met:
   15.11 + *
   15.12 + *   1. Redistributions of source code must retain the above copyright
   15.13 + *      notice, this list of conditions and the following disclaimer.
   15.14 + *
   15.15 + *   2. Redistributions in binary form must reproduce the above copyright
   15.16 + *      notice, this list of conditions and the following disclaimer in the
   15.17 + *      documentation and/or other materials provided with the distribution.
   15.18 + *
   15.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   15.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   15.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   15.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   15.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   15.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   15.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   15.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   15.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   15.29 + * POSSIBILITY OF SUCH DAMAGE.
   15.30 + */
   15.31 +/**
   15.32 + * Allocator for custom memory management.
   15.33 + * 
   15.34 + * A UCX allocator consists of a pointer to the memory area / pool and four
   15.35 + * function pointers to memory management functions operating on this memory
   15.36 + * area / pool. These functions shall behave equivalent to the standard libc
   15.37 + * functions <code>malloc(), calloc(), realloc()</code> and <code>free()</code>.
   15.38 + * 
   15.39 + * The signature of the memory management functions is based on the signature
   15.40 + * of the respective libc function but each of them takes the pointer to the
   15.41 + * memory area / pool as first argument.
   15.42 + * 
   15.43 + * As the pointer to the memory area / pool can be arbitrarily chosen, any data
   15.44 + * can be provided to the memory management functions. A UcxMempool is just
   15.45 + * one example.
   15.46 + * 
   15.47 + * @see mempool.h
   15.48 + * @see UcxMap
   15.49 + * 
   15.50 + * @file   allocator.h
   15.51 + * @author Mike Becker
   15.52 + * @author Olaf Wintermann
   15.53 + */
   15.54 +
   15.55 +#ifndef UCX_ALLOCATOR_H
   15.56 +#define	UCX_ALLOCATOR_H
   15.57 +
   15.58 +#include <ucx/ucx.h>
   15.59 +
   15.60 +#ifdef	__cplusplus
   15.61 +extern "C" {
   15.62 +#endif
   15.63 +
   15.64 +/**
   15.65 + * A function pointer to the allocators <code>malloc()</code> function.
   15.66 + * @see UcxAllocator
   15.67 + */
   15.68 +typedef void*(*ucx_allocator_malloc)(void *pool, size_t n);
   15.69 +
   15.70 +/**
   15.71 + * A function pointer to the allocators <code>calloc()</code> function.
   15.72 + * @see UcxAllocator
   15.73 + */
   15.74 +typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size);
   15.75 +
   15.76 +/**
   15.77 + * A function pointer to the allocators <code>realloc()</code> function.
   15.78 + * @see UcxAllocator
   15.79 + */
   15.80 +typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n);
   15.81 +
   15.82 +/**
   15.83 + * A function pointer to the allocators <code>free()</code> function.
   15.84 + * @see UcxAllocator
   15.85 + */
   15.86 +typedef void(*ucx_allocator_free)(void *pool, void *data);
   15.87 +
   15.88 +/**
   15.89 + * UCX allocator data structure containing memory management functions.
   15.90 + */
   15.91 +typedef struct {
   15.92 +    /** Pointer to an area of memory or a complex memory pool.
   15.93 +     * This pointer will be passed to any memory management function as first
   15.94 +     * argument.
   15.95 +     */
   15.96 +    void *pool;
   15.97 +    /**
   15.98 +     * The <code>malloc()</code> function for this allocator.
   15.99 +     */
  15.100 +    ucx_allocator_malloc  malloc;
  15.101 +    /**
  15.102 +     * The <code>calloc()</code> function for this allocator.
  15.103 +     */
  15.104 +    ucx_allocator_calloc  calloc;
  15.105 +    /**
  15.106 +     * The <code>realloc()</code> function for this allocator.
  15.107 +     */
  15.108 +    ucx_allocator_realloc realloc;
  15.109 +    /**
  15.110 +     * The <code>free()</code> function for this allocator.
  15.111 +     */
  15.112 +    ucx_allocator_free    free;
  15.113 +} UcxAllocator;
  15.114 +
  15.115 +/**
  15.116 + * Returns a pointer to the default allocator.
  15.117 + * 
  15.118 + * The default allocator contains wrappers to the standard libc memory
  15.119 + * management functions. Use this function to get a pointer to a globally
  15.120 + * available allocator. You may also define an own UcxAllocator by assigning
  15.121 + * #UCX_ALLOCATOR_DEFAULT to a variable and pass the address of this variable
  15.122 + * to any function that takes a UcxAllocator as argument. Note that using
  15.123 + * this function is the recommended way of passing a default allocator, thus
  15.124 + * it never runs out of scope.
  15.125 + * 
  15.126 + * @return a pointer to the default allocator
  15.127 + * 
  15.128 + * @see UCX_ALLOCATOR_DEFAULT
  15.129 + */
  15.130 +UcxAllocator *ucx_default_allocator();
  15.131 +
  15.132 +/**
  15.133 + * A wrapper for the standard libc <code>malloc()</code> function.
  15.134 + * @param ignore ignored (may be used by allocators for pooled memory)
  15.135 + * @param n argument passed to <code>malloc()</code>
  15.136 + * @return return value of <code>malloc()</code>
  15.137 + */
  15.138 +void *ucx_default_malloc(void *ignore, size_t n);
  15.139 +/**
  15.140 + * A wrapper for the standard libc <code>calloc()</code> function.
  15.141 + * @param ignore ignored (may be used by allocators for pooled memory)
  15.142 + * @param n argument passed to <code>calloc()</code>
  15.143 + * @param size  argument passed to <code>calloc()</code>
  15.144 + * @return return value of <code>calloc()</code>
  15.145 + */
  15.146 +void *ucx_default_calloc(void *ignore, size_t n, size_t size);
  15.147 +/**
  15.148 + * A wrapper for the standard libc <code>realloc()</code> function.
  15.149 + * @param ignore ignored (may be used by allocators for pooled memory)
  15.150 + * @param data argumend passed to <code>realloc()</code>
  15.151 + * @param n argument passed to <code>realloc()</code>
  15.152 + * @return return value of <code>realloc()</code>
  15.153 + */
  15.154 +void *ucx_default_realloc(void *ignore, void *data, size_t n);
  15.155 +/**
  15.156 + * A wrapper for the standard libc <code>free()</code> function.
  15.157 + * @param ignore ignored (may be used by allocators for pooled memory)
  15.158 + * @param data argument passed to <code>free()</code>
  15.159 + */
  15.160 +void ucx_default_free(void *ignore, void *data);
  15.161 +
  15.162 +/**
  15.163 + * Shorthand for calling an allocators malloc function.
  15.164 + * @param allocator the allocator to use
  15.165 + * @param n size of space to allocate
  15.166 + * @return a pointer to the allocated memory area
  15.167 + */
  15.168 +#define almalloc(allocator, n) ((allocator)->malloc((allocator)->pool, n))
  15.169 +
  15.170 +/**
  15.171 + * Shorthand for calling an allocators calloc function.
  15.172 + * @param allocator the allocator to use
  15.173 + * @param n the count of elements the space should be allocated for
  15.174 + * @param size the size of each element
  15.175 + * @return a pointer to the allocated memory area
  15.176 + */
  15.177 +#define alcalloc(allocator, n, size) \
  15.178 +        ((allocator)->calloc((allocator)->pool, n, size))
  15.179 +
  15.180 +/**
  15.181 + * Shorthand for calling an allocators realloc function.
  15.182 + * @param allocator the allocator to use
  15.183 + * @param ptr the pointer to the memory area that shall be reallocated
  15.184 + * @param n the new size of the allocated memory area
  15.185 + * @return a pointer to the reallocated memory area
  15.186 + */
  15.187 +#define alrealloc(allocator, ptr, n) \
  15.188 +        ((allocator)->realloc((allocator)->pool, ptr, n))
  15.189 +
  15.190 +/**
  15.191 + * Shorthand for calling an allocators free function.
  15.192 + * @param allocator the allocator to use
  15.193 + * @param ptr the pointer to the memory area that shall be freed
  15.194 + */
  15.195 +#define alfree(allocator, ptr) ((allocator)->free((allocator)->pool, ptr))
  15.196 +
  15.197 +/**
  15.198 + * Convenient macro for a default allocator <code>struct</code> definition.
  15.199 + */
  15.200 +#define UCX_ALLOCATOR_DEFAULT {NULL, \
  15.201 +        ucx_default_malloc, ucx_default_calloc, ucx_default_realloc, \
  15.202 +        ucx_default_free }
  15.203 +
  15.204 +#ifdef	__cplusplus
  15.205 +}
  15.206 +#endif
  15.207 +
  15.208 +#endif	/* UCX_ALLOCATOR_H */
  15.209 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/ucx/avl.h	Tue Oct 17 16:15:41 2017 +0200
    16.3 @@ -0,0 +1,327 @@
    16.4 +/*
    16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    16.6 + *
    16.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    16.8 + *
    16.9 + * Redistribution and use in source and binary forms, with or without
   16.10 + * modification, are permitted provided that the following conditions are met:
   16.11 + *
   16.12 + *   1. Redistributions of source code must retain the above copyright
   16.13 + *      notice, this list of conditions and the following disclaimer.
   16.14 + *
   16.15 + *   2. Redistributions in binary form must reproduce the above copyright
   16.16 + *      notice, this list of conditions and the following disclaimer in the
   16.17 + *      documentation and/or other materials provided with the distribution.
   16.18 + *
   16.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   16.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   16.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   16.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   16.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   16.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   16.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   16.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   16.29 + * POSSIBILITY OF SUCH DAMAGE.
   16.30 + */
   16.31 +
   16.32 +
   16.33 +/**
   16.34 + * @file avl.h
   16.35 + * 
   16.36 + * AVL tree implementation.
   16.37 + * 
   16.38 + * This binary search tree implementation allows average O(1) insertion and
   16.39 + * removal of elements (excluding binary search time).
   16.40 + * 
   16.41 + * @author Mike Becker
   16.42 + * @author Olaf Wintermann
   16.43 + */
   16.44 +
   16.45 +#ifndef UCX_AVL_H
   16.46 +#define UCX_AVL_H
   16.47 +
   16.48 +#include <ucx/ucx.h>
   16.49 +#include <ucx/allocator.h>
   16.50 +#include <inttypes.h>
   16.51 +
   16.52 +#ifdef	__cplusplus
   16.53 +extern "C" {
   16.54 +#endif
   16.55 +
   16.56 +/**
   16.57 + * UCX AVL Node type.
   16.58 + * 
   16.59 + * @see UcxAVLNode
   16.60 + */
   16.61 +typedef struct UcxAVLNode UcxAVLNode;
   16.62 +
   16.63 +/**
   16.64 + * UCX AVL Node.
   16.65 + */
   16.66 +struct UcxAVLNode {
   16.67 +    /**
   16.68 +     * The key for this node.
   16.69 +     */
   16.70 +    intptr_t key;
   16.71 +    /**
   16.72 +     * Data contained by this node.
   16.73 +     */
   16.74 +    void *value;
   16.75 +    /**
   16.76 +     * The height of this (sub)-tree.
   16.77 +     */
   16.78 +    size_t height;
   16.79 +    /**
   16.80 +     * Parent node.
   16.81 +     */
   16.82 +    UcxAVLNode *parent;
   16.83 +    /**
   16.84 +     * Root node of left subtree.
   16.85 +     */
   16.86 +    UcxAVLNode *left;
   16.87 +    /**
   16.88 +     * Root node of right subtree.
   16.89 +     */
   16.90 +    UcxAVLNode *right;
   16.91 +};
   16.92 +
   16.93 +/**
   16.94 + * UCX AVL Tree.
   16.95 + */
   16.96 +typedef struct {
   16.97 +    /**
   16.98 +     * The UcxAllocator that shall be used to manage the memory for node data.
   16.99 +     */
  16.100 +    UcxAllocator *allocator;
  16.101 +    /**
  16.102 +     * Root node of the tree.
  16.103 +     */
  16.104 +    UcxAVLNode *root;
  16.105 +    /**
  16.106 +     * Compare function that shall be used to compare the UcxAVLNode keys.
  16.107 +     * @see UcxAVLNode.key
  16.108 +     */
  16.109 +    cmp_func cmpfunc;
  16.110 +    /**
  16.111 +     * Custom user data.
  16.112 +     * This data will also be provided to the cmpfunc.
  16.113 +     */
  16.114 +    void *userdata;
  16.115 +} UcxAVLTree;
  16.116 +
  16.117 +/**
  16.118 + * Initializes a new UcxAVLTree with a default allocator.
  16.119 + * 
  16.120 + * @param cmpfunc the compare function that shall be used
  16.121 + * @return a new UcxAVLTree object
  16.122 + * @see ucx_avl_new_a()
  16.123 + */
  16.124 +UcxAVLTree *ucx_avl_new(cmp_func cmpfunc);
  16.125 +
  16.126 +/**
  16.127 + * Initializes a new UcxAVLTree with the specified allocator.
  16.128 + * 
  16.129 + * The cmpfunc should be capable of comparing two keys within this AVL tree.
  16.130 + * So if you want to use null terminated strings as keys, you could use the
  16.131 + * ucx_strcmp() function here.
  16.132 + * 
  16.133 + * @param cmpfunc the compare function that shall be used
  16.134 + * @param allocator the UcxAllocator that shall be used
  16.135 + * @return a new UcxAVLTree object
  16.136 + */
  16.137 +UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator);
  16.138 +
  16.139 +/**
  16.140 + * Destroys a UcxAVLTree.
  16.141 + * @param tree the tree to destroy
  16.142 + */
  16.143 +void ucx_avl_free(UcxAVLTree *tree);
  16.144 +
  16.145 +/**
  16.146 + * Macro for initializing a new UcxAVLTree with the default allocator and a
  16.147 + * ucx_ptrcmp() compare function.
  16.148 + * 
  16.149 + * @return a new default UcxAVLTree object
  16.150 + */
  16.151 +#define ucx_avl_default_new() ucx_avl_new_a(ucx_ptrcmp, ucx_default_allocator())
  16.152 +
  16.153 +/**
  16.154 + * Gets the node from the tree, that is associated with the specified key.
  16.155 + * @param tree the UcxAVLTree
  16.156 + * @param key the key
  16.157 + * @return the node (or <code>NULL</code>, if the key is not present)
  16.158 + */
  16.159 +UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key);
  16.160 +
  16.161 +/**
  16.162 + * Gets the value from the tree, that is associated with the specified key.
  16.163 + * @param tree the UcxAVLTree
  16.164 + * @param key the key
  16.165 + * @return the value (or <code>NULL</code>, if the key is not present)
  16.166 + */
  16.167 +void *ucx_avl_get(UcxAVLTree *tree, intptr_t key);
  16.168 +
  16.169 +/**
  16.170 + * A mode for #ucx_avl_find_node() with the same behavior as
  16.171 + * #ucx_avl_get_node().
  16.172 + */
  16.173 +#define UCX_AVL_FIND_EXACT         0
  16.174 +/**
  16.175 + * A mode for #ucx_avl_find_node() finding the node whose key is at least
  16.176 + * as large as the specified key.
  16.177 + */
  16.178 +#define UCX_AVL_FIND_LOWER_BOUNDED 1
  16.179 +/**
  16.180 + * A mode for #ucx_avl_find_node() finding the node whose key is at most
  16.181 + * as large as the specified key.
  16.182 + */
  16.183 +#define UCX_AVL_FIND_UPPER_BOUNDED 2
  16.184 +/**
  16.185 + * A mode for #ucx_avl_find_node() finding the node with a key that is as close
  16.186 + * to the specified key as possible. If the key is present, the behavior is
  16.187 + * like #ucx_avl_get_node(). This mode only returns <code>NULL</code> on
  16.188 + * empty trees.
  16.189 + */
  16.190 +#define UCX_AVL_FIND_CLOSEST       3
  16.191 +
  16.192 +/**
  16.193 + * Finds a node within the tree. The following modes are supported:
  16.194 + * <ul>
  16.195 + * <li>#UCX_AVL_FIND_EXACT: the same behavior as #ucx_avl_get_node()</li>
  16.196 + * <li>#UCX_AVL_FIND_LOWER_BOUNDED: finds the node whose key is at least
  16.197 + * as large as the specified key</li>
  16.198 + * <li>#UCX_AVL_FIND_UPPER_BOUNDED: finds the node whose key is at most
  16.199 + * as large as the specified key</li>
  16.200 + * <li>#UCX_AVL_FIND_CLOSEST: finds the node with a key that is as close to
  16.201 + * the specified key as possible. If the key is present, the behavior is
  16.202 + * like #ucx_avl_get_node(). This mode only returns <code>NULL</code> on
  16.203 + * empty trees.</li> 
  16.204 + * </ul>
  16.205 + * 
  16.206 + * The distance function provided MUST agree with the compare function of
  16.207 + * the AVL tree.
  16.208 + * 
  16.209 + * @param tree the UcxAVLTree
  16.210 + * @param key the key
  16.211 + * @param dfnc the distance function
  16.212 + * @param mode the find mode
  16.213 + * @return the node (or <code>NULL</code>, if no node can be found)
  16.214 + */
  16.215 +UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key,
  16.216 +        distance_func dfnc, int mode);
  16.217 +
  16.218 +/**
  16.219 + * Finds a value within the tree.
  16.220 + * See #ucx_avl_find_node() for details.
  16.221 + * 
  16.222 + * @param tree the UcxAVLTree
  16.223 + * @param key the key
  16.224 + * @param dfnc the distance function
  16.225 + * @param mode the find mode
  16.226 + * @return the value (or <code>NULL</code>, if no value can be found)
  16.227 + */
  16.228 +void *ucx_avl_find(UcxAVLTree *tree, intptr_t key,
  16.229 +        distance_func dfnc, int mode);
  16.230 +
  16.231 +/**
  16.232 + * Puts a key/value pair into the tree.
  16.233 + * 
  16.234 + * Attention: use this function only, if a possible old value does not need
  16.235 + * to be preserved.
  16.236 + * 
  16.237 + * @param tree the UcxAVLTree
  16.238 + * @param key the key
  16.239 + * @param value the new value
  16.240 + * @return zero, if and only if the operation succeeded
  16.241 + */
  16.242 +int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value);
  16.243 +
  16.244 +/**
  16.245 + * Puts a key/value pair into the tree.
  16.246 + * 
  16.247 + * This is a secure function which saves the old value to the variable pointed
  16.248 + * at by oldvalue.
  16.249 + * 
  16.250 + * @param tree the UcxAVLTree
  16.251 + * @param key the key
  16.252 + * @param value the new value
  16.253 + * @param oldvalue optional: a pointer to the location where a possible old
  16.254 + * value shall be stored
  16.255 + * @return zero, if and only if the operation succeeded
  16.256 + */
  16.257 +int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value, void **oldvalue);
  16.258 +
  16.259 +/**
  16.260 + * Removes a node from the AVL tree.
  16.261 + * 
  16.262 + * Note: the specified node is logically removed. The tree implementation
  16.263 + * decides which memory area is freed. In most cases the here provided node
  16.264 + * is freed, so its further use is generally undefined.
  16.265 + * 
  16.266 + * @param tree the UcxAVLTree
  16.267 + * @param node the node to remove
  16.268 + * @return zero, if and only if an element has been removed
  16.269 + */
  16.270 +int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node);
  16.271 +
  16.272 +/**
  16.273 + * Removes an element from the AVL tree.
  16.274 + * 
  16.275 + * @param tree the UcxAVLTree
  16.276 + * @param key the key
  16.277 + * @return zero, if and only if an element has been removed
  16.278 + */
  16.279 +int ucx_avl_remove(UcxAVLTree *tree, intptr_t key);
  16.280 +
  16.281 +/**
  16.282 + * Removes an element from the AVL tree.
  16.283 + * 
  16.284 + * This is a secure function which saves the old key and value data from node
  16.285 + * to the variables at the location of oldkey and oldvalue (if specified), so
  16.286 + * they can be freed afterwards (if necessary).
  16.287 + * 
  16.288 + * Note: the returned key in oldkey is possibly not the same as the provided
  16.289 + * key for the lookup (in terms of memory location).
  16.290 + * 
  16.291 + * @param tree the UcxAVLTree
  16.292 + * @param key the key of the element to remove
  16.293 + * @param oldkey optional: a pointer to the location where the old key shall be
  16.294 + * stored
  16.295 + * @param oldvalue optional: a pointer to the location where the old value
  16.296 + * shall be stored
  16.297 + * @return zero, if and only if an element has been removed
  16.298 + */
  16.299 +int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key,
  16.300 +        intptr_t *oldkey, void **oldvalue);
  16.301 +
  16.302 +/**
  16.303 + * Counts the nodes in the specified UcxAVLTree.
  16.304 + * @param tree the AVL tree
  16.305 + * @return the node count
  16.306 + */
  16.307 +size_t ucx_avl_count(UcxAVLTree *tree);
  16.308 +
  16.309 +/**
  16.310 + * Finds the in-order predecessor of the given node.
  16.311 + * @param node an AVL node
  16.312 + * @return the in-order predecessor of the given node, or <code>NULL</code> if
  16.313 + * the given node is the in-order minimum
  16.314 + */
  16.315 +UcxAVLNode* ucx_avl_pred(UcxAVLNode* node);
  16.316 +
  16.317 +/**
  16.318 + * Finds the in-order successor of the given node.
  16.319 + * @param node an AVL node
  16.320 + * @return the in-order successor of the given node, or <code>NULL</code> if
  16.321 + * the given node is the in-order maximum
  16.322 + */
  16.323 +UcxAVLNode* ucx_avl_succ(UcxAVLNode* node);
  16.324 +
  16.325 +#ifdef	__cplusplus
  16.326 +}
  16.327 +#endif
  16.328 +
  16.329 +#endif	/* UCX_AVL_H */
  16.330 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/ucx/buffer.h	Tue Oct 17 16:15:41 2017 +0200
    17.3 @@ -0,0 +1,270 @@
    17.4 +/*
    17.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    17.6 + *
    17.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    17.8 + *
    17.9 + * Redistribution and use in source and binary forms, with or without
   17.10 + * modification, are permitted provided that the following conditions are met:
   17.11 + *
   17.12 + *   1. Redistributions of source code must retain the above copyright
   17.13 + *      notice, this list of conditions and the following disclaimer.
   17.14 + *
   17.15 + *   2. Redistributions in binary form must reproduce the above copyright
   17.16 + *      notice, this list of conditions and the following disclaimer in the
   17.17 + *      documentation and/or other materials provided with the distribution.
   17.18 + *
   17.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   17.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   17.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   17.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   17.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   17.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   17.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   17.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   17.29 + * POSSIBILITY OF SUCH DAMAGE.
   17.30 + */
   17.31 +
   17.32 +/**
   17.33 + * @file buffer.h
   17.34 + * 
   17.35 + * Advanced buffer implementation.
   17.36 + * 
   17.37 + * Instances of UcxBuffer can be used to read from or to write to like one
   17.38 + * would do with a stream. This allows the use of ucx_stream_copy() to copy
   17.39 + * contents from one buffer to another.
   17.40 + * 
   17.41 + * Some features for convenient use of the buffer
   17.42 + * can be enabled. See the documentation of the macro constants for more
   17.43 + * information.
   17.44 + * 
   17.45 + * @author Mike Becker
   17.46 + * @author Olaf Wintermann
   17.47 + */
   17.48 +
   17.49 +#ifndef UCX_BUFFER_H
   17.50 +#define	UCX_BUFFER_H
   17.51 +
   17.52 +#include <ucx/ucx.h>
   17.53 +#include <sys/types.h>
   17.54 +#include <stdio.h>
   17.55 +
   17.56 +#ifdef	__cplusplus
   17.57 +extern "C" {
   17.58 +#endif
   17.59 +
   17.60 +/**
   17.61 + * No buffer features enabled (all flags cleared).
   17.62 + */
   17.63 +#define UCX_BUFFER_DEFAULT      0x00
   17.64 +
   17.65 +/**
   17.66 + * If this flag is enabled, the buffer will automatically free its contents.
   17.67 + */
   17.68 +#define UCX_BUFFER_AUTOFREE     0x01
   17.69 +
   17.70 +/**
   17.71 + * If this flag is enabled, the buffer will automatically extends its capacity.
   17.72 + */
   17.73 +#define UCX_BUFFER_AUTOEXTEND   0x02
   17.74 +
   17.75 +/** UCX Buffer. */
   17.76 +typedef struct {
   17.77 +    /** A pointer to the buffer contents. */
   17.78 +    char *space;
   17.79 +    /** Current position of the buffer. */
   17.80 +    size_t pos;
   17.81 +    /** Current capacity (i.e. maximum size) of the buffer. */
   17.82 +    size_t capacity;
   17.83 +    /** Current size of the buffer content. */
   17.84 +    size_t size;
   17.85 +    /**
   17.86 +     * Flag register for buffer features.
   17.87 +     * @see #UCX_BUFFER_DEFAULT
   17.88 +     * @see #UCX_BUFFER_AUTOFREE
   17.89 +     * @see #UCX_BUFFER_AUTOEXTEND
   17.90 +     */
   17.91 +    int flags;
   17.92 +} UcxBuffer;
   17.93 +
   17.94 +/**
   17.95 + * Creates a new buffer.
   17.96 + * 
   17.97 + * <b>Note:</b> you may provide <code>NULL</code> as argument for
   17.98 + * <code>space</code>. Then this function will allocate the space and enforce
   17.99 + * the #UCX_BUFFER_AUTOFREE flag.
  17.100 + * 
  17.101 + * @param space pointer to the memory area, or <code>NULL</code> to allocate
  17.102 + * new memory
  17.103 + * @param capacity the capacity of the buffer
  17.104 + * @param flags buffer features (see UcxBuffer.flags)
  17.105 + * @return the new buffer
  17.106 + */
  17.107 +UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags);
  17.108 +
  17.109 +/**
  17.110 + * Destroys a buffer.
  17.111 + * 
  17.112 + * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer
  17.113 + * are also freed.
  17.114 + * 
  17.115 + * @param buffer the buffer to destroy
  17.116 + */
  17.117 +void ucx_buffer_free(UcxBuffer* buffer);
  17.118 +
  17.119 +/**
  17.120 + * Creates a new buffer and fills it with extracted content from another buffer.
  17.121 + * 
  17.122 + * <b>Note:</b> the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer.
  17.123 + * 
  17.124 + * @param src the source buffer
  17.125 + * @param start the start position of extraction
  17.126 + * @param length the count of bytes to extract (must not be zero)
  17.127 + * @param flags feature mask for the new buffer
  17.128 + * @return a new buffer containing the extraction
  17.129 + */
  17.130 +UcxBuffer* ucx_buffer_extract(UcxBuffer *src,
  17.131 +        size_t start, size_t length, int flags);
  17.132 +
  17.133 +/**
  17.134 + * A shorthand macro for the full extraction of the buffer.
  17.135 + * 
  17.136 + * @param src the source buffer
  17.137 + * @param flags feature mask for the new buffer
  17.138 + * @return a new buffer with the extracted content
  17.139 + */
  17.140 +#define ucx_buffer_clone(src,flags) \
  17.141 +    ucx_buffer_extract(src, 0, (src)->capacity, flags)
  17.142 +
  17.143 +/**
  17.144 + * Moves the position of the buffer.
  17.145 + * 
  17.146 + * The new position is relative to the <code>whence</code> argument.
  17.147 + *
  17.148 + * SEEK_SET marks the start of the buffer.
  17.149 + * SEEK_CUR marks the current position.
  17.150 + * SEEK_END marks the end of the buffer.
  17.151 + * 
  17.152 + * With an offset of zero, this function sets the buffer position to zero
  17.153 + * (SEEK_SET), the buffer size (SEEK_END) or leaves the buffer position
  17.154 + * unchanged (SEEK_CUR).
  17.155 + * 
  17.156 + * @param buffer
  17.157 + * @param offset position offset relative to <code>whence</code>
  17.158 + * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END
  17.159 + * @return 0 on success, non-zero if the position is invalid
  17.160 + *
  17.161 + */
  17.162 +int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence);
  17.163 +
  17.164 +/**
  17.165 + * Clears the buffer by resetting the position and deleting the data.
  17.166 + * 
  17.167 + * The data is deleted by a zeroing it with call to <code>memset()</code>.
  17.168 + * 
  17.169 + * @param buffer the buffer to be cleared
  17.170 + */
  17.171 +#define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \
  17.172 +        buffer->size = 0; buffer->pos = 0;
  17.173 +
  17.174 +/**
  17.175 + * Tests, if the buffer position has exceeded the buffer capacity.
  17.176 + * 
  17.177 + * @param buffer the buffer to test
  17.178 + * @return non-zero, if the current buffer position has exceeded the last
  17.179 + * available byte of the buffer.
  17.180 + */
  17.181 +int ucx_buffer_eof(UcxBuffer *buffer);
  17.182 +
  17.183 +
  17.184 +/**
  17.185 + * Extends the capacity of the buffer.
  17.186 + * 
  17.187 + * <b>Note:</b> The buffer capacity increased by a power of two. I.e.
  17.188 + * the buffer capacity is doubled, as long as it would not hold the current
  17.189 + * content plus the additional required bytes.
  17.190 + * 
  17.191 + * <b>Attention:</b> the argument provided is the number of <i>additional</i>
  17.192 + * bytes the buffer shall hold. It is <b>NOT</b> the total number of bytes the
  17.193 + * buffer shall hold.
  17.194 + * 
  17.195 + * @param buffer the buffer to extend
  17.196 + * @param additional_bytes the number of additional bytes the buffer shall
  17.197 + * <i>at least</i> hold
  17.198 + * @return 0 on success or a non-zero value on failure
  17.199 + */
  17.200 +int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes);
  17.201 +
  17.202 +/**
  17.203 + * Writes data to a UcxBuffer.
  17.204 + * 
  17.205 + * The position of the buffer is increased by the number of bytes written.
  17.206 + * 
  17.207 + * @param ptr a pointer to the memory area containing the bytes to be written
  17.208 + * @param size the length of one element
  17.209 + * @param nitems the element count
  17.210 + * @param buffer the UcxBuffer to write to
  17.211 + * @return the total count of bytes written
  17.212 + */
  17.213 +size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
  17.214 +        UcxBuffer *buffer);
  17.215 +
  17.216 +/**
  17.217 + * Reads data from a UcxBuffer.
  17.218 + * 
  17.219 + * The position of the buffer is increased by the number of bytes read.
  17.220 + * 
  17.221 + * @param ptr a pointer to the memory area where to store the read data
  17.222 + * @param size the length of one element
  17.223 + * @param nitems the element count
  17.224 + * @param buffer the UcxBuffer to read from
  17.225 + * @return the total number of elements read
  17.226 + */
  17.227 +size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
  17.228 +        UcxBuffer *buffer);
  17.229 +
  17.230 +/**
  17.231 + * Writes a character to a buffer.
  17.232 + * 
  17.233 + * The least significant byte of the argument is written to the buffer. If the
  17.234 + * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled,
  17.235 + * the buffer capacity is extended by ucx_buffer_extend(). If the feature is
  17.236 + * disabled or buffer extension fails, <code>EOF</code> is returned.
  17.237 + * 
  17.238 + * On successful write the position of the buffer is increased.
  17.239 + * 
  17.240 + * @param buffer the buffer to write to
  17.241 + * @param c the character to write as <code>int</code> value
  17.242 + * @return the byte that has bean written as <code>int</code> value or
  17.243 + * <code>EOF</code> when the end of the stream is reached and automatic
  17.244 + * extension is not enabled or not possible
  17.245 + */
  17.246 +int ucx_buffer_putc(UcxBuffer *buffer, int c);
  17.247 +
  17.248 +/**
  17.249 + * Gets a character from a buffer.
  17.250 + * 
  17.251 + * The current position of the buffer is increased after a successful read.
  17.252 + * 
  17.253 + * @param buffer the buffer to read from
  17.254 + * @return the character as <code>int</code> value or <code>EOF</code>, if the
  17.255 + * end of the buffer is reached
  17.256 + */
  17.257 +int ucx_buffer_getc(UcxBuffer *buffer);
  17.258 +
  17.259 +/**
  17.260 + * Writes a string to a buffer.
  17.261 + * 
  17.262 + * @param buffer the buffer
  17.263 + * @param str the string
  17.264 + * @return the number of bytes written
  17.265 + */
  17.266 +size_t ucx_buffer_puts(UcxBuffer *buffer, char *str);
  17.267 +
  17.268 +#ifdef	__cplusplus
  17.269 +}
  17.270 +#endif
  17.271 +
  17.272 +#endif	/* UCX_BUFFER_H */
  17.273 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/ucx/list.h	Tue Oct 17 16:15:41 2017 +0200
    18.3 @@ -0,0 +1,428 @@
    18.4 +/*
    18.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    18.6 + *
    18.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    18.8 + *
    18.9 + * Redistribution and use in source and binary forms, with or without
   18.10 + * modification, are permitted provided that the following conditions are met:
   18.11 + *
   18.12 + *   1. Redistributions of source code must retain the above copyright
   18.13 + *      notice, this list of conditions and the following disclaimer.
   18.14 + *
   18.15 + *   2. Redistributions in binary form must reproduce the above copyright
   18.16 + *      notice, this list of conditions and the following disclaimer in the
   18.17 + *      documentation and/or other materials provided with the distribution.
   18.18 + *
   18.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   18.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   18.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   18.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   18.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   18.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   18.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   18.29 + * POSSIBILITY OF SUCH DAMAGE.
   18.30 + */
   18.31 +/**
   18.32 + * Doubly linked list implementation.
   18.33 + * 
   18.34 + * @file   list.h
   18.35 + * @author Mike Becker
   18.36 + * @author Olaf Wintermann
   18.37 + */
   18.38 +
   18.39 +#ifndef UCX_LIST_H
   18.40 +#define	UCX_LIST_H
   18.41 +
   18.42 +#include <ucx/ucx.h>
   18.43 +#include <ucx/allocator.h>
   18.44 +
   18.45 +#ifdef	__cplusplus
   18.46 +extern "C" {
   18.47 +#endif
   18.48 +
   18.49 +/**
   18.50 + * Loop statement for UCX lists.
   18.51 + * 
   18.52 + * The first argument is the name of the iteration variable. The scope of
   18.53 + * this variable is limited to the <code>UCX_FOREACH</code> statement.
   18.54 + * 
   18.55 + * The second argument is a pointer to the list. In most cases this will be the
   18.56 + * pointer to the first element of the list, but it may also be an arbitrary
   18.57 + * element of the list. The iteration will then start with that element.
   18.58 + * 
   18.59 + * @param list The first element of the list
   18.60 + * @param elem The variable name of the element
   18.61 + */
   18.62 +#define UCX_FOREACH(elem,list) \
   18.63 +        for (UcxList* elem = list ; elem != NULL ; elem = elem->next)
   18.64 +
   18.65 +/**
   18.66 + * UCX list type.
   18.67 + * @see UcxList
   18.68 + */
   18.69 +typedef struct UcxList UcxList;
   18.70 +
   18.71 +/**
   18.72 + * UCX list structure.
   18.73 + */
   18.74 +struct UcxList {
   18.75 +    /**
   18.76 +     * List element payload.
   18.77 +     */
   18.78 +    void    *data;
   18.79 +    /**
   18.80 +     * Pointer to the next list element or <code>NULL</code>, if this is the
   18.81 +     * last element.
   18.82 +     */
   18.83 +    UcxList *next;
   18.84 +    /**
   18.85 +     * Pointer to the previous list element or <code>NULL</code>, if this is
   18.86 +     * the first element.
   18.87 +     */
   18.88 +    UcxList *prev;
   18.89 +};
   18.90 +
   18.91 +/**
   18.92 + * Creates an element-wise copy of a list.
   18.93 + * 
   18.94 + * This function clones the specified list by creating new list elements and
   18.95 + * copying the data with the specified copy_func(). If no copy_func() is
   18.96 + * specified, a shallow copy is created and the new list will reference the
   18.97 + * same data as the source list.
   18.98 + * 
   18.99 + * @param list the list to copy
  18.100 + * @param cpyfnc a pointer to the function that shall copy an element (may be
  18.101 + * <code>NULL</code>)
  18.102 + * @param data additional data for the copy_func()
  18.103 + * @return a pointer to the copy
  18.104 + */
  18.105 +UcxList *ucx_list_clone(UcxList *list, copy_func cpyfnc, void* data);
  18.106 +
  18.107 +/**
  18.108 + * Creates an element-wise copy of a list using a UcxAllocator.
  18.109 + * 
  18.110 + * See ucx_list_clone() for details.
  18.111 + * 
  18.112 + * You might want to pass the allocator via the <code>data</code> parameter,
  18.113 + * to access it within the copy function for making deep copies.
  18.114 + * 
  18.115 + * @param allocator the allocator to use
  18.116 + * @param list the list to copy
  18.117 + * @param cpyfnc a pointer to the function that shall copy an element (may be
  18.118 + * <code>NULL</code>)
  18.119 + * @param data additional data for the copy_func()
  18.120 + * @return a pointer to the copy
  18.121 + * @see ucx_list_clone()
  18.122 + */
  18.123 +UcxList *ucx_list_clone_a(UcxAllocator *allocator, UcxList *list,
  18.124 +        copy_func cpyfnc, void* data);
  18.125 +
  18.126 +/**
  18.127 + * Compares two UCX lists element-wise by using a compare function.
  18.128 + * 
  18.129 + * Each element of the two specified lists are compared by using the specified
  18.130 + * compare function and the additional data. The type and content of this
  18.131 + * additional data depends on the cmp_func() used.
  18.132 + * 
  18.133 + * If the list pointers denote elements within a list, the lists are compared
  18.134 + * starting with the denoted elements. Thus any previous elements are not taken
  18.135 + * into account. This might be useful to check, if certain list tails match
  18.136 + * each other.
  18.137 + * 
  18.138 + * @param list1 the first list
  18.139 + * @param list2 the second list
  18.140 + * @param cmpfnc the compare function
  18.141 + * @param data additional data for the compare function
  18.142 + * @return 1, if and only if the two lists equal element-wise, 0 otherwise
  18.143 + */
  18.144 +int ucx_list_equals(const UcxList *list1, const UcxList *list2,
  18.145 +        cmp_func cmpfnc, void* data);
  18.146 +
  18.147 +/**
  18.148 + * Destroys the entire list.
  18.149 + * 
  18.150 + * The members of the list are not automatically freed, so ensure they are
  18.151 + * otherwise referenced or destroyed by ucx_list_free_contents().
  18.152 + * Otherwise, a memory leak is likely to occur.
  18.153 + * 
  18.154 + * <b>Caution:</b> the argument <b>MUST</b> denote an entire list (i.e. a call
  18.155 + * to ucx_list_first() on the argument must return the argument itself)
  18.156 + * 
  18.157 + * @param list the list to free
  18.158 + * @see ucx_list_free_contents()
  18.159 + */
  18.160 +void ucx_list_free(UcxList *list);
  18.161 +
  18.162 +/**
  18.163 + * Destroys the entire list using a UcxAllocator.
  18.164 + * 
  18.165 + * See ucx_list_free() for details.
  18.166 + * 
  18.167 + * @param allocator the allocator to use
  18.168 + * @param list the list to free
  18.169 + * @see ucx_list_free()
  18.170 + */
  18.171 +void ucx_list_free_a(UcxAllocator *allocator, UcxList *list);
  18.172 +
  18.173 +/**
  18.174 + * Destroys the contents of the specified list by calling the specified
  18.175 + * destructor on each of them.
  18.176 + * 
  18.177 + * Note, that the contents are not usable afterwards and the list should be
  18.178 + * destroyed with ucx_list_free().
  18.179 + * 
  18.180 + * @param list the list for which the contents shall be freed
  18.181 + * @param destr the destructor function (e.g. stdlib free())
  18.182 + * @see ucx_list_free()
  18.183 + */
  18.184 +void ucx_list_free_content(UcxList* list, ucx_destructor destr);
  18.185 +
  18.186 +
  18.187 +/**
  18.188 + * Inserts an element at the end of the list.
  18.189 + * 
  18.190 + * This is generally an O(n) operation, as the end of the list is retrieved with
  18.191 + * ucx_list_last().
  18.192 + * 
  18.193 + * @param list the list where to append the data, or <code>NULL</code> to
  18.194 + * create a new list
  18.195 + * @param data the data to insert
  18.196 + * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  18.197 + * the newly created list otherwise
  18.198 + */
  18.199 +UcxList *ucx_list_append(UcxList *list, void *data);
  18.200 +
  18.201 +/**
  18.202 + * Inserts an element at the end of the list using a UcxAllocator.
  18.203 + * 
  18.204 + * See ucx_list_append() for details.
  18.205 + * 
  18.206 + * @param allocator the allocator to use
  18.207 + * @param list the list where to append the data, or <code>NULL</code> to
  18.208 + * create a new list
  18.209 + * @param data the data to insert
  18.210 + * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  18.211 + * the newly created list otherwise
  18.212 + * @see ucx_list_append()
  18.213 + */
  18.214 +UcxList *ucx_list_append_a(UcxAllocator *allocator, UcxList *list, void *data);
  18.215 +
  18.216 +/**
  18.217 + * Inserts an element at the end of the list, if it is not present in the list.
  18.218 + * 
  18.219 + * 
  18.220 + * @param list the list where to append the data, or <code>NULL</code> to
  18.221 + * create a new list
  18.222 + * @param data the data to insert
  18.223 + * @param cmpfnc the compare function
  18.224 + * @param cmpdata additional data for the compare function
  18.225 + * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  18.226 + * the newly created list otherwise
  18.227 + * @see ucx_list_append()
  18.228 + */
  18.229 +UcxList *ucx_list_append_once(UcxList *list, void *data,
  18.230 +        cmp_func cmpfnc, void *cmpdata);
  18.231 +
  18.232 +/**
  18.233 + * Inserts an element at the end of the list, if it is not present in the list,
  18.234 + * using a UcxAllocator.
  18.235 + * 
  18.236 + * See ucx_list_append() for details.
  18.237 + * 
  18.238 + * @param allocator the allocator to use
  18.239 + * @param list the list where to append the data, or <code>NULL</code> to
  18.240 + * create a new list
  18.241 + * @param data the data to insert
  18.242 + * @param cmpfnc the compare function
  18.243 + * @param cmpdata additional data for the compare function
  18.244 + * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  18.245 + * the newly created list otherwise
  18.246 + * @see ucx_list_append_a()
  18.247 + */
  18.248 +UcxList *ucx_list_append_once_a(UcxAllocator *allocator,
  18.249 +        UcxList *list, void *data, cmp_func cmpfnc, void *cmpdata);
  18.250 +
  18.251 +/**
  18.252 + * Inserts an element at the beginning of the list.
  18.253 + * 
  18.254 + * You <i>should</i> overwrite the old list pointer by calling
  18.255 + * <code>mylist = ucx_list_prepend(mylist, mydata);</code>. However, you may
  18.256 + * also perform successive calls of ucx_list_prepend() on the same list pointer,
  18.257 + * as this function always searchs for the head of the list with
  18.258 + * ucx_list_first().
  18.259 + * 
  18.260 + * @param list the list where to insert the data or <code>NULL</code> to create
  18.261 + * a new list
  18.262 + * @param data the data to insert
  18.263 + * @return a pointer to the new list head
  18.264 + */
  18.265 +UcxList *ucx_list_prepend(UcxList *list, void *data);
  18.266 +
  18.267 +/**
  18.268 + * Inserts an element at the beginning of the list using a UcxAllocator.
  18.269 + * 
  18.270 + * See ucx_list_prepend() for details.
  18.271 + * 
  18.272 + * @param allocator the allocator to use
  18.273 + * @param list the list where to insert the data or <code>NULL</code> to create
  18.274 + * a new list
  18.275 + * @param data the data to insert
  18.276 + * @return a pointer to the new list head
  18.277 + * @see ucx_list_prepend()
  18.278 + */
  18.279 +UcxList *ucx_list_prepend_a(UcxAllocator *allocator, UcxList *list, void *data);
  18.280 +
  18.281 +/**
  18.282 + * Concatenates two lists.
  18.283 + * 
  18.284 + * Either of the two arguments may be <code>NULL</code>.
  18.285 + * 
  18.286 + * This function modifies the references to the next/previous element of
  18.287 + * the last/first element of <code>list1</code>/<code>
  18.288 + * list2</code>.
  18.289 + * 
  18.290 + * @param list1 first list
  18.291 + * @param list2 second list
  18.292 + * @return if <code>list1</code> is <code>NULL</code>, <code>list2</code> is
  18.293 + * returned, otherwise <code>list1</code> is returned
  18.294 + */
  18.295 +UcxList *ucx_list_concat(UcxList *list1, UcxList *list2);
  18.296 +
  18.297 +/**
  18.298 + * Returns the first element of a list.
  18.299 + * 
  18.300 + * If the argument is the list pointer, it is directly returned. Otherwise
  18.301 + * this function traverses to the first element of the list and returns the
  18.302 + * list pointer.
  18.303 + * 
  18.304 + * @param elem one element of the list
  18.305 + * @return the first element of the list, the specified element is a member of
  18.306 + */
  18.307 +UcxList *ucx_list_first(const UcxList *elem);
  18.308 +
  18.309 +/**
  18.310 + * Returns the last element of a list.
  18.311 + * 
  18.312 + * If the argument has no successor, it is the last element and therefore
  18.313 + * directly returned. Otherwise this function traverses to the last element of
  18.314 + * the list and returns it.
  18.315 + * 
  18.316 + * @param elem one element of the list
  18.317 + * @return the last element of the list, the specified element is a member of
  18.318 + */
  18.319 +UcxList *ucx_list_last(const UcxList *elem);
  18.320 +
  18.321 +/**
  18.322 + * Returns the list element at the specified index.
  18.323 + * 
  18.324 + * @param list the list to retrieve the element from
  18.325 + * @param index index of the element to return
  18.326 + * @return the element at the specified index or <code>NULL</code>, if the
  18.327 + * index is greater than the list size
  18.328 + */
  18.329 +UcxList *ucx_list_get(const UcxList *list, size_t index);
  18.330 +
  18.331 +/**
  18.332 + * Returns the index of an element.
  18.333 + * 
  18.334 + * @param list the list where to search for the element
  18.335 + * @param elem the element to find
  18.336 + * @return the index of the element or -1 if the list does not contain the
  18.337 + * element
  18.338 + */
  18.339 +ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem);
  18.340 +
  18.341 +/**
  18.342 + * Returns the element count of the list.
  18.343 + * 
  18.344 + * @param list the list whose elements are counted
  18.345 + * @return the element count
  18.346 + */
  18.347 +size_t ucx_list_size(const UcxList *list);
  18.348 +
  18.349 +/**
  18.350 + * Returns the index of an element containing the specified data.
  18.351 + *
  18.352 + * This function uses a cmp_func() to compare the data of each list element
  18.353 + * with the specified data. If no cmp_func is provided, the pointers are
  18.354 + * compared.
  18.355 + * 
  18.356 + * If the list contains the data more than once, the index of the first
  18.357 + * occurrence is returned.
  18.358 + *  
  18.359 + * @param list the list where to search for the data
  18.360 + * @param elem the element data
  18.361 + * @param cmpfnc the compare function
  18.362 + * @param data additional data for the compare function
  18.363 + * @return the index of the element containing the specified data or -1 if the
  18.364 + * data is not found in this list
  18.365 + */
  18.366 +ssize_t ucx_list_find(UcxList *list, void *elem, cmp_func cmpfnc, void *data);
  18.367 +
  18.368 +/**
  18.369 + * Checks, if a list contains a specific element.
  18.370 + * 
  18.371 + * An element is found, if ucx_list_find() returns a value greater than -1.
  18.372 + * 
  18.373 + * @param list the list where to search for the data
  18.374 + * @param elem the element data
  18.375 + * @param cmpfnc the compare function
  18.376 + * @param data additional data for the compare function
  18.377 + * @return 1, if and only if the list contains the specified element data
  18.378 + * @see ucx_list_find()
  18.379 + */
  18.380 +int ucx_list_contains(UcxList *list, void *elem, cmp_func cmpfnc, void *data);
  18.381 +
  18.382 +/**
  18.383 + * Sorts a UcxList with natural merge sort.
  18.384 + * 
  18.385 + * This function uses O(n) additional temporary memory for merge operations
  18.386 + * that is automatically freed after each merge.
  18.387 + * 
  18.388 + * As the head of the list might change, you <b>MUST</b> call this function
  18.389 + * as follows: <code>mylist = ucx_list_sort(mylist, mycmpfnc, mydata);</code>.
  18.390 + * 
  18.391 + * @param list the list to sort
  18.392 + * @param cmpfnc the function that shall be used to compare the element data
  18.393 + * @param data additional data for the cmp_func()
  18.394 + * @return the sorted list
  18.395 + */
  18.396 +UcxList *ucx_list_sort(UcxList *list, cmp_func cmpfnc, void *data);
  18.397 +
  18.398 +/**
  18.399 + * Removes an element from the list.
  18.400 + * 
  18.401 + * If the first element is removed, the list pointer changes. So it is
  18.402 + * <i>highly recommended</i> to <i>always</i> update the pointer by calling
  18.403 + * <code>mylist = ucx_list_remove(mylist, myelem);</code>.
  18.404 + * 
  18.405 + * @param list the list from which the element shall be removed
  18.406 + * @param element the element to remove
  18.407 + * @return returns the updated list pointer or <code>NULL</code>, if the list
  18.408 + * is now empty
  18.409 + */
  18.410 +UcxList *ucx_list_remove(UcxList *list, UcxList *element);
  18.411 +
  18.412 +/**
  18.413 + * Removes an element from the list using a UcxAllocator.
  18.414 + * 
  18.415 + * See ucx_list_remove() for details.
  18.416 + * 
  18.417 + * @param allocator the allocator to use
  18.418 + * @param list the list from which the element shall be removed
  18.419 + * @param element the element to remove
  18.420 + * @return returns the updated list pointer or <code>NULL</code>, if the list
  18.421 + * @see ucx_list_remove()
  18.422 + */
  18.423 +UcxList *ucx_list_remove_a(UcxAllocator *allocator, UcxList *list,
  18.424 +        UcxList *element);
  18.425 +
  18.426 +#ifdef	__cplusplus
  18.427 +}
  18.428 +#endif
  18.429 +
  18.430 +#endif	/* UCX_LIST_H */
  18.431 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/ucx/logging.h	Tue Oct 17 16:15:41 2017 +0200
    19.3 @@ -0,0 +1,238 @@
    19.4 +/*
    19.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    19.6 + *
    19.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    19.8 + *
    19.9 + * Redistribution and use in source and binary forms, with or without
   19.10 + * modification, are permitted provided that the following conditions are met:
   19.11 + *
   19.12 + *   1. Redistributions of source code must retain the above copyright
   19.13 + *      notice, this list of conditions and the following disclaimer.
   19.14 + *
   19.15 + *   2. Redistributions in binary form must reproduce the above copyright
   19.16 + *      notice, this list of conditions and the following disclaimer in the
   19.17 + *      documentation and/or other materials provided with the distribution.
   19.18 + *
   19.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   19.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   19.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   19.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   19.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   19.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   19.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   19.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   19.29 + * POSSIBILITY OF SUCH DAMAGE.
   19.30 + */
   19.31 +/**
   19.32 + * Logging API.
   19.33 + * 
   19.34 + * @file   logging.h
   19.35 + * @author Mike Becker, Olaf Wintermann
   19.36 + */
   19.37 +#ifndef UCX_LOGGING_H
   19.38 +#define UCX_LOGGING_H
   19.39 +
   19.40 +#include <ucx/ucx.h>
   19.41 +#include <ucx/map.h>
   19.42 +#include <ucx/string.h>
   19.43 +#include <stdio.h>
   19.44 +
   19.45 +#ifdef __cplusplus
   19.46 +extern "C" {
   19.47 +#endif
   19.48 +
   19.49 +/* leave enough space for custom log levels */
   19.50 +
   19.51 +/** Log level for error messages. */
   19.52 +#define UCX_LOGGER_ERROR        0x00
   19.53 +    
   19.54 +/** Log level for warning messages. */
   19.55 +#define UCX_LOGGER_WARN         0x10
   19.56 +
   19.57 +/** Log level for information messages. */
   19.58 +#define UCX_LOGGER_INFO         0x20
   19.59 +
   19.60 +/** Log level for debug messages. */
   19.61 +#define UCX_LOGGER_DEBUG        0x30
   19.62 +
   19.63 +/** Log level for trace messages. */
   19.64 +#define UCX_LOGGER_TRACE        0x40
   19.65 +
   19.66 +/**
   19.67 + * Output flag for the log level. 
   19.68 + * If this flag is set, the log message will contain the log level.
   19.69 + * @see UcxLogger.mask
   19.70 + */
   19.71 +#define UCX_LOGGER_LEVEL        0x01
   19.72 +
   19.73 +/**
   19.74 + * Output flag for the timestmap.
   19.75 + * If this flag is set, the log message will contain the timestmap.
   19.76 + * @see UcxLogger.mask
   19.77 + */
   19.78 +#define UCX_LOGGER_TIMESTAMP    0x02
   19.79 +
   19.80 +/**
   19.81 + * Output flag for the source.
   19.82 + * If this flag is set, the log message will contain the source file and line
   19.83 + * number.
   19.84 + * @see UcxLogger.mask
   19.85 + */
   19.86 +#define UCX_LOGGER_SOURCE       0x04
   19.87 +
   19.88 +/**
   19.89 + * The UCX Logger object.
   19.90 + */
   19.91 +typedef struct {
   19.92 +    /** The stream this logger writes its messages to.*/
   19.93 +    void *stream;
   19.94 +
   19.95 +    /**
   19.96 +     * The write function that shall be used.
   19.97 +     * For standard file or stdout loggers this might be standard fwrite
   19.98 +     * (default).
   19.99 +     */
  19.100 +    write_func writer;
  19.101 +
  19.102 +    /**
  19.103 +     * The date format for timestamp outputs including the delimiter
  19.104 +     * (default: <code>"%F %T %z "</code>).
  19.105 +     * @see UCX_LOGGER_TIMESTAMP
  19.106 +     */
  19.107 +    char *dateformat;
  19.108 +
  19.109 +    /**
  19.110 +     * The level, this logger operates on.
  19.111 +     * If a log command is issued, the message will only be logged, if the log
  19.112 +     * level of the message is less or equal than the log level of the logger.
  19.113 +     */
  19.114 +    unsigned int level;
  19.115 +
  19.116 +    /**
  19.117 +     * A configuration mask for automatic output. 
  19.118 +     * For each flag that is set, the logger automatically outputs some extra
  19.119 +     * information like the timestamp or the source file and line number.
  19.120 +     * See the documentation for the flags for details.
  19.121 +     */
  19.122 +    unsigned int mask;
  19.123 +
  19.124 +    /**
  19.125 +     * A map of valid log levels for this logger.
  19.126 +     * 
  19.127 +     * The keys represent all valid log levels and the values provide string
  19.128 +     * representations, that are used, if the UCX_LOGGER_LEVEL flag is set.
  19.129 +     * 
  19.130 +     * The exact data types are <code>unsigned int</code> for the key and
  19.131 +     * <code>const char*</code> for the value.
  19.132 +     * 
  19.133 +     * @see UCX_LOGGER_LEVEL
  19.134 +     */
  19.135 +    UcxMap* levels;
  19.136 +} UcxLogger;
  19.137 +
  19.138 +/**
  19.139 + * Creates a new logger.
  19.140 + * @param stream the stream, which the logger shall write to
  19.141 + * @param level the level on which the logger shall operate
  19.142 + * @param mask configuration mask (cf. UcxLogger.mask)
  19.143 + * @return a new logger object
  19.144 + */
  19.145 +UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask);
  19.146 +
  19.147 +/**
  19.148 + * Destroys the logger.
  19.149 + * 
  19.150 + * The map containing the valid log levels is also automatically destroyed.
  19.151 + * 
  19.152 + * @param logger the logger to destroy
  19.153 + */
  19.154 +void ucx_logger_free(UcxLogger* logger);
  19.155 +
  19.156 +/**
  19.157 + * Internal log function - use macros instead.
  19.158 + * 
  19.159 + * This function uses the <code>format</code> and variadic arguments for a
  19.160 + * printf()-style output of the log message.
  19.161 + * 
  19.162 + * Dependent on the UcxLogger.mask some information is prepended. The complete
  19.163 + * format is:
  19.164 + * 
  19.165 + * <code>[LEVEL] [TIMESTAMP] [SOURCEFILE]:[LINENO] message</code>
  19.166 + * 
  19.167 + * <b>Attention:</b> the message (including automatically generated information)
  19.168 + * is limited to 4096 characters. The level description is limited to
  19.169 + * 256 characters and the timestamp string is limited to 128 characters.
  19.170 + * 
  19.171 + * @param logger the logger to use
  19.172 + * @param level the level to log on
  19.173 + * @param file information about the source file
  19.174 + * @param line information about the source line number
  19.175 + * @param format format string
  19.176 + * @param ... arguments
  19.177 + * @see ucx_logger_log()
  19.178 + */
  19.179 +void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
  19.180 +        const unsigned int line, const char* format, ...);
  19.181 +
  19.182 +/**
  19.183 + * Logs a message at the specified level.
  19.184 + * @param logger the logger to use
  19.185 + * @param level the level to log the message on
  19.186 + * @param ... format string and arguments
  19.187 + * @see ucx_logger_logf()
  19.188 + */
  19.189 +#define ucx_logger_log(logger, level, ...) \
  19.190 +    ucx_logger_logf(logger, level, __FILE__, __LINE__, __VA_ARGS__)
  19.191 +
  19.192 +/**
  19.193 + * Shortcut for logging an error message.
  19.194 + * @param logger the logger to use
  19.195 + * @param ... format string and arguments
  19.196 + * @see ucx_logger_logf()
  19.197 + */
  19.198 +#define ucx_logger_error(logger, ...) \
  19.199 +    ucx_logger_log(logger, UCX_LOGGER_ERROR, __VA_ARGS__)
  19.200 +
  19.201 +/**
  19.202 + * Shortcut for logging an information message.
  19.203 + * @param logger the logger to use
  19.204 + * @param ... format string and arguments
  19.205 + * @see ucx_logger_logf()
  19.206 + */
  19.207 +#define ucx_logger_info(logger, ...) \
  19.208 +    ucx_logger_log(logger, UCX_LOGGER_INFO, __VA_ARGS__)
  19.209 +
  19.210 +/**
  19.211 + * Shortcut for logging a warning message.
  19.212 + * @param logger the logger to use
  19.213 + * @param ... format string and arguments
  19.214 + * @see ucx_logger_logf()
  19.215 + */
  19.216 +#define ucx_logger_warn(logger, ...) \
  19.217 +    ucx_logger_log(logger, UCX_LOGGER_WARN, __VA_ARGS__)
  19.218 +
  19.219 +/**
  19.220 + * Shortcut for logging a debug message.
  19.221 + * @param logger the logger to use
  19.222 + * @param ... format string and arguments
  19.223 + * @see ucx_logger_logf()
  19.224 + */
  19.225 +#define ucx_logger_debug(logger, ...) \
  19.226 +    ucx_logger_log(logger, UCX_LOGGER_DEBUG, __VA_ARGS__)
  19.227 +
  19.228 +/**
  19.229 + * Shortcut for logging a trace message.
  19.230 + * @param logger the logger to use
  19.231 + * @param ... format string and arguments
  19.232 + * @see ucx_logger_logf()
  19.233 + */
  19.234 +#define ucx_logger_trace(logger, ...) \
  19.235 +    ucx_logger_log(logger, UCX_LOGGER_TRACE, __VA_ARGS__)
  19.236 +
  19.237 +#ifdef __cplusplus
  19.238 +}
  19.239 +#endif
  19.240 +
  19.241 +#endif /* UCX_LOGGING_H */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/ucx/map.h	Tue Oct 17 16:15:41 2017 +0200
    20.3 @@ -0,0 +1,423 @@
    20.4 +/*
    20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    20.6 + *
    20.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    20.8 + *
    20.9 + * Redistribution and use in source and binary forms, with or without
   20.10 + * modification, are permitted provided that the following conditions are met:
   20.11 + *
   20.12 + *   1. Redistributions of source code must retain the above copyright
   20.13 + *      notice, this list of conditions and the following disclaimer.
   20.14 + *
   20.15 + *   2. Redistributions in binary form must reproduce the above copyright
   20.16 + *      notice, this list of conditions and the following disclaimer in the
   20.17 + *      documentation and/or other materials provided with the distribution.
   20.18 + *
   20.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   20.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   20.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   20.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   20.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   20.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   20.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   20.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   20.29 + * POSSIBILITY OF SUCH DAMAGE.
   20.30 + */
   20.31 +
   20.32 +/**
   20.33 + * @file map.h
   20.34 + * 
   20.35 + * Hash map implementation.
   20.36 + * 
   20.37 + * This implementation uses murmur hash 2 and separate chaining with linked
   20.38 + * lists.
   20.39 + * 
   20.40 + * @author Mike Becker
   20.41 + * @author Olaf Wintermann
   20.42 + */
   20.43 +
   20.44 +#ifndef UCX_MAP_H
   20.45 +#define	UCX_MAP_H
   20.46 +
   20.47 +#include <ucx/ucx.h>
   20.48 +#include <ucx/string.h>
   20.49 +#include <ucx/allocator.h>
   20.50 +#include <stdio.h>
   20.51 +
   20.52 +#ifdef	__cplusplus
   20.53 +extern "C" {
   20.54 +#endif
   20.55 +
   20.56 +/**
   20.57 + * Loop statement for UCX maps.
   20.58 + * 
   20.59 + * The <code>key</code> variable is implicitly defined, but the
   20.60 + * <code>value</code> variable must be already declared as type information
   20.61 + * cannot be inferred.
   20.62 + * 
   20.63 + * @param key the variable name for the key
   20.64 + * @param value the variable name for the value
   20.65 + * @param iter a UcxMapIterator
   20.66 + * @see ucx_map_iterator()
   20.67 + */
   20.68 +#define UCX_MAP_FOREACH(key,value,iter) \
   20.69 +        for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&value);)
   20.70 +
   20.71 +/** Type for the UCX map. @see UcxMap */
   20.72 +typedef struct UcxMap          UcxMap;
   20.73 +
   20.74 +/** Type for a key of a UcxMap. @see UcxKey */
   20.75 +typedef struct UcxKey          UcxKey;
   20.76 +
   20.77 +/** Type for an element of a UcxMap. @see UcxMapElement */
   20.78 +typedef struct UcxMapElement   UcxMapElement;
   20.79 +
   20.80 +/** Type for an iterator over a UcxMap. @see UcxMapIterator */
   20.81 +typedef struct UcxMapIterator  UcxMapIterator;
   20.82 +
   20.83 +/** Structure for the UCX map. */
   20.84 +struct UcxMap {
   20.85 +    /** An allocator that is used for the map elements. */
   20.86 +    UcxAllocator  *allocator;
   20.87 +    /** The array of map element lists. */
   20.88 +    UcxMapElement **map;
   20.89 +    /** The size of the map is the length of the element list array. */
   20.90 +    size_t        size;
   20.91 +    /** The count of elements currently stored in this map. */
   20.92 +    size_t        count;
   20.93 +};
   20.94 +
   20.95 +/** Structure for a key of a UcxMap. */
   20.96 +struct UcxKey {
   20.97 +    /** The key data. */
   20.98 +    void   *data;
   20.99 +    /** The length of the key data. */
  20.100 +    size_t len;
  20.101 +    /** The hash value of the key data. */
  20.102 +    int    hash;
  20.103 +};
  20.104 +
  20.105 +/** Structure for an element of a UcxMap. */
  20.106 +struct UcxMapElement {
  20.107 +    /** The value data. */
  20.108 +    void          *data;
  20.109 +    
  20.110 +    /** A pointer to the next element in the current list. */
  20.111 +    UcxMapElement *next;
  20.112 +    
  20.113 +    /** The corresponding key. */
  20.114 +    UcxKey        key;
  20.115 +};
  20.116 +
  20.117 +/** Structure for an iterator over a UcxMap. */
  20.118 +struct UcxMapIterator {
  20.119 +    /** The map to iterate over. */
  20.120 +    UcxMap        *map;
  20.121 +    
  20.122 +    /** The current map element. */
  20.123 +    UcxMapElement *cur;
  20.124 +    
  20.125 +    /**
  20.126 +     * The current index of the element list array.
  20.127 +     * <b>Attention: </b> this is <b>NOT</b> the element index! Do <b>NOT</b>
  20.128 +     * manually iterate over the map by increasing this index. Use
  20.129 +     * ucx_map_iter_next().
  20.130 +     * @see UcxMap.map*/
  20.131 +    size_t        index;
  20.132 +};
  20.133 +
  20.134 +/**
  20.135 + * Creates a new hash map with the specified size.
  20.136 + * @param size the size of the hash map
  20.137 + * @return a pointer to the new hash map
  20.138 + */
  20.139 +UcxMap *ucx_map_new(size_t size);
  20.140 +
  20.141 +/**
  20.142 + * Creates a new hash map with the specified size using a UcxAllocator.
  20.143 + * @param allocator the allocator to use
  20.144 + * @param size the size of the hash map
  20.145 + * @return a pointer to the new hash map
  20.146 + */
  20.147 +UcxMap *ucx_map_new_a(UcxAllocator *allocator, size_t size);
  20.148 +
  20.149 +/**
  20.150 + * Frees a hash map.
  20.151 + * 
  20.152 + * <b>Note:</b> the contents are <b>not</b> freed, use ucx_map_free_content()
  20.153 + * before calling this function to achieve that.
  20.154 + * 
  20.155 + * @param map the map to be freed
  20.156 + * @see ucx_map_free_content()
  20.157 + */
  20.158 +void ucx_map_free(UcxMap *map);
  20.159 +
  20.160 +/**
  20.161 + * Frees the contents of a hash map.
  20.162 + * 
  20.163 + * This is a convenience function that iterates over the map and passes all
  20.164 + * values to the specified destructor function (e.g. stdlib free()).
  20.165 + * 
  20.166 + * You must ensure, that it is valid to pass each value in the map to the same
  20.167 + * destructor function.
  20.168 + * 
  20.169 + * You should free or clear the map afterwards, as the contents will be invalid.
  20.170 + * 
  20.171 + * @param map for which the contents shall be freed
  20.172 + * @param destr pointer to the destructor function
  20.173 + * @see ucx_map_free()
  20.174 + * @see ucx_map_clear()
  20.175 + */
  20.176 +void ucx_map_free_content(UcxMap *map, ucx_destructor destr);
  20.177 +
  20.178 +/**
  20.179 + * Clears a hash map.
  20.180 + * 
  20.181 + * <b>Note:</b> the contents are <b>not</b> freed, use ucx_map_free_content()
  20.182 + * before calling this function to achieve that.
  20.183 + * 
  20.184 + * @param map the map to be cleared
  20.185 + * @see ucx_map_free_content()
  20.186 + */
  20.187 +void ucx_map_clear(UcxMap *map);
  20.188 +
  20.189 +
  20.190 +/**
  20.191 + * Copies contents from a map to another map using a copy function.
  20.192 + * 
  20.193 + * <b>Note:</b> The destination map does not need to be empty. However, if it
  20.194 + * contains data with keys that are also present in the source map, the contents
  20.195 + * are overwritten.
  20.196 + * 
  20.197 + * @param from the source map
  20.198 + * @param to the destination map
  20.199 + * @param fnc the copy function or <code>NULL</code> if the pointer address
  20.200 + * shall be copied
  20.201 + * @param data additional data for the copy function
  20.202 + * @return 0 on success or a non-zero value on memory allocation errors
  20.203 + */
  20.204 +int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
  20.205 +        copy_func fnc, void *data);
  20.206 +
  20.207 +/**
  20.208 + * Clones the map and rehashes if necessary.
  20.209 + * 
  20.210 + * <b>Note:</b> In contrast to ucx_map_rehash() the load factor is irrelevant.
  20.211 + * This function <i>always</i> ensures a new UcxMap.size of at least
  20.212 + * 2.5*UcxMap.count.
  20.213 + * 
  20.214 + * @param map the map to clone
  20.215 + * @param fnc the copy function to use or <code>NULL</code> if the new and
  20.216 + * the old map shall share the data pointers
  20.217 + * @param data additional data for the copy function
  20.218 + * @return the cloned map
  20.219 + * @see ucx_map_copy()
  20.220 + */
  20.221 +UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data);
  20.222 +
  20.223 +/**
  20.224 + * Increases size of the hash map, if necessary.
  20.225 + * 
  20.226 + * The load value is 0.75*UcxMap.size. If the element count exceeds the load
  20.227 + * value, the map needs to be rehashed. Otherwise no action is performed and
  20.228 + * this function simply returns 0.
  20.229 + * 
  20.230 + * The rehashing process ensures, that the UcxMap.size is at least
  20.231 + * 2.5*UcxMap.count. So there is enough room for additional elements without
  20.232 + * the need of another soon rehashing.
  20.233 + * 
  20.234 + * You can use this function to dramatically increase access performance.
  20.235 + * 
  20.236 + * @param map the map to rehash
  20.237 + * @return 1, if a memory allocation error occurred, 0 otherwise
  20.238 + */
  20.239 +int ucx_map_rehash(UcxMap *map);
  20.240 +
  20.241 +/**
  20.242 + * Puts a key/value-pair into the map.
  20.243 + * 
  20.244 + * @param map the map
  20.245 + * @param key the key
  20.246 + * @param value the value
  20.247 + * @return 0 on success, non-zero value on failure
  20.248 + */
  20.249 +int ucx_map_put(UcxMap *map, UcxKey key, void *value);
  20.250 +
  20.251 +/**
  20.252 + * Retrieves a value by using a key.
  20.253 + * 
  20.254 + * @param map the map
  20.255 + * @param key the key
  20.256 + * @return the value
  20.257 + */
  20.258 +void* ucx_map_get(UcxMap *map, UcxKey key);
  20.259 +
  20.260 +/**
  20.261 + * Removes a key/value-pair from the map by using the key.
  20.262 + * 
  20.263 + * @param map the map
  20.264 + * @param key the key
  20.265 + * @return the removed value
  20.266 + */
  20.267 +void* ucx_map_remove(UcxMap *map, UcxKey key);
  20.268 +
  20.269 +/**
  20.270 + * Shorthand for putting data with a sstr_t key into the map.
  20.271 + * @param map the map
  20.272 + * @param key the key
  20.273 + * @param value the value
  20.274 + * @return 0 on success, non-zero value on failure
  20.275 + * @see ucx_map_put()
  20.276 + */
  20.277 +#define ucx_map_sstr_put(map, key, value) \
  20.278 +    ucx_map_put(map, ucx_key(key.ptr, key.length), (void*)value)
  20.279 +
  20.280 +/**
  20.281 + * Shorthand for putting data with a C string key into the map.
  20.282 + * @param map the map
  20.283 + * @param key the key
  20.284 + * @param value the value
  20.285 + * @return 0 on success, non-zero value on failure
  20.286 + * @see ucx_map_put()
  20.287 + */
  20.288 +#define ucx_map_cstr_put(map, key, value) \
  20.289 +    ucx_map_put(map, ucx_key((void*)key, strlen(key)), (void*)value)
  20.290 +
  20.291 +/**
  20.292 + * Shorthand for putting data with an integer key into the map.
  20.293 + * @param map the map
  20.294 + * @param key the key
  20.295 + * @param value the value
  20.296 + * @return 0 on success, non-zero value on failure
  20.297 + * @see ucx_map_put()
  20.298 + */
  20.299 +#define ucx_map_int_put(map, key, value) \
  20.300 +    ucx_map_put(map, ucx_key((void*)&key, sizeof(key)), (void*)value)
  20.301 +
  20.302 +/**
  20.303 + * Shorthand for getting data from the map with a sstr_t key.
  20.304 + * @param map the map
  20.305 + * @param key the key
  20.306 + * @return the value
  20.307 + * @see ucx_map_get()
  20.308 + */
  20.309 +#define ucx_map_sstr_get(map, key) \
  20.310 +    ucx_map_get(map, ucx_key(key.ptr, key.length))
  20.311 +
  20.312 +/**
  20.313 + * Shorthand for getting data from the map with a C string key.
  20.314 + * @param map the map
  20.315 + * @param key the key
  20.316 + * @return the value
  20.317 + * @see ucx_map_get()
  20.318 + */
  20.319 +#define ucx_map_cstr_get(map, key) \
  20.320 +    ucx_map_get(map, ucx_key((void*)key, strlen(key)))
  20.321 +
  20.322 +/**
  20.323 + * Shorthand for getting data from the map with an integer key.
  20.324 + * @param map the map
  20.325 + * @param key the key
  20.326 + * @return the value
  20.327 + * @see ucx_map_get()
  20.328 + */
  20.329 +#define ucx_map_int_get(map, key) \
  20.330 +    ucx_map_get(map, ucx_key((void*)&key, sizeof(int)))
  20.331 +
  20.332 +/**
  20.333 + * Shorthand for removing data from the map with a sstr_t key.
  20.334 + * @param map the map
  20.335 + * @param key the key
  20.336 + * @return the removed value
  20.337 + * @see ucx_map_remove()
  20.338 + */
  20.339 +#define ucx_map_sstr_remove(map, key) \
  20.340 +    ucx_map_remove(map, ucx_key(key.ptr, key.length))
  20.341 +
  20.342 +/**
  20.343 + * Shorthand for removing data from the map with a C string key.
  20.344 + * @param map the map
  20.345 + * @param key the key
  20.346 + * @return the removed value
  20.347 + * @see ucx_map_remove()
  20.348 + */
  20.349 +#define ucx_map_cstr_remove(map, key) \
  20.350 +    ucx_map_remove(map, ucx_key((void*)key, strlen(key)))
  20.351 +
  20.352 +/**
  20.353 + * Shorthand for removing data from the map with an integer key.
  20.354 + * @param map the map
  20.355 + * @param key the key
  20.356 + * @return the removed value
  20.357 + * @see ucx_map_remove()
  20.358 + */
  20.359 +#define ucx_map_int_remove(map, key) \
  20.360 +    ucx_map_remove(map, ucx_key((void*)&key, sizeof(key)))
  20.361 +
  20.362 +/**
  20.363 + * Creates a UcxKey based on the given data.
  20.364 + * 
  20.365 + * This function implicitly computes the hash.
  20.366 + * 
  20.367 + * @param data the data for the key
  20.368 + * @param len the length of the data
  20.369 + * @return a UcxKey with implicitly computed hash
  20.370 + * @see ucx_hash()
  20.371 + */
  20.372 +UcxKey ucx_key(void *data, size_t len);
  20.373 +
  20.374 +/**
  20.375 + * Computes a murmur hash-2.
  20.376 + * 
  20.377 + * @param data the data to hash
  20.378 + * @param len the length of the data
  20.379 + * @return the murmur hash-2 of the data
  20.380 + */
  20.381 +int ucx_hash(const char *data, size_t len);
  20.382 +
  20.383 +/**
  20.384 + * Creates an iterator for a map.
  20.385 + * 
  20.386 + * <b>Note:</b> A UcxMapIterator iterates over all elements in all element
  20.387 + * lists successively. Therefore the order highly depends on the key hashes and
  20.388 + * may vary under different map sizes. So generally you may <b>NOT</b> rely on
  20.389 + * the iteration order.
  20.390 + * 
  20.391 + * <b>Note:</b> The iterator is <b>NOT</b> initialized. You need to call
  20.392 + * ucx_map_iter_next() at least once before accessing any information. However,
  20.393 + * it is not recommended to access the fields of a UcxMapIterator directly.
  20.394 + * 
  20.395 + * @param map the map to create the iterator for
  20.396 + * @return an iterator initialized on the first element of the
  20.397 + * first element list
  20.398 + * @see ucx_map_iter_next()
  20.399 + */
  20.400 +UcxMapIterator ucx_map_iterator(UcxMap *map);
  20.401 +
  20.402 +/**
  20.403 + * Proceeds to the next element of the map (if any).
  20.404 + * 
  20.405 + * Subsequent calls on the same iterator proceed to the next element and
  20.406 + * store the key/value-pair into the memory specified as arguments of this
  20.407 + * function.
  20.408 + * 
  20.409 + * If no further elements are found, this function returns zero and leaves the
  20.410 + * last found key/value-pair in memory.
  20.411 + * 
  20.412 + * @param iterator the iterator to use
  20.413 + * @param key a pointer to the memory where to store the key
  20.414 + * @param value a pointer to the memory where to store the value
  20.415 + * @return 1, if another element was found, 0 if all elements has been processed
  20.416 + * @see ucx_map_iterator()
  20.417 + */
  20.418 +int ucx_map_iter_next(UcxMapIterator *iterator, UcxKey *key, void **value);
  20.419 +
  20.420 +
  20.421 +#ifdef	__cplusplus
  20.422 +}
  20.423 +#endif
  20.424 +
  20.425 +#endif	/* UCX_MAP_H */
  20.426 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/ucx/mempool.h	Tue Oct 17 16:15:41 2017 +0200
    21.3 @@ -0,0 +1,200 @@
    21.4 +/*
    21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    21.6 + *
    21.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    21.8 + *
    21.9 + * Redistribution and use in source and binary forms, with or without
   21.10 + * modification, are permitted provided that the following conditions are met:
   21.11 + *
   21.12 + *   1. Redistributions of source code must retain the above copyright
   21.13 + *      notice, this list of conditions and the following disclaimer.
   21.14 + *
   21.15 + *   2. Redistributions in binary form must reproduce the above copyright
   21.16 + *      notice, this list of conditions and the following disclaimer in the
   21.17 + *      documentation and/or other materials provided with the distribution.
   21.18 + *
   21.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   21.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   21.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   21.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   21.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   21.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   21.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   21.29 + * POSSIBILITY OF SUCH DAMAGE.
   21.30 + */
   21.31 +
   21.32 +/**
   21.33 + * @file mempool.h
   21.34 + * 
   21.35 + * Memory pool implementation.
   21.36 + * 
   21.37 + * @author Mike Becker
   21.38 + * @author Olaf Wintermann
   21.39 + */
   21.40 +
   21.41 +#ifndef UCX_MEMPOOL_H
   21.42 +#define	UCX_MEMPOOL_H
   21.43 +
   21.44 +#include <ucx/ucx.h>
   21.45 +#include <ucx/allocator.h>
   21.46 +#include <stddef.h>
   21.47 +
   21.48 +#ifdef	__cplusplus
   21.49 +extern "C" {
   21.50 +#endif
   21.51 +
   21.52 +/**
   21.53 + * UCX mempool structure.
   21.54 + */
   21.55 +typedef struct {
   21.56 +    /** UcxAllocator based on this pool */
   21.57 +    UcxAllocator *allocator;
   21.58 +    
   21.59 +    /** List of pointers to pooled memory. */
   21.60 +    void         **data;
   21.61 +    
   21.62 +    /** Count of pooled memory items. */
   21.63 +    size_t       ndata;
   21.64 +    
   21.65 +    /** Memory pool size. */
   21.66 +    size_t       size;
   21.67 +} UcxMempool;
   21.68 +
   21.69 +/** Shorthand for a new default memory pool with a capacity of 16 elements. */
   21.70 +#define ucx_mempool_new_default() ucx_mempool_new(16)
   21.71 +
   21.72 +
   21.73 +/**
   21.74 + * Creates a memory pool with the specified initial size.
   21.75 + * 
   21.76 + * As the created memory pool automatically grows in size by factor two when
   21.77 + * trying to allocate memory on a full pool, it is recommended that you use
   21.78 + * a power of two for the initial size.
   21.79 + * 
   21.80 + * @param n initial pool size (should be a power of two, e.g. 16)
   21.81 + * @return a pointer to the new memory pool
   21.82 + * @see ucx_mempool_new_default()
   21.83 + */
   21.84 +UcxMempool *ucx_mempool_new(size_t n);
   21.85 +
   21.86 +/**
   21.87 + * Resizes a memory pool.
   21.88 + * 
   21.89 + * This function will fail if the new capacity is not sufficient for the
   21.90 + * present data.
   21.91 + * 
   21.92 + * @param pool the pool to resize
   21.93 + * @param newcap the new capacity
   21.94 + * @return zero on success or non-zero on failure
   21.95 + */
   21.96 +int ucx_mempool_chcap(UcxMempool *pool, size_t newcap);
   21.97 +
   21.98 +/**
   21.99 + * Allocates pooled memory.
  21.100 + * 
  21.101 + * @param pool the memory pool
  21.102 + * @param n amount of memory to allocate
  21.103 + * @return a pointer to the allocated memory
  21.104 + * @see ucx_allocator_malloc()
  21.105 + */
  21.106 +void *ucx_mempool_malloc(UcxMempool *pool, size_t n);
  21.107 +/**
  21.108 + * Allocates a pooled memory array.
  21.109 + * 
  21.110 + * The content of the allocated memory is set to zero.
  21.111 + * 
  21.112 + * @param pool the memory pool
  21.113 + * @param nelem amount of elements to allocate
  21.114 + * @param elsize amount of memory per element
  21.115 + * @return a pointer to the allocated memory
  21.116 + * @see ucx_allocator_calloc()
  21.117 + */
  21.118 +void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize);
  21.119 +
  21.120 +/**
  21.121 + * Reallocates pooled memory.
  21.122 + * 
  21.123 + * If the memory to be reallocated is not contained by the specified pool, the
  21.124 + * behavior is undefined.
  21.125 + * 
  21.126 + * @param pool the memory pool
  21.127 + * @param ptr a pointer to the memory that shall be reallocated
  21.128 + * @param n the new size of the memory
  21.129 + * @return a pointer to the new location of the memory
  21.130 + * @see ucx_allocator_realloc()
  21.131 + */
  21.132 +void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n);
  21.133 +
  21.134 +/**
  21.135 + * Frees pooled memory.
  21.136 + * 
  21.137 + * Before freeing the memory, the specified destructor function (if any)
  21.138 + * is called.
  21.139 + * 
  21.140 + * If you specify memory, that is not pooled by the specified memory pool, the
  21.141 + * program will terminate with a call to <code>abort()</code>.
  21.142 + * 
  21.143 + * @param pool the memory pool
  21.144 + * @param ptr a pointer to the memory that shall be freed
  21.145 + * @see ucx_mempool_set_destr()
  21.146 + */
  21.147 +void ucx_mempool_free(UcxMempool *pool, void *ptr);
  21.148 +
  21.149 +/**
  21.150 + * Destroys a memory pool.
  21.151 + * 
  21.152 + * For each element the destructor function (if any) is called and the element
  21.153 + * is freed.
  21.154 + * 
  21.155 + * Each of the registered destructor function that has no corresponding element
  21.156 + * within the pool (namely those registered by ucx_mempool_reg_destr) is
  21.157 + * called interleaving with the element destruction, but with guarantee to the
  21.158 + * order in which they were registered (FIFO order).
  21.159 + * 
  21.160 + * 
  21.161 + * @param pool the mempool to destroy
  21.162 + */
  21.163 +void ucx_mempool_destroy(UcxMempool *pool);
  21.164 +
  21.165 +/**
  21.166 + * Sets a destructor function for the specified memory.
  21.167 + * 
  21.168 + * The destructor is automatically called when the memory is freed or the
  21.169 + * pool is destroyed.
  21.170 + * 
  21.171 + * The only requirement for the specified memory is, that it <b>MUST</b> be
  21.172 + * pooled memory by a UcxMempool or an element-compatible mempool. The pointer
  21.173 + * to the destructor function is saved in a reserved area before the actual
  21.174 + * memory.
  21.175 + * 
  21.176 + * @param ptr pooled memory
  21.177 + * @param func a pointer to the destructor function
  21.178 + * @see ucx_mempool_free()
  21.179 + * @see ucx_mempool_destroy()
  21.180 + */
  21.181 +void ucx_mempool_set_destr(void *ptr, ucx_destructor func);
  21.182 +
  21.183 +/**
  21.184 + * Registers a destructor function for the specified (non-pooled) memory.
  21.185 + * 
  21.186 + * This is useful, if you have memory that has not been allocated by a mempool,
  21.187 + * but shall be managed by a mempool.
  21.188 + * 
  21.189 + * This function creates an entry in the specified mempool and the memory will
  21.190 + * therefore (logically) convert to pooled memory.
  21.191 + * 
  21.192 + * @param pool the memory pool
  21.193 + * @param ptr data the destructor is registered for
  21.194 + * @param destr a pointer to the destructor function
  21.195 + */
  21.196 +void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr);
  21.197 +
  21.198 +#ifdef	__cplusplus
  21.199 +}
  21.200 +#endif
  21.201 +
  21.202 +#endif	/* UCX_MEMPOOL_H */
  21.203 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/src/ucx/properties.h	Tue Oct 17 16:15:41 2017 +0200
    22.3 @@ -0,0 +1,218 @@
    22.4 +/*
    22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    22.6 + *
    22.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    22.8 + *
    22.9 + * Redistribution and use in source and binary forms, with or without
   22.10 + * modification, are permitted provided that the following conditions are met:
   22.11 + *
   22.12 + *   1. Redistributions of source code must retain the above copyright
   22.13 + *      notice, this list of conditions and the following disclaimer.
   22.14 + *
   22.15 + *   2. Redistributions in binary form must reproduce the above copyright
   22.16 + *      notice, this list of conditions and the following disclaimer in the
   22.17 + *      documentation and/or other materials provided with the distribution.
   22.18 + *
   22.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   22.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   22.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   22.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   22.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   22.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   22.29 + * POSSIBILITY OF SUCH DAMAGE.
   22.30 + */
   22.31 +/**
   22.32 + * @file properties.h
   22.33 + * 
   22.34 + * Load / store utilities for properties files.
   22.35 + * 
   22.36 + * @author Mike Becker
   22.37 + * @author Olaf Wintermann
   22.38 + */
   22.39 +
   22.40 +#ifndef UCX_PROPERTIES_H
   22.41 +#define	UCX_PROPERTIES_H
   22.42 +
   22.43 +#include <ucx/ucx.h>
   22.44 +#include <ucx/map.h>
   22.45 +
   22.46 +#ifdef	__cplusplus
   22.47 +extern "C" {
   22.48 +#endif
   22.49 +
   22.50 +/**
   22.51 + * UcxProperties object for parsing properties data.
   22.52 + * Most of the fields are for internal use only. You may configure the
   22.53 + * properties parser, e.g. by changing the used delimiter or specifying 
   22.54 + * up to three different characters that shall introduce comments.
   22.55 + */
   22.56 +typedef struct {
   22.57 +    /**
   22.58 +     * Input buffer (don't set manually).
   22.59 +     * Automatically set by calls to ucx_properties_fill().
   22.60 +     */
   22.61 +    char   *buffer;
   22.62 +    
   22.63 +    /**
   22.64 +     * Length of the input buffer (don't set manually).
   22.65 +     * Automatically set by calls to ucx_properties_fill().
   22.66 +     */
   22.67 +    size_t buflen;
   22.68 +    
   22.69 +    /**
   22.70 +     * Current buffer position (don't set manually).
   22.71 +     * Used by ucx_properties_next().
   22.72 +     */
   22.73 +    size_t pos;
   22.74 +    
   22.75 +    /**
   22.76 +     * Internal temporary buffer (don't set manually).
   22.77 +     * Used by ucx_properties_next().
   22.78 +     */
   22.79 +    char   *tmp;
   22.80 +    
   22.81 +    /**
   22.82 +     * Internal temporary buffer length (don't set manually).
   22.83 +     * Used by ucx_properties_next().
   22.84 +     */
   22.85 +    size_t tmplen;
   22.86 +    
   22.87 +    /**
   22.88 +     * Internal temporary buffer capacity (don't set manually).
   22.89 +     * Used by ucx_properties_next().
   22.90 +     */
   22.91 +    size_t tmpcap;
   22.92 +    
   22.93 +    /**
   22.94 +     * Parser error code.
   22.95 +     * This is always 0 on success and a nonzero value on syntax errors.
   22.96 +     * The value is set by ucx_properties_next().
   22.97 +     */
   22.98 +    int    error;
   22.99 +    
  22.100 +    /**
  22.101 +     * The delimiter that shall be used.
  22.102 +     * This is '=' by default.
  22.103 +     */
  22.104 +    char   delimiter;
  22.105 +    
  22.106 +    /**
  22.107 +     * The first comment character.
  22.108 +     * This is '#' by default.
  22.109 +     */
  22.110 +    char   comment1;
  22.111 +    
  22.112 +    /**
  22.113 +     * The second comment character.
  22.114 +     * This is not set by default.
  22.115 +     */
  22.116 +    char   comment2;
  22.117 +    
  22.118 +    /**
  22.119 +     * The third comment character.
  22.120 +     * This is not set by default.
  22.121 +     */
  22.122 +    char   comment3;
  22.123 +} UcxProperties;
  22.124 +
  22.125 +
  22.126 +/**
  22.127 + * Constructs a new UcxProperties object.
  22.128 + * @return a pointer to the new UcxProperties object
  22.129 + */
  22.130 +UcxProperties *ucx_properties_new();
  22.131 +
  22.132 +/**
  22.133 + * Destroys a UcxProperties object.
  22.134 + * @param prop the UcxProperties object to destroy
  22.135 + */
  22.136 +void ucx_properties_free(UcxProperties *prop);
  22.137 +
  22.138 +/**
  22.139 + * Sets the input buffer for the properties parser.
  22.140 + * 
  22.141 + * After calling this function, you may parse the data by calling
  22.142 + * ucx_properties_next() until it returns 0. The function ucx_properties2map()
  22.143 + * is a convenience function that reads as much data as possible by using this
  22.144 + * function.
  22.145 + * 
  22.146 + * 
  22.147 + * @param prop the UcxProperties object
  22.148 + * @param buf a pointer to the new buffer
  22.149 + * @param len the payload length of the buffer
  22.150 + * @see ucx_properties_next()
  22.151 + * @see ucx_properties2map()
  22.152 + */
  22.153 +void ucx_properties_fill(UcxProperties *prop, char *buf, size_t len);
  22.154 +
  22.155 +/**
  22.156 + * Retrieves the next key/value-pair.
  22.157 + * 
  22.158 + * This function returns a nonzero value as long as there are key/value-pairs
  22.159 + * found. If no more key/value-pairs are found, you may refill the input buffer
  22.160 + * with ucx_properties_fill().
  22.161 + * 
  22.162 + * <b>Attention:</b> the sstr_t.ptr pointers of the output parameters point to
  22.163 + * memory within the input buffer of the parser and will get invalid some time.
  22.164 + * If you want long term copies of the key/value-pairs, use sstrdup() after
  22.165 + * calling this function.
  22.166 + * 
  22.167 + * @param prop the UcxProperties object
  22.168 + * @param name a pointer to the sstr_t that shall contain the property name
  22.169 + * @param value a pointer to the sstr_t that shall contain the property value
  22.170 + * @return Nonzero, if a key/value-pair was successfully retrieved
  22.171 + * @see ucx_properties_fill()
  22.172 + */
  22.173 +int ucx_properties_next(UcxProperties *prop, sstr_t *name, sstr_t *value);
  22.174 +
  22.175 +/**
  22.176 + * Retrieves all available key/value-pairs and puts them into a UcxMap.
  22.177 + * 
  22.178 + * This is done by successive calls to ucx_properties_next() until no more
  22.179 + * key/value-pairs can be retrieved. 
  22.180 + * 
  22.181 + * @param prop the UcxProperties object
  22.182 + * @param map the target map
  22.183 + * @return The UcxProperties.error code (i.e. 0 on success).
  22.184 + * @see ucx_properties_fill()
  22.185 + */
  22.186 +int ucx_properties2map(UcxProperties *prop, UcxMap *map);
  22.187 +
  22.188 +/**
  22.189 + * Loads a properties file to a UcxMap.
  22.190 + * 
  22.191 + * This is a convenience function that reads data from an input
  22.192 + * stream until the end of the stream is reached.
  22.193 + * 
  22.194 + * @param map the map object to write the key/value-pairs to
  22.195 + * @param file the <code>FILE*</code> stream to read from
  22.196 + * @return 0 on success, or a non-zero value on error
  22.197 + * 
  22.198 + * @see ucx_properties_fill()
  22.199 + * @see ucx_properties2map()
  22.200 + */
  22.201 +int ucx_properties_load(UcxMap *map, FILE *file);
  22.202 +
  22.203 +/**
  22.204 + * Stores a UcxMap to a file.
  22.205 + * 
  22.206 + * The key/value-pairs are written by using the following format:
  22.207 + * 
  22.208 + * <code>[key] = [value]\\n</code>
  22.209 + * 
  22.210 + * @param map the map to store
  22.211 + * @param file the <code>FILE*</code> stream to write to
  22.212 + * @return 0 on success, or a non-zero value on error
  22.213 + */
  22.214 +int ucx_properties_store(UcxMap *map, FILE *file);
  22.215 +
  22.216 +#ifdef	__cplusplus
  22.217 +}
  22.218 +#endif
  22.219 +
  22.220 +#endif	/* UCX_PROPERTIES_H */
  22.221 +
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/ucx/stack.h	Tue Oct 17 16:15:41 2017 +0200
    23.3 @@ -0,0 +1,232 @@
    23.4 +/*
    23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    23.6 + *
    23.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    23.8 + *
    23.9 + * Redistribution and use in source and binary forms, with or without
   23.10 + * modification, are permitted provided that the following conditions are met:
   23.11 + *
   23.12 + *   1. Redistributions of source code must retain the above copyright
   23.13 + *      notice, this list of conditions and the following disclaimer.
   23.14 + *
   23.15 + *   2. Redistributions in binary form must reproduce the above copyright
   23.16 + *      notice, this list of conditions and the following disclaimer in the
   23.17 + *      documentation and/or other materials provided with the distribution.
   23.18 + *
   23.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   23.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   23.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   23.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   23.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   23.29 + * POSSIBILITY OF SUCH DAMAGE.
   23.30 + */
   23.31 +
   23.32 +/**
   23.33 + * @file stack.h
   23.34 + * 
   23.35 + * Default stack memory allocation implementation.
   23.36 + * 
   23.37 + * @author Mike Becker
   23.38 + * @author Olaf Wintermann
   23.39 + */
   23.40 +
   23.41 +#ifndef UCX_STACK_H
   23.42 +#define	UCX_STACK_H
   23.43 +
   23.44 +#include <ucx/ucx.h>
   23.45 +#include <ucx/allocator.h>
   23.46 +
   23.47 +#ifdef	__cplusplus
   23.48 +extern "C" {
   23.49 +#endif
   23.50 +
   23.51 +
   23.52 +/**
   23.53 + * UCX stack structure.
   23.54 + */
   23.55 +typedef struct {
   23.56 +    /** UcxAllocator based on this stack */
   23.57 +    UcxAllocator allocator;
   23.58 +    
   23.59 +    /** Stack size. */
   23.60 +    size_t size;
   23.61 +    
   23.62 +    /** Pointer to the bottom of the stack */
   23.63 +    char *space;
   23.64 +    
   23.65 +    /** Pointer to the top of the stack */
   23.66 +    char *top;
   23.67 +} UcxStack;
   23.68 +
   23.69 +/**
   23.70 + * Metadata for each UCX stack element.
   23.71 + */
   23.72 +struct ucx_stack_metadata {
   23.73 +    /**
   23.74 +     * Location of the previous element (<code>NULL</code> if this is the first)
   23.75 +     */
   23.76 +    char *prev;
   23.77 +    
   23.78 +    /** Size of this element */
   23.79 +    size_t size;
   23.80 +};
   23.81 +
   23.82 +/**
   23.83 + * Initializes UcxStack structure with memory.
   23.84 + * 
   23.85 + * @param stack a pointer to an uninitialized stack structure
   23.86 + * @param space the memory area that shall be managed
   23.87 + * @param size size of the memory area
   23.88 + * @return a new UcxStack structure
   23.89 + */
   23.90 +void ucx_stack_init(UcxStack *stack, char* space, size_t size);
   23.91 +
   23.92 +/**
   23.93 + * Allocates stack memory.
   23.94 + * 
   23.95 + * @param stack a pointer to the stack
   23.96 + * @param n amount of memory to allocate
   23.97 + * @return a pointer to the allocated memory
   23.98 + * @see ucx_allocator_malloc()
   23.99 + */
  23.100 +void *ucx_stack_malloc(UcxStack *stack, size_t n);
  23.101 +
  23.102 +/**
  23.103 + * Alias for #ucx_stack_malloc().
  23.104 + * @param stack a pointer to the stack
  23.105 + * @param n amount of memory to allocate
  23.106 + * @return a pointer to the allocated memory
  23.107 + * @see ucx_stack_malloc
  23.108 + */
  23.109 +#define ucx_stack_push(stack, n) ucx_stack_malloc(stack, n)
  23.110 +
  23.111 +/**
  23.112 + * Allocates an array of stack memory
  23.113 + * 
  23.114 + * The content of the allocated memory is set to zero.
  23.115 + * 
  23.116 + * @param stack a pointer to the stack
  23.117 + * @param nelem amount of elements to allocate
  23.118 + * @param elsize amount of memory per element
  23.119 + * @return a pointer to the allocated memory
  23.120 + * @see ucx_allocator_calloc()
  23.121 + */
  23.122 +void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize);
  23.123 +
  23.124 +/**
  23.125 + * Alias for #ucx_stack_calloc().
  23.126 + * 
  23.127 + * @param stack a pointer to the stack
  23.128 + * @param n amount of elements to allocate
  23.129 + * @param elsize amount of memory per element
  23.130 + * @return a pointer to the allocated memory
  23.131 + * @see ucx_stack_calloc
  23.132 + */
  23.133 +#define ucx_stack_pusharr(stack,n,elsize) ucx_stack_calloc(stack,n,elssize)
  23.134 +
  23.135 +/**
  23.136 + * Reallocates memory on the stack.
  23.137 + * 
  23.138 + * Shrinking memory is always safe. Extending memory can be very expensive. 
  23.139 + * 
  23.140 + * @param stack the stack
  23.141 + * @param ptr a pointer to the memory that shall be reallocated
  23.142 + * @param n the new size of the memory
  23.143 + * @return a pointer to the new location of the memory
  23.144 + * @see ucx_allocator_realloc()
  23.145 + */
  23.146 +void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n);
  23.147 +
  23.148 +/**
  23.149 + * Frees memory on the stack.
  23.150 + * 
  23.151 + * Freeing stack memory behaves in a special way.
  23.152 + * 
  23.153 + * If the element, that should be freed, is the top most element of the stack,
  23.154 + * it is removed from the stack. Otherwise it is marked as freed. Marked
  23.155 + * elements are removed, when they become the top most elements of the stack.
  23.156 + * 
  23.157 + * @param stack a pointer to the stack
  23.158 + * @param ptr a pointer to the memory that shall be freed
  23.159 + */
  23.160 +void ucx_stack_free(UcxStack *stack, void *ptr);
  23.161 +
  23.162 +
  23.163 +/**
  23.164 + * Returns the size of the top most element.
  23.165 + * @param stack a pointer to the stack
  23.166 + * @return the size of the top most element
  23.167 + */
  23.168 +#define ucx_stack_topsize(stack) ((stack)->top ? ((struct ucx_stack_metadata*)\
  23.169 +                                  (stack)->top - 1)->size : 0)
  23.170 +
  23.171 +/**
  23.172 + * Removes the top most element from the stack and copies the content to <code>
  23.173 + * dest</code>, if specified.
  23.174 + * 
  23.175 + * Use #ucx_stack_topsize()# to get the amount of memory that must be available
  23.176 + * at the location of <code>dest</code>.
  23.177 + * 
  23.178 + * @param stack a pointer to the stack
  23.179 + * @param dest the location where the contents shall be written to, or <code>
  23.180 + * NULL</code>, if the element shall only be removed.
  23.181 + * @see ucx_stack_free
  23.182 + * @see ucx_stack_popn
  23.183 + */
  23.184 +#define ucx_stack_pop(stack, dest) ucx_stack_popn(stack, dest, (size_t)-1)
  23.185 +
  23.186 +/**
  23.187 + * Removes the top most element from the stack and copies the content to <code>
  23.188 + * dest</code>.
  23.189 + * 
  23.190 + * In contrast to #ucx_stack_pop() the <code>dest</code> pointer <code>MUST
  23.191 + * NOT</code> be <code>NULL</code>.
  23.192 + * 
  23.193 + * @param stack a pointer to the stack
  23.194 + * @param dest the location where the contents shall be written to
  23.195 + * @param n copies at most n elements to <code>dest</code>
  23.196 + * @see ucx_stack_pop
  23.197 + */
  23.198 +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n);
  23.199 +
  23.200 +/**
  23.201 + * Returns the remaining available memory on the specified stack.
  23.202 + * 
  23.203 + * @param stack a pointer to the stack
  23.204 + * @return the remaining available memory
  23.205 + */
  23.206 +size_t ucx_stack_avail(UcxStack *stack);
  23.207 +
  23.208 +/**
  23.209 + * Checks, if the stack is empty.
  23.210 + * 
  23.211 + * @param stack a pointer to the stack
  23.212 + * @return nonzero, if the stack is empty, zero otherwise
  23.213 + */
  23.214 +#define ucx_stack_empty(stack) (!(stack)->top)
  23.215 +
  23.216 +/**
  23.217 + * Computes a recommended size for the stack memory area. Note, that
  23.218 + * reallocations have not been taken into account, so you might need to reserve
  23.219 + * twice as much memory to allow many reallocations.
  23.220 + * 
  23.221 + * @param size the approximate payload
  23.222 + * @param elems the approximate count of element allocations
  23.223 + * @return a recommended size for the stack space based on the information
  23.224 + * provided
  23.225 + */
  23.226 +#define ucx_stack_dim(size, elems) (size+sizeof(struct ucx_stack_metadata) * \
  23.227 +                                    (elems + 1))
  23.228 +
  23.229 +
  23.230 +#ifdef	__cplusplus
  23.231 +}
  23.232 +#endif
  23.233 +
  23.234 +#endif	/* UCX_STACK_H */
  23.235 +
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/ucx/string.h	Tue Oct 17 16:15:41 2017 +0200
    24.3 @@ -0,0 +1,460 @@
    24.4 +/*
    24.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    24.6 + *
    24.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    24.8 + *
    24.9 + * Redistribution and use in source and binary forms, with or without
   24.10 + * modification, are permitted provided that the following conditions are met:
   24.11 + *
   24.12 + *   1. Redistributions of source code must retain the above copyright
   24.13 + *      notice, this list of conditions and the following disclaimer.
   24.14 + *
   24.15 + *   2. Redistributions in binary form must reproduce the above copyright
   24.16 + *      notice, this list of conditions and the following disclaimer in the
   24.17 + *      documentation and/or other materials provided with the distribution.
   24.18 + *
   24.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   24.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   24.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   24.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   24.29 + * POSSIBILITY OF SUCH DAMAGE.
   24.30 + */
   24.31 +/**
   24.32 + * Bounded string implementation.
   24.33 + * 
   24.34 + * The UCX strings (<code>sstr_t</code>) provide an alternative to C strings.
   24.35 + * The main difference to C strings is, that <code>sstr_t</code> does <b>not
   24.36 + * need to be <code>NULL</code>-terminated</b>. Instead the length is stored
   24.37 + * within the structure.
   24.38 + * 
   24.39 + * When using <code>sstr_t</code>, developers must be full aware of what type
   24.40 + * of string (<code>NULL</code>-terminated) or not) they are using, when 
   24.41 + * accessing the <code>char* ptr</code> directly.
   24.42 + * 
   24.43 + * The UCX string module provides some common string functions, known from
   24.44 + * standard libc, working with <code>sstr_t</code>.
   24.45 + * 
   24.46 + * @file   string.h
   24.47 + * @author Mike Becker
   24.48 + * @author Olaf Wintermann
   24.49 + */
   24.50 +
   24.51 +#ifndef UCX_STRING_H
   24.52 +#define	UCX_STRING_H
   24.53 +
   24.54 +#include <ucx/ucx.h>
   24.55 +#include <ucx/allocator.h>
   24.56 +#include <stddef.h>
   24.57 +
   24.58 +/** Shortcut for a <code>sstr_t struct</code> literal. */
   24.59 +#define ST(s) { (char*)s, sizeof(s)-1 }
   24.60 +
   24.61 +/** Shortcut for the conversion of a C string to a <code>sstr_t</code>. */
   24.62 +#define S(s) sstrn((char*)s, sizeof(s)-1)
   24.63 +
   24.64 +#ifdef	__cplusplus
   24.65 +extern "C" {
   24.66 +#endif
   24.67 +
   24.68 +/**
   24.69 + * The UCX string structure.
   24.70 + */
   24.71 +typedef struct {
   24.72 +   /** A reference to the string (<b>not necessarily  <code>NULL</code>
   24.73 +    * -terminated</b>) */
   24.74 +    char   *ptr;
   24.75 +    /** The length of the string */
   24.76 +    size_t length;
   24.77 +} sstr_t;
   24.78 +
   24.79 +/**
   24.80 + * Creates a new sstr_t based on a C string.
   24.81 + * 
   24.82 + * The length is implicitly inferred by using a call to <code>strlen()</code>.
   24.83 + *
   24.84 + * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you
   24.85 + * do want a copy, use sstrdup() on the return value of this function.
   24.86 + * 
   24.87 + * @param cstring the C string to wrap
   24.88 + * @return a new sstr_t containing the C string
   24.89 + * 
   24.90 + * @see sstrn()
   24.91 + */
   24.92 +sstr_t sstr(char *cstring);
   24.93 +
   24.94 +/**
   24.95 + * Creates a new sstr_t of the specified length based on a C string.
   24.96 + *
   24.97 + * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you
   24.98 + * do want a copy, use sstrdup() on the return value of this function.
   24.99 + * 
  24.100 + * @param cstring  the C string to wrap
  24.101 + * @param length   the length of the string
  24.102 + * @return a new sstr_t containing the C string
  24.103 + * 
  24.104 + * @see sstr()
  24.105 + * @see S()
  24.106 + */
  24.107 +sstr_t sstrn(char *cstring, size_t length);
  24.108 +
  24.109 +
  24.110 +/**
  24.111 + * Returns the cumulated length of all specified strings.
  24.112 + *
  24.113 + * At least one string must be specified.
  24.114 + * 
  24.115 + * <b>Attention:</b> if the count argument does not match the count of the
  24.116 + * specified strings, the behavior is undefined.
  24.117 + *
  24.118 + * @param count    the total number of specified strings (so at least 1)
  24.119 + * @param string   the first string
  24.120 + * @param ...      all other strings
  24.121 + * @return the cumulated length of all strings
  24.122 + */
  24.123 +size_t sstrnlen(size_t count, sstr_t string, ...);
  24.124 +
  24.125 +/**
  24.126 + * Concatenates two or more strings.
  24.127 + * 
  24.128 + * The resulting string will be allocated by standard <code>malloc()</code>. 
  24.129 + * So developers <b>MUST</b> pass the sstr_t.ptr to <code>free()</code>.
  24.130 + * 
  24.131 + * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>-
  24.132 + * terminated.
  24.133 + *
  24.134 + * @param count   the total number of strings to concatenate
  24.135 + * @param s1      first string
  24.136 + * @param s2      second string
  24.137 + * @param ...     all remaining strings
  24.138 + * @return the concatenated string
  24.139 + */
  24.140 +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...);
  24.141 +
  24.142 +/**
  24.143 + * Concatenates two or more strings using a UcxAllocator.
  24.144 + * 
  24.145 + * See sstrcat() for details.
  24.146 + *
  24.147 + * @param a       the allocator to use
  24.148 + * @param count   the total number of strings to concatenate
  24.149 + * @param s1      first string
  24.150 + * @param s2      second string
  24.151 + * @param ...     all remaining strings
  24.152 + * @return the concatenated string
  24.153 + */
  24.154 +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...);
  24.155 +
  24.156 +
  24.157 +/**
  24.158 + * Returns a substring starting at the specified location.
  24.159 + * 
  24.160 + * <b>Attention:</b> the new string references the same memory area as the
  24.161 + * input string and will <b>NOT</b> be <code>NULL</code>-terminated.
  24.162 + * Use sstrdup() to get a copy.
  24.163 + * 
  24.164 + * @param string input string
  24.165 + * @param start  start location of the substring
  24.166 + * @return a substring of <code>string</code> starting at <code>start</code>
  24.167 + * 
  24.168 + * @see sstrsubsl()
  24.169 + * @see sstrchr()
  24.170 + */
  24.171 +sstr_t sstrsubs(sstr_t string, size_t start);
  24.172 +
  24.173 +/**
  24.174 + * Returns a substring with a maximum length starting at the specified location.
  24.175 + * 
  24.176 + * <b>Attention:</b> the new string references the same memory area as the
  24.177 + * input string and will <b>NOT</b> be <code>NULL</code>-terminated.
  24.178 + * Use sstrdup() to get a copy.
  24.179 + * 
  24.180 + * @param string input string
  24.181 + * @param start  start location of the substring
  24.182 + * @param length the maximum length of the substring
  24.183 + * @return a substring of <code>string</code> starting at <code>start</code>
  24.184 + * with a maximum length of <code>length</code>
  24.185 + * 
  24.186 + * @see sstrsubs()
  24.187 + * @see sstrchr()
  24.188 + */
  24.189 +sstr_t sstrsubsl(sstr_t string, size_t start, size_t length);
  24.190 +
  24.191 +/**
  24.192 + * Returns a substring starting at the location of the first occurrence of the
  24.193 + * specified character.
  24.194 + * 
  24.195 + * If the string does not contain the character, an empty string is returned.
  24.196 + * 
  24.197 + * @param string the string where to locate the character
  24.198 + * @param chr    the character to locate
  24.199 + * @return       a substring starting at the first location of <code>chr</code>
  24.200 + * 
  24.201 + * @see sstrsubs()
  24.202 + */
  24.203 +sstr_t sstrchr(sstr_t string, int chr);
  24.204 +
  24.205 +/**
  24.206 + * Returns a substring starting at the location of the last occurrence of the
  24.207 + * specified character.
  24.208 + * 
  24.209 + * If the string does not contain the character, an empty string is returned.
  24.210 + * 
  24.211 + * @param string the string where to locate the character
  24.212 + * @param chr    the character to locate
  24.213 + * @return       a substring starting at the last location of <code>chr</code>
  24.214 + * 
  24.215 + * @see sstrsubs()
  24.216 + */
  24.217 +sstr_t sstrrchr(sstr_t string, int chr);
  24.218 +
  24.219 +/**
  24.220 + * Returns a substring starting at the location of the first occurrence of the
  24.221 + * specified string.
  24.222 + * 
  24.223 + * If the string does not contain the other string, an empty string is returned.
  24.224 + * 
  24.225 + * If <code>match</code> is an empty string, the complete <code>string</code> is
  24.226 + * returned.
  24.227 + * 
  24.228 + * @param string the string to be scanned
  24.229 + * @param match  string containing the sequence of characters to match
  24.230 + * @return       a substring starting at the first occurrence of
  24.231 + *               <code>match</code>, or an empty string, if the sequence is not
  24.232 + *               present in <code>string</code>
  24.233 + */
  24.234 +sstr_t sstrstr(sstr_t string, sstr_t match);
  24.235 +
  24.236 +/**
  24.237 + * Splits a string into parts by using a delimiter string.
  24.238 + * 
  24.239 + * This function will return <code>NULL</code>, if one of the following happens:
  24.240 + * <ul>
  24.241 + *   <li>the string length is zero</li>
  24.242 + *   <li>the delimeter length is zero</li>
  24.243 + *   <li>the string equals the delimeter</li>
  24.244 + *   <li>memory allocation fails</li>
  24.245 + * </ul>
  24.246 + * 
  24.247 + * The integer referenced by <code>count</code> is used as input and determines
  24.248 + * the maximum size of the resulting array, i.e. the maximum count of splits to
  24.249 + * perform + 1.
  24.250 + * 
  24.251 + * The integer referenced by <code>count</code> is also used as output and is
  24.252 + * set to
  24.253 + * <ul>
  24.254 + *   <li>-2, on memory allocation errors</li>
  24.255 + *   <li>-1, if either the string or the delimiter is an empty string</li>
  24.256 + *   <li>0, if the string equals the delimiter</li>
  24.257 + *   <li>1, if the string does not contain the delimiter</li>
  24.258 + *   <li>the count of array items, otherwise</li>
  24.259 + * </ul>
  24.260 + * 
  24.261 + * If the string starts with the delimiter, the first item of the resulting
  24.262 + * array will be an empty string.
  24.263 + * 
  24.264 + * If the string ends with the delimiter and the maximum list size is not
  24.265 + * exceeded, the last array item will be an empty string.
  24.266 + * In case the list size would be exceeded, the last array item will be the
  24.267 + * remaining string after the last split, <i>including</i> the terminating
  24.268 + * delimiter.
  24.269 + * 
  24.270 + * <b>Attention:</b> The array pointer <b>AND</b> all sstr_t.ptr of the array
  24.271 + * items must be manually passed to <code>free()</code>. Use sstrsplit_a() with
  24.272 + * an allocator to managed memory, to avoid this.
  24.273 + *
  24.274 + * @param string the string to split
  24.275 + * @param delim  the delimiter string
  24.276 + * @param count  IN: the maximum size of the resulting array (0 = no limit),
  24.277 + *               OUT: the actual size of the array
  24.278 + * @return a sstr_t array containing the split strings or
  24.279 + *         <code>NULL</code> on error
  24.280 + * 
  24.281 + * @see sstrsplit_a()
  24.282 + */
  24.283 +sstr_t* sstrsplit(sstr_t string, sstr_t delim, ssize_t *count);
  24.284 +
  24.285 +/**
  24.286 + * Performing sstrsplit() using a UcxAllocator.
  24.287 + * 
  24.288 + * <i>Read the description of sstrsplit() for details.</i>
  24.289 + * 
  24.290 + * The memory for the sstr_t.ptr pointers of the array items and the memory for
  24.291 + * the sstr_t array itself are allocated by using the UcxAllocator.malloc()
  24.292 + * function.
  24.293 + * 
  24.294 + * <b>Note:</b> the allocator is not used for memory that is freed within the
  24.295 + * same call of this function (locally scoped variables).
  24.296 + * 
  24.297 + * @param allocator the UcxAllocator used for allocating memory
  24.298 + * @param string the string to split
  24.299 + * @param delim  the delimiter string
  24.300 + * @param count  IN: the maximum size of the resulting array (0 = no limit),
  24.301 + *               OUT: the actual size of the array
  24.302 + * @return a sstr_t array containing the split strings or
  24.303 + *         <code>NULL</code> on error
  24.304 + * 
  24.305 + * @see sstrsplit()
  24.306 + */
  24.307 +sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t string, sstr_t delim,
  24.308 +        ssize_t *count);
  24.309 +
  24.310 +/**
  24.311 + * Compares two UCX strings with standard <code>memcmp()</code>.
  24.312 + * 
  24.313 + * At first it compares the sstr_t.length attribute of the two strings. The
  24.314 + * <code>memcmp()</code> function is called, if and only if the lengths match.
  24.315 + * 
  24.316 + * @param s1 the first string
  24.317 + * @param s2 the second string
  24.318 + * @return -1, if the length of s1 is less than the length of s2 or 1, if the 
  24.319 + * length of s1 is greater than the length of s2 or the result of
  24.320 + * <code>memcmp()</code> otherwise (i.e. 0 if the strings match)
  24.321 + */
  24.322 +int sstrcmp(sstr_t s1, sstr_t s2);
  24.323 +
  24.324 +/**
  24.325 + * Compares two UCX strings ignoring the case.
  24.326 + * 
  24.327 + * At first it compares the sstr_t.length attribute of the two strings. If and
  24.328 + * only if the lengths match, both strings are compared char by char ignoring
  24.329 + * the case.
  24.330 + * 
  24.331 + * @param s1 the first string
  24.332 + * @param s2 the second string
  24.333 + * @return -1, if the length of s1 is less than the length of s2 or 1, if the 
  24.334 + * length of s1 is greater than the length of s2 or the difference between the
  24.335 + * first two differing characters otherwise (i.e. 0 if the strings match and
  24.336 + * no characters differ)
  24.337 + */
  24.338 +int sstrcasecmp(sstr_t s1, sstr_t s2);
  24.339 +
  24.340 +/**
  24.341 + * Creates a duplicate of the specified string.
  24.342 + * 
  24.343 + * The new sstr_t will contain a copy allocated by standard
  24.344 + * <code>malloc()</code>. So developers <b>MUST</b> pass the sstr_t.ptr to
  24.345 + * <code>free()</code>.
  24.346 + * 
  24.347 + * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>-
  24.348 + * terminated.
  24.349 + * 
  24.350 + * @param string the string to duplicate
  24.351 + * @return a duplicate of the string
  24.352 + * @see sstrdup_a()
  24.353 + */
  24.354 +sstr_t sstrdup(sstr_t string);
  24.355 +
  24.356 +/**
  24.357 + * Creates a duplicate of the specified string using a UcxAllocator.
  24.358 + * 
  24.359 + * The new sstr_t will contain a copy allocated by the allocators
  24.360 + * ucx_allocator_malloc function. So it is implementation depended, whether the
  24.361 + * returned sstr_t.ptr pointer must be passed to the allocators
  24.362 + * ucx_allocator_free function manually.
  24.363 + * 
  24.364 + * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>-
  24.365 + * terminated.
  24.366 + * 
  24.367 + * @param allocator a valid instance of a UcxAllocator
  24.368 + * @param string the string to duplicate
  24.369 + * @return a duplicate of the string
  24.370 + * @see sstrdup()
  24.371 + */
  24.372 +sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t string);
  24.373 +
  24.374 +/**
  24.375 + * Omits leading and trailing spaces.
  24.376 + * 
  24.377 + * This function returns a new sstr_t containing a trimmed version of the
  24.378 + * specified string.
  24.379 + * 
  24.380 + * <b>Note:</b> the new sstr_t references the same memory, thus you
  24.381 + * <b>MUST NOT</b> pass the sstr_t.ptr of the return value to
  24.382 + * <code>free()</code>. It is also highly recommended to avoid assignments like
  24.383 + * <code>mystr = sstrtrim(mystr);</code> as you lose the reference to the
  24.384 + * source string. Assignments of this type are only permitted, if the
  24.385 + * sstr_t.ptr of the source string does not need to be freed or if another
  24.386 + * reference to the source string exists.
  24.387 + * 
  24.388 + * @param string the string that shall be trimmed
  24.389 + * @return a new sstr_t containing the trimmed string
  24.390 + */
  24.391 +sstr_t sstrtrim(sstr_t string);
  24.392 +
  24.393 +/**
  24.394 + * Checks, if a string has a specific prefix.
  24.395 + * @param string the string to check
  24.396 + * @param prefix the prefix the string should have
  24.397 + * @return 1, if and only if the string has the specified prefix, 0 otherwise
  24.398 + */
  24.399 +int sstrprefix(sstr_t string, sstr_t prefix);
  24.400 +
  24.401 +/**
  24.402 + * Checks, if a string has a specific suffix.
  24.403 + * @param string the string to check
  24.404 + * @param suffix the suffix the string should have
  24.405 + * @return 1, if and only if the string has the specified suffix, 0 otherwise
  24.406 + */
  24.407 +int sstrsuffix(sstr_t string, sstr_t suffix);
  24.408 +
  24.409 +/**
  24.410 + * Returns a lower case version of a string.
  24.411 + * 
  24.412 + * This function creates a duplicate of the input string, first. See the
  24.413 + * documentation of sstrdup() for the implications.
  24.414 + * 
  24.415 + * @param string the input string
  24.416 + * @return the resulting lower case string
  24.417 + * @see sstrdup()
  24.418 + */
  24.419 +sstr_t sstrlower(sstr_t string);
  24.420 +
  24.421 +/**
  24.422 + * Returns a lower case version of a string.
  24.423 + * 
  24.424 + * This function creates a duplicate of the input string, first. See the
  24.425 + * documentation of sstrdup_a() for the implications.
  24.426 + * 
  24.427 + * @param allocator the allocator used for duplicating the string
  24.428 + * @param string the input string
  24.429 + * @return the resulting lower case string
  24.430 + * @see sstrdup_a()
  24.431 + */
  24.432 +sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string);
  24.433 +
  24.434 +/**
  24.435 + * Returns a upper case version of a string.
  24.436 + * 
  24.437 + * This function creates a duplicate of the input string, first. See the
  24.438 + * documentation of sstrdup() for the implications.
  24.439 + * 
  24.440 + * @param string the input string
  24.441 + * @return the resulting upper case string
  24.442 + * @see sstrdup()
  24.443 + */
  24.444 +sstr_t sstrupper(sstr_t string);
  24.445 +
  24.446 +/**
  24.447 + * Returns a upper case version of a string.
  24.448 + * 
  24.449 + * This function creates a duplicate of the input string, first. See the
  24.450 + * documentation of sstrdup_a() for the implications.
  24.451 + * 
  24.452 + * @param allocator the allocator used for duplicating the string
  24.453 + * @param string the input string
  24.454 + * @return the resulting upper case string
  24.455 + * @see sstrdup_a()
  24.456 + */
  24.457 +sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string);
  24.458 +
  24.459 +#ifdef	__cplusplus
  24.460 +}
  24.461 +#endif
  24.462 +
  24.463 +#endif	/* UCX_STRING_H */
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/src/ucx/test.h	Tue Oct 17 16:15:41 2017 +0200
    25.3 @@ -0,0 +1,241 @@
    25.4 +/*
    25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    25.6 + *
    25.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    25.8 + *
    25.9 + * Redistribution and use in source and binary forms, with or without
   25.10 + * modification, are permitted provided that the following conditions are met:
   25.11 + *
   25.12 + *   1. Redistributions of source code must retain the above copyright
   25.13 + *      notice, this list of conditions and the following disclaimer.
   25.14 + *
   25.15 + *   2. Redistributions in binary form must reproduce the above copyright
   25.16 + *      notice, this list of conditions and the following disclaimer in the
   25.17 + *      documentation and/or other materials provided with the distribution.
   25.18 + *
   25.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   25.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   25.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   25.29 + * POSSIBILITY OF SUCH DAMAGE.
   25.30 + */
   25.31 + 
   25.32 +/**
   25.33 + * @file: test.h
   25.34 + * 
   25.35 + * UCX Test Framework.
   25.36 + * 
   25.37 + * Usage of this test framework:
   25.38 + *
   25.39 + * **** IN HEADER FILE: ****
   25.40 + *
   25.41 + * <pre>
   25.42 + * UCX_TEST(function_name)
   25.43 + * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) // optional
   25.44 + * </pre>
   25.45 + *
   25.46 + * **** IN SOURCE FILE: ****
   25.47 + * <pre>
   25.48 + * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) {
   25.49 + *   // tests with UCX_TEST_ASSERT()
   25.50 + * }
   25.51 + * 
   25.52 + * UCX_TEST(function_name) {
   25.53 + *   // memory allocation and other stuff here
   25.54 + *   #UCX_TEST_BEGIN
   25.55 + *   // tests with UCX_TEST_ASSERT() and/or
   25.56 + *   // calls with UCX_TEST_CALL_SUBROUTINE() here
   25.57 + *   #UCX_TEST_END
   25.58 + *   // cleanup of memory here
   25.59 + * }
   25.60 + * </pre>
   25.61 + *
   25.62 + * <b>Note:</b> if a test fails, a longjump is performed
   25.63 + * back to the #UCX_TEST_BEGIN macro!
   25.64 + * 
   25.65 + * <b>Attention:</b> Do not call own functions within a test, that use
   25.66 + * UCX_TEST_ASSERT() macros and are not defined by using UCX_TEST_SUBROUTINE().
   25.67 + * 
   25.68 + *
   25.69 + * @author Mike Becker
   25.70 + * @author Olaf Wintermann
   25.71 + *
   25.72 + */
   25.73 +
   25.74 +#ifndef UCX_TEST_H
   25.75 +#define	UCX_TEST_H
   25.76 +
   25.77 +#include <ucx/ucx.h>
   25.78 +#include <stdio.h>
   25.79 +#include <string.h>
   25.80 +#include <setjmp.h>
   25.81 +
   25.82 +#ifdef	__cplusplus
   25.83 +extern "C" {
   25.84 +#endif
   25.85 +
   25.86 +#ifndef __FUNCTION__
   25.87 +
   25.88 +/**
   25.89 + * Alias for the <code>__func__</code> preprocessor macro.
   25.90 + * Some compilers use <code>__func__</code> and others use __FUNCTION__.
   25.91 + * We use __FUNCTION__ so we define it for those compilers which use
   25.92 + * <code>__func__</code>.
   25.93 + */
   25.94 +#define __FUNCTION__ __func__
   25.95 +#endif
   25.96 +
   25.97 +/** Type for the UcxTestSuite. */
   25.98 +typedef struct UcxTestSuite UcxTestSuite;
   25.99 +
  25.100 +/** Pointer to a test function. */
  25.101 +typedef void(*UcxTest)(UcxTestSuite*,FILE*);
  25.102 +
  25.103 +/** Type for the internal list of test cases. */
  25.104 +typedef struct UcxTestList UcxTestList;
  25.105 +
  25.106 +/** Structure for the internal list of test cases. */
  25.107 +struct UcxTestList {
  25.108 +    
  25.109 +    /** Test case. */
  25.110 +    UcxTest test;
  25.111 +    
  25.112 +    /** Pointer to the next list element. */
  25.113 +    UcxTestList *next;
  25.114 +};
  25.115 +
  25.116 +/**
  25.117 + * A test suite containing multiple test cases.
  25.118 + */
  25.119 +struct UcxTestSuite {
  25.120 +    
  25.121 +    /** The number of successful tests after the suite has been run. */
  25.122 +    unsigned int success;
  25.123 +    
  25.124 +    /** The number of failed tests after the suite has been run. */
  25.125 +    unsigned int failure;
  25.126 +    
  25.127 +    /**
  25.128 +     * Internal list of test cases.
  25.129 +     * Use ucx_test_register() to add tests to this list.
  25.130 +     */
  25.131 +    UcxTestList *tests;
  25.132 +};
  25.133 +
  25.134 +/**
  25.135 + * Creates a new test suite.
  25.136 + * @return a new test suite
  25.137 + */
  25.138 +UcxTestSuite* ucx_test_suite_new();
  25.139 +
  25.140 +/**
  25.141 + * Destroys a test suite.
  25.142 + * @param suite the test suite to destroy
  25.143 + */
  25.144 +void ucx_test_suite_free(UcxTestSuite* suite);
  25.145 +
  25.146 +/**
  25.147 + * Registers a test function with the specified test suite.
  25.148 + * 
  25.149 + * @param suite the suite, the test function shall be added to
  25.150 + * @param test the test function to register
  25.151 + * @return <code>EXIT_SUCCESS</code> on success or
  25.152 + * <code>EXIT_FAILURE</code> on failure
  25.153 + */
  25.154 +int ucx_test_register(UcxTestSuite* suite, UcxTest test);
  25.155 +
  25.156 +/**
  25.157 + * Runs a test suite and writes the test log to the specified stream.
  25.158 + * @param suite the test suite to run
  25.159 + * @param outstream the stream the log shall be written to
  25.160 + */
  25.161 +void ucx_test_run(UcxTestSuite* suite, FILE* outstream);
  25.162 +
  25.163 +/**
  25.164 + * Macro for a #UcxTest function header.
  25.165 + * 
  25.166 + * Use this macro to declare and/or define a #UcxTest function.
  25.167 + * 
  25.168 + * @param name the name of the test function
  25.169 + */
  25.170 +#define UCX_TEST(name) void name(UcxTestSuite* _suite_,FILE *_output_)
  25.171 +
  25.172 +/**
  25.173 + * Marks the begin of a test.
  25.174 + * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>after</b>
  25.175 + * #UCX_TEST_BEGIN.
  25.176 + * 
  25.177 + * @see #UCX_TEST_END
  25.178 + */
  25.179 +#define UCX_TEST_BEGIN fwrite("Running ", 1, 8, _output_);\
  25.180 +        fwrite(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\
  25.181 +        fwrite("... ", 1, 4, _output_);\
  25.182 +        jmp_buf _env_; \
  25.183 +        if (!setjmp(_env_)) {
  25.184 +
  25.185 +/**
  25.186 + * Checks a test assertion.
  25.187 + * If the assertion is correct, the test carries on. If the assertion is not
  25.188 + * correct, the specified message (terminated by a dot and a line break) is
  25.189 + * written to the test suites output stream.
  25.190 + * @param condition the condition to check
  25.191 + * @param message the message that shall be printed out on failure
  25.192 + */
  25.193 +#define UCX_TEST_ASSERT(condition,message) if (!(condition)) { \
  25.194 +        fwrite(message".\n", 1, 2+strlen(message), _output_); \
  25.195 +        _suite_->failure++; \
  25.196 +        longjmp(_env_, 1);\
  25.197 +    }
  25.198 +
  25.199 +/**
  25.200 + * Macro for a test subroutine function header.
  25.201 + * 
  25.202 + * Use this to declare and/or define a subroutine that can be called by using
  25.203 + * UCX_TEST_CALL_SUBROUTINE().
  25.204 + * 
  25.205 + * @param name the name of the subroutine
  25.206 + * @param ... the parameter list
  25.207 + * 
  25.208 + * @see UCX_TEST_CALL_SUBROUTINE()
  25.209 + */
  25.210 +#define UCX_TEST_SUBROUTINE(name,...) void name(UcxTestSuite* _suite_,\
  25.211 +        FILE *_output_, jmp_buf _env_, __VA_ARGS__)
  25.212 +
  25.213 +/**
  25.214 + * Macro for calling a test subroutine.
  25.215 + * 
  25.216 + * Subroutines declared with UCX_TEST_SUBROUTINE() can be called by using this
  25.217 + * macro.
  25.218 + * 
  25.219 + * <b>Note:</b> You may <b>only</b> call subroutines within a #UCX_TEST_BEGIN-
  25.220 + * #UCX_TEST_END-block.
  25.221 + * 
  25.222 + * @param name the name of the subroutine
  25.223 + * @param ... the argument list
  25.224 + * 
  25.225 + * @see UCX_TEST_SUBROUTINE()
  25.226 + */
  25.227 +#define UCX_TEST_CALL_SUBROUTINE(name,...) \
  25.228 +        name(_suite_,_output_,_env_,__VA_ARGS__);
  25.229 +
  25.230 +/**
  25.231 + * Marks the end of a test.
  25.232 + * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>before</b>
  25.233 + * #UCX_TEST_END.
  25.234 + * 
  25.235 + * @see #UCX_TEST_BEGIN
  25.236 + */
  25.237 +#define UCX_TEST_END fwrite("success.\n", 1, 9, _output_); _suite_->success++;}
  25.238 +
  25.239 +#ifdef	__cplusplus
  25.240 +}
  25.241 +#endif
  25.242 +
  25.243 +#endif	/* UCX_TEST_H */
  25.244 +
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/src/ucx/ucx.h	Tue Oct 17 16:15:41 2017 +0200
    26.3 @@ -0,0 +1,145 @@
    26.4 +/*
    26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    26.6 + *
    26.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    26.8 + *
    26.9 + * Redistribution and use in source and binary forms, with or without
   26.10 + * modification, are permitted provided that the following conditions are met:
   26.11 + *
   26.12 + *   1. Redistributions of source code must retain the above copyright
   26.13 + *      notice, this list of conditions and the following disclaimer.
   26.14 + *
   26.15 + *   2. Redistributions in binary form must reproduce the above copyright
   26.16 + *      notice, this list of conditions and the following disclaimer in the
   26.17 + *      documentation and/or other materials provided with the distribution.
   26.18 + *
   26.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   26.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   26.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26.29 + * POSSIBILITY OF SUCH DAMAGE.
   26.30 + */
   26.31 +/**
   26.32 + * Main UCX Header providing most common definitions.
   26.33 + * 
   26.34 + * @file   ucx.h
   26.35 + * @author Mike Becker
   26.36 + * @author Olaf Wintermann
   26.37 + */
   26.38 +
   26.39 +#ifndef UCX_H
   26.40 +#define	UCX_H
   26.41 +
   26.42 +/** Major UCX version as integer constant. */
   26.43 +#define UCX_VERSION_MAJOR   0
   26.44 +
   26.45 +/** Minor UCX version as integer constant. */
   26.46 +#define UCX_VERSION_MINOR   13
   26.47 +
   26.48 +#include <stdlib.h>
   26.49 +#include <stdint.h>
   26.50 +
   26.51 +#ifdef _WIN32
   26.52 +#if !(defined __ssize_t_defined || defined _SSIZE_T_)
   26.53 +#include <BaseTsd.h>
   26.54 +typedef SSIZE_T ssize_t;
   26.55 +#define __ssize_t_defined
   26.56 +#define _SSIZE_T_
   26.57 +#endif /* __ssize_t_defined and _SSIZE_T */
   26.58 +#else /* !_WIN32 */
   26.59 +#include <sys/types.h>
   26.60 +#endif /* _WIN32 */
   26.61 +
   26.62 +#ifdef	__cplusplus
   26.63 +#ifndef _Bool
   26.64 +#define _Bool bool
   26.65 +#define restrict
   26.66 +#endif
   26.67 +/** Use C naming even when compiling with C++.  */
   26.68 +#define UCX_EXTERN extern "C"
   26.69 +extern "C" {
   26.70 +#else
   26.71 +/** Pointless in C. */
   26.72 +#define UCX_EXTERN
   26.73 +#endif
   26.74 +    
   26.75 +
   26.76 +/**
   26.77 + * A function pointer to a destructor function.
   26.78 + * @see ucx_mempool_setdestr()
   26.79 + * @see ucx_mempool_regdestr()
   26.80 + */
   26.81 +typedef void(*ucx_destructor)(void*);
   26.82 +
   26.83 +/**
   26.84 + * Function pointer to a compare function.
   26.85 + * 
   26.86 + * The compare function shall take three arguments: the two values that shall be
   26.87 + * compared and optional additional data.
   26.88 + * The function shall then return -1 if the first argument is less than the
   26.89 + * second argument, 1 if the first argument is greater than the second argument
   26.90 + * and 0 if both arguments are equal. If the third argument is
   26.91 + * <code>NULL</code>, it shall be ignored.
   26.92 + */
   26.93 +typedef int(*cmp_func)(const void*,const void*,void*);
   26.94 +
   26.95 +/**
   26.96 + * Function pointer to a distance function.
   26.97 + * 
   26.98 + * The distance function shall take three arguments: the two values for which
   26.99 + * the distance shall be computed and optional additional data.
  26.100 + * The function shall then return the signed distance as integer value.
  26.101 + */
  26.102 +typedef intmax_t(*distance_func)(const void*,const void*,void*);
  26.103 +
  26.104 +/**
  26.105 + * Function pointer to a copy function.
  26.106 + * 
  26.107 + * The copy function shall create a copy of the first argument and may use
  26.108 + * additional data provided by the second argument. If the second argument is
  26.109 + * <code>NULL</code>, it shall be ignored.
  26.110 +
  26.111 + * <b>Attention:</b> if pointers returned by functions of this type may be
  26.112 + * passed to <code>free()</code> depends on the implementation of the
  26.113 + * respective <code>copy_func</code>.
  26.114 + */
  26.115 +typedef void*(*copy_func)(const void*,void*);
  26.116 +
  26.117 +/**
  26.118 + * Function pointer to a write function.
  26.119 + * 
  26.120 + * The signature of the write function shall be compatible to the signature
  26.121 + * of standard <code>fwrite</code>, though it may use arbitrary data types for
  26.122 + * source and destination.
  26.123 + * 
  26.124 + * The arguments shall contain (in ascending order): a pointer to the source,
  26.125 + * the length of one element, the element count and a pointer to the
  26.126 + * destination.
  26.127 + */
  26.128 +typedef size_t(*write_func)(const void*, size_t, size_t, void*);
  26.129 +
  26.130 +/**
  26.131 + * Function pointer to a read function.
  26.132 + * 
  26.133 + * The signature of the read function shall be compatible to the signature
  26.134 + * of standard <code>fread</code>, though it may use arbitrary data types for
  26.135 + * source and destination.
  26.136 + * 
  26.137 + * The arguments shall contain (in ascending order): a pointer to the
  26.138 + * destination, the length of one element, the element count and a pointer to
  26.139 + * the source.
  26.140 + */
  26.141 +typedef size_t(*read_func)(void*, size_t, size_t, void*);
  26.142 +
  26.143 +#ifdef	__cplusplus
  26.144 +}
  26.145 +#endif
  26.146 +
  26.147 +#endif	/* UCX_H */
  26.148 +
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/src/ucx/utils.h	Tue Oct 17 16:15:41 2017 +0200
    27.3 @@ -0,0 +1,281 @@
    27.4 +/*
    27.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    27.6 + *
    27.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    27.8 + *
    27.9 + * Redistribution and use in source and binary forms, with or without
   27.10 + * modification, are permitted provided that the following conditions are met:
   27.11 + *
   27.12 + *   1. Redistributions of source code must retain the above copyright
   27.13 + *      notice, this list of conditions and the following disclaimer.
   27.14 + *
   27.15 + *   2. Redistributions in binary form must reproduce the above copyright
   27.16 + *      notice, this list of conditions and the following disclaimer in the
   27.17 + *      documentation and/or other materials provided with the distribution.
   27.18 + *
   27.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   27.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   27.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27.29 + * POSSIBILITY OF SUCH DAMAGE.
   27.30 + */
   27.31 +
   27.32 +/**
   27.33 + * @file utils.h
   27.34 + * 
   27.35 + * Compare, copy and printf functions.
   27.36 + * 
   27.37 + * @author Mike Becker
   27.38 + * @author Olaf Wintermann
   27.39 + */
   27.40 +
   27.41 +#ifndef UCX_UTILS_H
   27.42 +#define UCX_UTILS_H
   27.43 +
   27.44 +#ifdef __cplusplus
   27.45 +extern "C" {
   27.46 +#endif
   27.47 +
   27.48 +#include <ucx/ucx.h>
   27.49 +#include <ucx/string.h>
   27.50 +#include <ucx/allocator.h>
   27.51 +#include <inttypes.h>
   27.52 +#include <string.h>
   27.53 +#include <stdarg.h>
   27.54 +
   27.55 +/**
   27.56 + * Default buffer size for ucx_stream_copy() and ucx_stream_ncopy().
   27.57 + */
   27.58 +#define UCX_STREAM_COPY_BUFSIZE 4096
   27.59 +
   27.60 +/**
   27.61 + * Copies a string.
   27.62 + * @param s the string to copy
   27.63 + * @param data omitted
   27.64 + * @return a pointer to a copy of s1 that can be passed to free(void*)
   27.65 + */
   27.66 +void *ucx_strcpy(const void *s, void *data);
   27.67 +
   27.68 +/**
   27.69 + * Copies a memory area.
   27.70 + * @param m a pointer to the memory area
   27.71 + * @param n a pointer to the size_t containing the size of the memory area
   27.72 + * @return a pointer to a copy of the specified memory area that can
   27.73 + * be passed to free(void*)
   27.74 + */
   27.75 +void *ucx_memcpy(const void *m, void *n);
   27.76 +
   27.77 +
   27.78 +/**
   27.79 + * Reads data from a stream and writes it to another stream.
   27.80 + * 
   27.81 + * @param src the source stream
   27.82 + * @param dest the destination stream
   27.83 + * @param rfnc the read function
   27.84 + * @param wfnc the write function
   27.85 + * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer
   27.86 + * shall be implicitly created on the heap
   27.87 + * @param bufsize the size of the copy buffer - if <code>NULL</code> was
   27.88 + * provided for <code>buf</code>, this is the size of the buffer that shall be
   27.89 + * implicitly created
   27.90 + * @param n the maximum number of bytes that shall be copied
   27.91 + * @return the total number of bytes copied
   27.92 +  */
   27.93 +size_t ucx_stream_bncopy(void *src, void *dest, read_func rfnc, write_func wfnc,
   27.94 +        char* buf, size_t bufsize, size_t n);
   27.95 +
   27.96 +/**
   27.97 + * Shorthand for an unbounded ucx_stream_bncopy call using a default buffer.
   27.98 + * 
   27.99 + * @param src the source stream
  27.100 + * @param dest the destination stream
  27.101 + * @param rfnc the read function
  27.102 + * @param wfnc the write function
  27.103 + * @return total number of bytes copied
  27.104 + * 
  27.105 + * @see #UCX_STREAM_COPY_BUFSIZE
  27.106 + */
  27.107 +#define ucx_stream_copy(src,dest,rfnc,wfnc) ucx_stream_bncopy(\
  27.108 +        src, dest, (read_func)rfnc, (write_func)wfnc, \
  27.109 +        NULL, UCX_STREAM_COPY_BUFSIZE, (size_t)-1)
  27.110 +
  27.111 +/**
  27.112 + * Shorthand for ucx_stream_bncopy using a default copy buffer.
  27.113 + * 
  27.114 + * @param src the source stream
  27.115 + * @param dest the destination stream
  27.116 + * @param rfnc the read function
  27.117 + * @param wfnc the write function
  27.118 + * @param n maximum number of bytes that shall be copied
  27.119 + * @return total number of bytes copied
  27.120 + */
  27.121 +#define ucx_stream_ncopy(src,dest,rfnc,wfnc, n) ucx_stream_bncopy(\
  27.122 +        src, dest, (read_func)rfnc, (write_func)wfnc, \
  27.123 +        NULL, UCX_STREAM_COPY_BUFSIZE, n)
  27.124 +
  27.125 +/**
  27.126 + * Shorthand for an unbounded ucx_stream_bncopy call using the specified buffer.
  27.127 + * 
  27.128 + * @param src the source stream
  27.129 + * @param dest the destination stream
  27.130 + * @param rfnc the read function
  27.131 + * @param wfnc the write function
  27.132 + * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer
  27.133 + * shall be implicitly created on the heap
  27.134 + * @param bufsize the size of the copy buffer - if <code>NULL</code> was
  27.135 + * provided for <code>buf</code>, this is the size of the buffer that shall be
  27.136 + * implicitly created
  27.137 + * @return total number of bytes copied
  27.138 + */
  27.139 +#define ucx_stream_bcopy(src,dest,rfnc,wfnc, buf, bufsize) ucx_stream_bncopy(\
  27.140 +        src, dest, (read_func)rfnc, (write_func)wfnc, \
  27.141 +        buf, bufsize, (size_t)-1)
  27.142 +
  27.143 +/**
  27.144 + * Wraps the strcmp function.
  27.145 + * @param s1 string one
  27.146 + * @param s2 string two
  27.147 + * @param data omitted
  27.148 + * @return the result of strcmp(s1, s2)
  27.149 + */
  27.150 +int ucx_strcmp(const void *s1, const void *s2, void *data);
  27.151 +
  27.152 +/**
  27.153 + * Wraps the strncmp function.
  27.154 + * @param s1 string one
  27.155 + * @param s2 string two
  27.156 + * @param n a pointer to the size_t containing the third strncmp parameter
  27.157 + * @return the result of strncmp(s1, s2, *n)
  27.158 + */
  27.159 +int ucx_strncmp(const void *s1, const void *s2, void *n);
  27.160 +
  27.161 +/**
  27.162 + * Compares two integers of type int.
  27.163 + * @param i1 pointer to integer one
  27.164 + * @param i2 pointer to integer two
  27.165 + * @param data omitted
  27.166 + * @return -1, if *i1 is less than *i2, 0 if both are equal,
  27.167 + * 1 if *i1 is greater than *i2
  27.168 + */
  27.169 +int ucx_intcmp(const void *i1, const void *i2, void *data);
  27.170 +
  27.171 +/**
  27.172 + * Compares two real numbers of type float.
  27.173 + * @param f1 pointer to float one
  27.174 + * @param f2 pointer to float two
  27.175 + * @param data if provided: a pointer to precision (default: 1e-6f)
  27.176 + * @return -1, if *f1 is less than *f2, 0 if both are equal,
  27.177 + * 1 if *f1 is greater than *f2
  27.178 + */
  27.179 +
  27.180 +int ucx_floatcmp(const void *f1, const void *f2, void *data);
  27.181 +
  27.182 +/**
  27.183 + * Compares two real numbers of type double.
  27.184 + * @param d1 pointer to double one
  27.185 + * @param d2 pointer to double two
  27.186 + * @param data if provided: a pointer to precision (default: 1e-14)
  27.187 + * @return -1, if *d1 is less than *d2, 0 if both are equal,
  27.188 + * 1 if *d1 is greater than *d2
  27.189 + */
  27.190 +int ucx_doublecmp(const void *d1, const void *d2, void *data);
  27.191 +
  27.192 +/**
  27.193 + * Compares two pointers.
  27.194 + * @param ptr1 pointer one
  27.195 + * @param ptr2 pointer two
  27.196 + * @param data omitted
  27.197 + * @return -1 if ptr1 is less than ptr2, 0 if both are equal,
  27.198 + * 1 if ptr1 is greater than ptr2
  27.199 + */
  27.200 +int ucx_ptrcmp(const void *ptr1, const void *ptr2, void *data);
  27.201 +
  27.202 +/**
  27.203 + * Compares two memory areas.
  27.204 + * @param ptr1 pointer one
  27.205 + * @param ptr2 pointer two
  27.206 + * @param n a pointer to the size_t containing the third parameter for memcmp
  27.207 + * @return the result of memcmp(ptr1, ptr2, *n)
  27.208 + */
  27.209 +int ucx_memcmp(const void *ptr1, const void *ptr2, void *n);
  27.210 +
  27.211 +/**
  27.212 + * A <code>printf()</code> like function which writes the output to a stream by
  27.213 + * using a write_func().
  27.214 + * @param stream the stream the data is written to
  27.215 + * @param wfc the write function
  27.216 + * @param fmt format string
  27.217 + * @param ... additional arguments
  27.218 + * @return the total number of bytes written
  27.219 + */
  27.220 +int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...);
  27.221 +
  27.222 +/**
  27.223 + * <code>va_list</code> version of ucx_fprintf().
  27.224 + * @param stream the stream the data is written to
  27.225 + * @param wfc the write function
  27.226 + * @param fmt format string
  27.227 + * @param ap argument list
  27.228 + * @return the total number of bytes written
  27.229 + * @see ucx_fprintf()
  27.230 + */
  27.231 +int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap);
  27.232 +
  27.233 +/**
  27.234 + * A <code>printf()</code> like function which allocates space for a sstr_t
  27.235 + * the result is written to.
  27.236 + * 
  27.237 + * <b>Attention</b>: The sstr_t data is allocated with the allocators
  27.238 + * ucx_allocator_malloc() function. So it is implementation dependent, if
  27.239 + * the returned sstr_t.ptr pointer must be passed to the allocators
  27.240 + * ucx_allocator_free() function manually.
  27.241 + * 
  27.242 + * <b>Note</b>: The sstr_t.ptr of the return value will <i>always</i> be
  27.243 + * <code>NULL</code>-terminated.
  27.244 + * 
  27.245 + * @param allocator the UcxAllocator used for allocating the result sstr_t
  27.246 + * @param fmt format string
  27.247 + * @param ... additional arguments
  27.248 + * @return a sstr_t containing the formatted string
  27.249 + */
  27.250 +sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...);
  27.251 +
  27.252 +/**
  27.253 + * <code>va_list</code> version of ucx_asprintf().
  27.254 + * 
  27.255 + * @param allocator the UcxAllocator used for allocating the result sstr_t
  27.256 + * @param fmt format string
  27.257 + * @param ap argument list
  27.258 + * @return a sstr_t containing the formatted string
  27.259 + * @see ucx_asprintf()
  27.260 + */
  27.261 +sstr_t ucx_vasprintf(UcxAllocator *allocator, const char *fmt, va_list ap);
  27.262 +
  27.263 +/** Shortcut for ucx_asprintf() with default allocator. */
  27.264 +#define ucx_sprintf(...) \
  27.265 +    ucx_asprintf(ucx_default_allocator(), __VA_ARGS__)
  27.266 +
  27.267 +/**
  27.268 + * A <code>printf()</code> like function which writes the output to a
  27.269 + * UcxBuffer.
  27.270 + * 
  27.271 + * @param buffer the buffer the data is written to
  27.272 + * @param ... format string and additional arguments
  27.273 + * @return the total number of bytes written
  27.274 + * @see ucx_fprintf()
  27.275 + */
  27.276 +#define ucx_bprintf(buffer, ...) ucx_fprintf((UcxBuffer*)buffer, \
  27.277 +        (write_func)ucx_buffer_write, __VA_ARGS__)
  27.278 +
  27.279 +#ifdef __cplusplus
  27.280 +}
  27.281 +#endif
  27.282 +
  27.283 +#endif /* UCX_UTILS_H */
  27.284 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/utils.c	Tue Oct 17 16:15:41 2017 +0200
    28.3 @@ -0,0 +1,260 @@
    28.4 +/*
    28.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    28.6 + *
    28.7 + * Copyright 2017 Olaf Wintermann. All rights reserved.
    28.8 + *
    28.9 + * Redistribution and use in source and binary forms, with or without
   28.10 + * modification, are permitted provided that the following conditions are met:
   28.11 + *
   28.12 + *   1. Redistributions of source code must retain the above copyright
   28.13 + *      notice, this list of conditions and the following disclaimer.
   28.14 + *
   28.15 + *   2. Redistributions in binary form must reproduce the above copyright
   28.16 + *      notice, this list of conditions and the following disclaimer in the
   28.17 + *      documentation and/or other materials provided with the distribution.
   28.18 + *
   28.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   28.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   28.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   28.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28.29 + * POSSIBILITY OF SUCH DAMAGE.
   28.30 + */
   28.31 +
   28.32 +#include "ucx/utils.h"
   28.33 +
   28.34 +#include <math.h>
   28.35 +#include <stdio.h>
   28.36 +#include <limits.h>
   28.37 +#include <errno.h>
   28.38 +
   28.39 +/* COPY FUCNTIONS */
   28.40 +void* ucx_strcpy(const void* s, void* data) {
   28.41 +    const char *str = (const char*) s;
   28.42 +    size_t n = 1+strlen(str);
   28.43 +    char *cpy = (char*) malloc(n);
   28.44 +    memcpy(cpy, str, n);
   28.45 +    return cpy;
   28.46 +}
   28.47 +
   28.48 +void* ucx_memcpy(const void* m, void* n) {
   28.49 +    size_t k = *((size_t*)n);
   28.50 +    void *cpy = malloc(k);
   28.51 +    memcpy(cpy, m, k);
   28.52 +    return cpy;
   28.53 +}
   28.54 +
   28.55 +size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc,
   28.56 +        write_func writefnc, char* buf, size_t bufsize, size_t n) {
   28.57 +    if(n == 0 || bufsize == 0) {
   28.58 +        return 0;
   28.59 +    }
   28.60 +    
   28.61 +    char *lbuf;    
   28.62 +    size_t ncp = 0;
   28.63 +    
   28.64 +    if(buf) {
   28.65 +        lbuf = buf;
   28.66 +    } else {
   28.67 +        lbuf = (char*)malloc(bufsize);
   28.68 +        if(lbuf == NULL) {
   28.69 +            return 0;
   28.70 +        }
   28.71 +    }
   28.72 +    
   28.73 +    size_t r;
   28.74 +    size_t rn = bufsize > n ? n : bufsize;
   28.75 +    while((r = readfnc(lbuf, 1, rn, src)) != 0) {
   28.76 +        r = writefnc(lbuf, 1, r, dest);
   28.77 +        ncp += r;
   28.78 +        n -= r;
   28.79 +        rn = bufsize > n ? n : bufsize;
   28.80 +        if(r == 0 || n == 0) {
   28.81 +            break;
   28.82 +        }
   28.83 +    }
   28.84 +    
   28.85 +    if (lbuf != buf) {
   28.86 +        free(lbuf);
   28.87 +    }
   28.88 +    
   28.89 +    return ncp;
   28.90 +}
   28.91 +
   28.92 +/* COMPARE FUNCTIONS */
   28.93 +
   28.94 +int ucx_strcmp(const void *s1, const void *s2, void *data) {
   28.95 +    return strcmp((const char*)s1, (const char*)s2);
   28.96 +}
   28.97 +
   28.98 +int ucx_strncmp(const void *s1, const void *s2, void *n) {
   28.99 +    return strncmp((const char*)s1, (const char*)s2, *((size_t*) n));
  28.100 +}
  28.101 +
  28.102 +int ucx_intcmp(const void *i1, const void *i2, void *data) {
  28.103 +   int a = *((const int*) i1);
  28.104 +   int b = *((const int*) i2);
  28.105 +   if (a == b) {
  28.106 +       return 0;
  28.107 +   } else {
  28.108 +       return a < b ? -1 : 1;
  28.109 +   }
  28.110 +}
  28.111 +
  28.112 +int ucx_floatcmp(const void *f1, const void *f2, void *epsilon) {
  28.113 +   float a = *((const float*) f1);
  28.114 +   float b = *((const float*) f2);
  28.115 +   float e = !epsilon ? 1e-6f : *((float*)epsilon);
  28.116 +   if (fabsf(a - b) < e) {
  28.117 +       return 0;
  28.118 +   } else {
  28.119 +       return a < b ? -1 : 1;
  28.120 +   }
  28.121 +}
  28.122 +
  28.123 +int ucx_doublecmp(const void *d1, const void *d2, void *epsilon) {
  28.124 +   double a = *((const double*) d1);
  28.125 +   double b = *((const double*) d2);
  28.126 +   double e = !epsilon ? 1e-14 : *((double*)epsilon);
  28.127 +   if (fabs(a - b) < e) {
  28.128 +       return 0;
  28.129 +   } else {
  28.130 +       return a < b ? -1 : 1;
  28.131 +   }
  28.132 +}
  28.133 +
  28.134 +int ucx_ptrcmp(const void *ptr1, const void *ptr2, void *data) {
  28.135 +    const intptr_t p1 = (const intptr_t) ptr1;
  28.136 +    const intptr_t p2 = (const intptr_t) ptr2;
  28.137 +    if (p1 == p2) {
  28.138 +        return 0;
  28.139 +    } else {
  28.140 +        return p1  < p2 ? -1 : 1;
  28.141 +    }
  28.142 +}
  28.143 +
  28.144 +int ucx_memcmp(const void *ptr1, const void *ptr2, void *n) {
  28.145 +    return memcmp(ptr1, ptr2, *((size_t*)n));
  28.146 +}
  28.147 +
  28.148 +/* PRINTF FUNCTIONS */
  28.149 +
  28.150 +#ifdef va_copy
  28.151 +#define UCX_PRINTF_BUFSIZE 256
  28.152 +#else
  28.153 +#pragma message("WARNING: C99 va_copy macro not supported by this platform" \
  28.154 +                " - limiting ucx_*printf to 2 KiB")
  28.155 +#define UCX_PRINTF_BUFSIZE 0x800
  28.156 +#endif
  28.157 +
  28.158 +int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) {
  28.159 +    int ret;
  28.160 +    va_list ap;
  28.161 +    va_start(ap, fmt);
  28.162 +    ret = ucx_vfprintf(stream, wfc, fmt, ap);
  28.163 +    va_end(ap);
  28.164 +    return ret;
  28.165 +}
  28.166 +
  28.167 +int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) {
  28.168 +    char buf[UCX_PRINTF_BUFSIZE];
  28.169 +#ifdef va_copy
  28.170 +    va_list ap2;
  28.171 +    va_copy(ap2, ap);
  28.172 +    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  28.173 +    if (ret < 0) {
  28.174 +        return ret;
  28.175 +    } else if (ret < UCX_PRINTF_BUFSIZE) {
  28.176 +        return (int)wfc(buf, 1, ret, stream);
  28.177 +    } else {
  28.178 +        if (ret == INT_MAX) {
  28.179 +            errno = ENOMEM;
  28.180 +            return -1;
  28.181 +        }
  28.182 +        
  28.183 +        int len = ret + 1;
  28.184 +        char *newbuf = (char*)malloc(len);
  28.185 +        if (!newbuf) {
  28.186 +            return -1;
  28.187 +        }
  28.188 +        
  28.189 +        ret = vsnprintf(newbuf, len, fmt, ap2);
  28.190 +        if (ret > 0) {
  28.191 +            ret = (int)wfc(newbuf, 1, ret, stream);
  28.192 +        }
  28.193 +        free(newbuf);
  28.194 +    }
  28.195 +    return ret;
  28.196 +#else
  28.197 +    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  28.198 +    if (ret < 0) {
  28.199 +        return ret;
  28.200 +    } else if (ret < UCX_PRINTF_BUFSIZE) {
  28.201 +        return (int)wfc(buf, 1, ret, stream);
  28.202 +    } else {
  28.203 +        errno = ENOMEM;
  28.204 +        return -1;
  28.205 +    }
  28.206 +#endif
  28.207 +}
  28.208 +
  28.209 +sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) {
  28.210 +    va_list ap;
  28.211 +    sstr_t ret;
  28.212 +    va_start(ap, fmt);
  28.213 +    ret = ucx_vasprintf(allocator, fmt, ap);
  28.214 +    va_end(ap);
  28.215 +    return ret;
  28.216 +}
  28.217 +
  28.218 +sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) {
  28.219 +    sstr_t s;
  28.220 +    s.ptr = NULL;
  28.221 +    s.length = 0;
  28.222 +    char buf[UCX_PRINTF_BUFSIZE];
  28.223 +#ifdef va_copy
  28.224 +    va_list ap2;
  28.225 +    va_copy(ap2, ap);
  28.226 +    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  28.227 +    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
  28.228 +        s.ptr = (char*)almalloc(a, ret + 1);
  28.229 +        if (s.ptr) {
  28.230 +            s.length = (size_t)ret;
  28.231 +            memcpy(s.ptr, buf, ret);
  28.232 +            s.ptr[s.length] = '\0';
  28.233 +        }
  28.234 +    } else if (ret == INT_MAX) {
  28.235 +        errno = ENOMEM;
  28.236 +    } else  {
  28.237 +        int len = ret + 1;
  28.238 +        s.ptr = (char*)almalloc(a, len);
  28.239 +        if (s.ptr) {
  28.240 +            ret = vsnprintf(s.ptr, len, fmt, ap2);
  28.241 +            if (ret < 0) {
  28.242 +                free(s.ptr);
  28.243 +                s.ptr = NULL;
  28.244 +            } else {
  28.245 +                s.length = (size_t)ret;
  28.246 +            }
  28.247 +        }
  28.248 +    }
  28.249 +#else
  28.250 +    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  28.251 +    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
  28.252 +        s.ptr = (char*)almalloc(a, ret + 1);
  28.253 +        if (s.ptr) {
  28.254 +            s.length = (size_t)ret;
  28.255 +            memcpy(s.ptr, buf, ret);
  28.256 +            s.ptr[s.length] = '\0';
  28.257 +        }
  28.258 +    } else {
  28.259 +        errno = ENOMEM;
  28.260 +    }
  28.261 +#endif
  28.262 +    return s;
  28.263 +}
    29.1 --- a/test/Makefile	Tue Oct 17 15:15:54 2017 +0200
    29.2 +++ b/test/Makefile	Tue Oct 17 16:15:41 2017 +0200
    29.3 @@ -52,7 +52,7 @@
    29.4  		$(OBJ) ../build/release/libucx$(LIB_EXT)
    29.5  
    29.6  ../build/release/test/%$(OBJ_EXT): %.c
    29.7 -	$(CC) $(CFLAGS) -I../ -o $@ -c $<
    29.8 +	$(CC) $(CFLAGS) -I../src/ -o $@ -c $<
    29.9  
   29.10  ../build/release/test:
   29.11  	$(MKDIR) $(MKDIRFLAGS) ../build/release/test
   29.12 @@ -62,7 +62,7 @@
   29.13  		$(OBJ_D) ../build/debug/libucx$(LIB_EXT)
   29.14  
   29.15  ../build/debug/test/%$(OBJ_EXT): %.c
   29.16 -	$(CC) $(CFLAGS_D) -I../ -o $@ -c $<
   29.17 +	$(CC) $(CFLAGS_D) -I../src/ -o $@ -c $<
   29.18  
   29.19  ../build/debug/test:
   29.20  	$(MKDIR) $(MKDIRFLAGS) ../build/debug/test
    30.1 --- a/test/allocator_tests.h	Tue Oct 17 15:15:54 2017 +0200
    30.2 +++ b/test/allocator_tests.h	Tue Oct 17 16:15:41 2017 +0200
    30.3 @@ -29,8 +29,8 @@
    30.4  #ifndef ALLOCATOR_TEST_H
    30.5  #define	ALLOCATOR_TEST_H
    30.6  
    30.7 -#include "ucx/test.h"
    30.8 -#include "ucx/allocator.h"
    30.9 +#include <ucx/test.h>
   30.10 +#include <ucx/allocator.h>
   30.11  
   30.12  #ifdef	__cplusplus
   30.13  extern "C" {
    31.1 --- a/test/avl_tests.c	Tue Oct 17 15:15:54 2017 +0200
    31.2 +++ b/test/avl_tests.c	Tue Oct 17 16:15:41 2017 +0200
    31.3 @@ -28,7 +28,7 @@
    31.4  
    31.5  #include "avl_tests.h"
    31.6  
    31.7 -#include "ucx/utils.h"
    31.8 +#include <ucx/utils.h>
    31.9  
   31.10  static int node_height(UcxAVLNode *node) {
   31.11      if(!node) {
    32.1 --- a/test/avl_tests.h	Tue Oct 17 15:15:54 2017 +0200
    32.2 +++ b/test/avl_tests.h	Tue Oct 17 16:15:41 2017 +0200
    32.3 @@ -29,8 +29,8 @@
    32.4  #ifndef AVL_TEST_H
    32.5  #define	AVL_TEST_H
    32.6  
    32.7 -#include "ucx/test.h"
    32.8 -#include "ucx/avl.h"
    32.9 +#include <ucx/test.h>
   32.10 +#include <ucx/avl.h>
   32.11  
   32.12  #ifdef	__cplusplus
   32.13  extern "C" {
    33.1 --- a/test/buffer_tests.h	Tue Oct 17 15:15:54 2017 +0200
    33.2 +++ b/test/buffer_tests.h	Tue Oct 17 16:15:41 2017 +0200
    33.3 @@ -29,8 +29,8 @@
    33.4  #ifndef BUFFER_TEST_H
    33.5  #define	BUFFER_TEST_H
    33.6  
    33.7 -#include "ucx/test.h"
    33.8 -#include "ucx/buffer.h"
    33.9 +#include <ucx/test.h>
   33.10 +#include <ucx/buffer.h>
   33.11  
   33.12  #ifdef	__cplusplus
   33.13  extern "C" {
    34.1 --- a/test/list_tests.c	Tue Oct 17 15:15:54 2017 +0200
    34.2 +++ b/test/list_tests.c	Tue Oct 17 16:15:41 2017 +0200
    34.3 @@ -27,7 +27,7 @@
    34.4   */
    34.5  
    34.6  #include "list_tests.h"
    34.7 -#include "ucx/utils.h"
    34.8 +#include <ucx/utils.h>
    34.9  
   34.10  UCX_TEST(test_ucx_list_append) {
   34.11      UcxList *list, *first;
    35.1 --- a/test/list_tests.h	Tue Oct 17 15:15:54 2017 +0200
    35.2 +++ b/test/list_tests.h	Tue Oct 17 16:15:41 2017 +0200
    35.3 @@ -29,10 +29,8 @@
    35.4  #ifndef LIST_TESTS_H
    35.5  #define	LIST_TESTS_H
    35.6  
    35.7 -#include "main.h"
    35.8 -
    35.9 -#include "ucx/list.h"
   35.10 -#include "ucx/test.h"
   35.11 +#include <ucx/list.h>
   35.12 +#include <ucx/test.h>
   35.13  
   35.14  #ifdef	__cplusplus
   35.15  extern "C" {
    36.1 --- a/test/logging_tests.h	Tue Oct 17 15:15:54 2017 +0200
    36.2 +++ b/test/logging_tests.h	Tue Oct 17 16:15:41 2017 +0200
    36.3 @@ -29,8 +29,8 @@
    36.4  #ifndef LOGGING_TESTS_H
    36.5  #define	LOGGING_TESTS_H
    36.6  
    36.7 -#include "ucx/test.h"
    36.8 -#include "ucx/logging.h"
    36.9 +#include <ucx/test.h>
   36.10 +#include <ucx/logging.h>
   36.11  
   36.12  #ifdef	__cplusplus
   36.13  extern "C" {
    37.1 --- a/test/main.c	Tue Oct 17 15:15:54 2017 +0200
    37.2 +++ b/test/main.c	Tue Oct 17 16:15:41 2017 +0200
    37.3 @@ -29,7 +29,7 @@
    37.4  #include <stdio.h>
    37.5  #include <stdlib.h>
    37.6  
    37.7 -#include "ucx/test.h"
    37.8 +#include <ucx/test.h>
    37.9  
   37.10  #include "main.h"
   37.11  
    38.1 --- a/test/map_tests.h	Tue Oct 17 15:15:54 2017 +0200
    38.2 +++ b/test/map_tests.h	Tue Oct 17 16:15:41 2017 +0200
    38.3 @@ -29,8 +29,8 @@
    38.4  #ifndef MAP_TESTS_H
    38.5  #define	MAP_TESTS_H
    38.6  
    38.7 -#include "ucx/test.h"
    38.8 -#include "ucx/map.h"
    38.9 +#include <ucx/test.h>
   38.10 +#include <ucx/map.h>
   38.11  
   38.12  #ifdef	__cplusplus
   38.13  extern "C" {
    39.1 --- a/test/mpool_tests.h	Tue Oct 17 15:15:54 2017 +0200
    39.2 +++ b/test/mpool_tests.h	Tue Oct 17 16:15:41 2017 +0200
    39.3 @@ -29,8 +29,8 @@
    39.4  #ifndef MPOOL_TESTS_H
    39.5  #define	MPOOL_TESTS_H
    39.6  
    39.7 -#include "ucx/test.h"
    39.8 -#include "ucx/mempool.h"
    39.9 +#include <ucx/test.h>
   39.10 +#include <ucx/mempool.h>
   39.11  
   39.12  #ifdef	__cplusplus
   39.13  extern "C" {
    40.1 --- a/test/prop_tests.c	Tue Oct 17 15:15:54 2017 +0200
    40.2 +++ b/test/prop_tests.c	Tue Oct 17 16:15:41 2017 +0200
    40.3 @@ -27,7 +27,7 @@
    40.4   */
    40.5  
    40.6  #include "prop_tests.h"
    40.7 -#include "ucx/mempool.h"
    40.8 +#include <ucx/mempool.h>
    40.9  
   40.10  UCX_TEST(test_ucx_properties_new) {
   40.11      UcxProperties *parser = ucx_properties_new();
    41.1 --- a/test/prop_tests.h	Tue Oct 17 15:15:54 2017 +0200
    41.2 +++ b/test/prop_tests.h	Tue Oct 17 16:15:41 2017 +0200
    41.3 @@ -29,8 +29,8 @@
    41.4  #ifndef PROP_TESTS_H
    41.5  #define	PROP_TESTS_H
    41.6  
    41.7 -#include "ucx/test.h"
    41.8 -#include "ucx/properties.h"
    41.9 +#include <ucx/test.h>
   41.10 +#include <ucx/properties.h>
   41.11  
   41.12  #ifdef	__cplusplus
   41.13  extern "C" {
    42.1 --- a/test/stack_tests.h	Tue Oct 17 15:15:54 2017 +0200
    42.2 +++ b/test/stack_tests.h	Tue Oct 17 16:15:41 2017 +0200
    42.3 @@ -29,8 +29,8 @@
    42.4  #ifndef STACK_TESTS_H
    42.5  #define	STACK_TESTS_H
    42.6  
    42.7 -#include "ucx/test.h"
    42.8 -#include "ucx/stack.h"
    42.9 +#include <ucx/test.h>
   42.10 +#include <ucx/stack.h>
   42.11  
   42.12  #ifdef	__cplusplus
   42.13  extern "C" {
    43.1 --- a/test/string_tests.h	Tue Oct 17 15:15:54 2017 +0200
    43.2 +++ b/test/string_tests.h	Tue Oct 17 16:15:41 2017 +0200
    43.3 @@ -29,8 +29,8 @@
    43.4  #ifndef STRING_TESTS_H
    43.5  #define	STRING_TESTS_H
    43.6  
    43.7 -#include "ucx/test.h"
    43.8 -#include "ucx/string.h"
    43.9 +#include <ucx/test.h>
   43.10 +#include <ucx/string.h>
   43.11  
   43.12  #ifdef	__cplusplus
   43.13  extern "C" {
    44.1 --- a/test/utils_tests.c	Tue Oct 17 15:15:54 2017 +0200
    44.2 +++ b/test/utils_tests.c	Tue Oct 17 16:15:41 2017 +0200
    44.3 @@ -27,7 +27,7 @@
    44.4   */
    44.5  
    44.6  #include "utils_tests.h"
    44.7 -#include "ucx/buffer.h"
    44.8 +#include <ucx/buffer.h>
    44.9  
   44.10  UCX_TEST(test_ucx_fprintf) {
   44.11      UcxBuffer *b1 = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND);
    45.1 --- a/test/utils_tests.h	Tue Oct 17 15:15:54 2017 +0200
    45.2 +++ b/test/utils_tests.h	Tue Oct 17 16:15:41 2017 +0200
    45.3 @@ -29,8 +29,8 @@
    45.4  #ifndef UTILS_TESTS_H
    45.5  #define	UTILS_TESTS_H
    45.6  
    45.7 -#include "ucx/test.h"
    45.8 -#include "ucx/utils.h"
    45.9 +#include <ucx/test.h>
   45.10 +#include <ucx/utils.h>
   45.11  
   45.12  #ifdef	__cplusplus
   45.13  extern "C" {
    46.1 --- a/ucx/Makefile	Tue Oct 17 15:15:54 2017 +0200
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,79 +0,0 @@
    46.4 -#
    46.5 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 -#
    46.7 -# Copyright 2017 Olaf Wintermann. All rights reserved.
    46.8 -#
    46.9 -# Redistribution and use in source and binary forms, with or without
   46.10 -# modification, are permitted provided that the following conditions are met:
   46.11 -#
   46.12 -#   1. Redistributions of source code must retain the above copyright
   46.13 -#      notice, this list of conditions and the following disclaimer.
   46.14 -#
   46.15 -#   2. Redistributions in binary form must reproduce the above copyright
   46.16 -#      notice, this list of conditions and the following disclaimer in the
   46.17 -#      documentation and/or other materials provided with the distribution.
   46.18 -#
   46.19 -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   46.20 -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   46.21 -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   46.22 -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   46.23 -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   46.24 -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   46.25 -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   46.26 -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   46.27 -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   46.28 -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   46.29 -# POSSIBILITY OF SUCH DAMAGE.
   46.30 -#
   46.31 -
   46.32 -include ../$(CONF).mk
   46.33 -include ../cppcheck.mk
   46.34 -
   46.35 -# list of source files
   46.36 -SRC  = utils.c
   46.37 -SRC += list.c
   46.38 -SRC += map.c
   46.39 -SRC += avl.c
   46.40 -SRC += properties.c
   46.41 -SRC += mempool.c
   46.42 -SRC += string.c
   46.43 -SRC += test.c
   46.44 -SRC += allocator.c
   46.45 -SRC += logging.c
   46.46 -SRC += buffer.c
   46.47 -SRC += stack.c
   46.48 -
   46.49 -OBJ   = $(SRC:%.c=../build/release/ucx/%$(OBJ_EXT))
   46.50 -OBJ_D = $(SRC:%.c=../build/debug/ucx/%$(OBJ_EXT))
   46.51 -
   46.52 -all: ../build/release/ucx \
   46.53 -	../build/release/libucx$(LIB_EXT) ../build/release/libucx$(SO_EXT)
   46.54 -debug: ../build/debug/ucx \
   46.55 -	../build/debug/libucx$(LIB_EXT) ../build/debug/libucx$(SO_EXT)
   46.56 -
   46.57 -../build/release/libucx$(LIB_EXT): $(OBJ)
   46.58 -	$(AR) $(ARFLAGS) ../build/release/libucx$(LIB_EXT) $(OBJ)
   46.59 -
   46.60 -../build/release/libucx$(SO_EXT): $(OBJ)
   46.61 -	$(LD) $(SOLDFLAGS) -o ../build/release/libucx$(SO_EXT) $(OBJ)
   46.62 -
   46.63 -../build/release/ucx/%$(OBJ_EXT): %.c
   46.64 -	$(CC) $(CFLAGS) -o $@ -c $<
   46.65 -
   46.66 -../build/release/ucx:
   46.67 -	$(MKDIR) $(MKDIRFLAGS) ../build/release/ucx
   46.68 -
   46.69 -../build/debug/libucx$(LIB_EXT): $(OBJ_D)
   46.70 -	$(AR) $(ARFLAGS) ../build/debug/libucx$(LIB_EXT) $(OBJ_D)
   46.71 -	
   46.72 -../build/debug/libucx$(SO_EXT): $(OBJ_D)
   46.73 -	$(LD) $(SOLDFLAGS) -o ../build/debug/libucx$(SO_EXT) $(OBJ_D)
   46.74 -
   46.75 -../build/debug/ucx/%$(OBJ_EXT): %.c
   46.76 -	$(CC) $(CFLAGS_D) -o $@ -c $<
   46.77 -
   46.78 -../build/debug/ucx:
   46.79 -	$(MKDIR) $(MKDIRFLAGS) ../build/debug/ucx
   46.80 -
   46.81 -cppcheck: $(SRC)
   46.82 -	$(CPPCHECK) $(CPPCHECK_CONFIG) $(CPPCHECK_FLAGS) $+ 2>> ../$(CPPCHECK_LOG)
    47.1 --- a/ucx/allocator.c	Tue Oct 17 15:15:54 2017 +0200
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,59 +0,0 @@
    47.4 -/*
    47.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    47.6 - *
    47.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    47.8 - *
    47.9 - * Redistribution and use in source and binary forms, with or without
   47.10 - * modification, are permitted provided that the following conditions are met:
   47.11 - *
   47.12 - *   1. Redistributions of source code must retain the above copyright
   47.13 - *      notice, this list of conditions and the following disclaimer.
   47.14 - *
   47.15 - *   2. Redistributions in binary form must reproduce the above copyright
   47.16 - *      notice, this list of conditions and the following disclaimer in the
   47.17 - *      documentation and/or other materials provided with the distribution.
   47.18 - *
   47.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   47.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   47.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   47.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   47.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   47.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   47.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   47.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   47.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   47.29 - * POSSIBILITY OF SUCH DAMAGE.
   47.30 - */
   47.31 -
   47.32 -#include <stdlib.h>
   47.33 -#include "allocator.h"
   47.34 -
   47.35 -UcxAllocator default_allocator = {
   47.36 -    NULL,
   47.37 -    ucx_default_malloc,
   47.38 -    ucx_default_calloc,
   47.39 -    ucx_default_realloc,
   47.40 -    ucx_default_free
   47.41 -};
   47.42 -
   47.43 -UcxAllocator *ucx_default_allocator() {
   47.44 -    UcxAllocator *allocator = &default_allocator;
   47.45 -    return allocator;
   47.46 -}
   47.47 -
   47.48 -void *ucx_default_malloc(void *ignore, size_t n) {
   47.49 -    return malloc(n);
   47.50 -}
   47.51 -
   47.52 -void *ucx_default_calloc(void *ignore, size_t n, size_t size) {
   47.53 -    return calloc(n, size);
   47.54 -}
   47.55 -
   47.56 -void *ucx_default_realloc(void *ignore, void *data, size_t n) {
   47.57 -    return realloc(data, n);
   47.58 -}
   47.59 -
   47.60 -void ucx_default_free(void *ignore, void *data) {
   47.61 -    free(data);
   47.62 -}
    48.1 --- a/ucx/allocator.h	Tue Oct 17 15:15:54 2017 +0200
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,206 +0,0 @@
    48.4 -/*
    48.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    48.6 - *
    48.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    48.8 - *
    48.9 - * Redistribution and use in source and binary forms, with or without
   48.10 - * modification, are permitted provided that the following conditions are met:
   48.11 - *
   48.12 - *   1. Redistributions of source code must retain the above copyright
   48.13 - *      notice, this list of conditions and the following disclaimer.
   48.14 - *
   48.15 - *   2. Redistributions in binary form must reproduce the above copyright
   48.16 - *      notice, this list of conditions and the following disclaimer in the
   48.17 - *      documentation and/or other materials provided with the distribution.
   48.18 - *
   48.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   48.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   48.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   48.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   48.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   48.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   48.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   48.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   48.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   48.29 - * POSSIBILITY OF SUCH DAMAGE.
   48.30 - */
   48.31 -/**
   48.32 - * Allocator for custom memory management.
   48.33 - * 
   48.34 - * A UCX allocator consists of a pointer to the memory area / pool and four
   48.35 - * function pointers to memory management functions operating on this memory
   48.36 - * area / pool. These functions shall behave equivalent to the standard libc
   48.37 - * functions <code>malloc(), calloc(), realloc()</code> and <code>free()</code>.
   48.38 - * 
   48.39 - * The signature of the memory management functions is based on the signature
   48.40 - * of the respective libc function but each of them takes the pointer to the
   48.41 - * memory area / pool as first argument.
   48.42 - * 
   48.43 - * As the pointer to the memory area / pool can be arbitrarily chosen, any data
   48.44 - * can be provided to the memory management functions. A UcxMempool is just
   48.45 - * one example.
   48.46 - * 
   48.47 - * @see mempool.h
   48.48 - * @see UcxMap
   48.49 - * 
   48.50 - * @file   allocator.h
   48.51 - * @author Mike Becker
   48.52 - * @author Olaf Wintermann
   48.53 - */
   48.54 -
   48.55 -#ifndef UCX_ALLOCATOR_H
   48.56 -#define	UCX_ALLOCATOR_H
   48.57 -
   48.58 -#include "ucx.h"
   48.59 -
   48.60 -#ifdef	__cplusplus
   48.61 -extern "C" {
   48.62 -#endif
   48.63 -
   48.64 -/**
   48.65 - * A function pointer to the allocators <code>malloc()</code> function.
   48.66 - * @see UcxAllocator
   48.67 - */
   48.68 -typedef void*(*ucx_allocator_malloc)(void *pool, size_t n);
   48.69 -
   48.70 -/**
   48.71 - * A function pointer to the allocators <code>calloc()</code> function.
   48.72 - * @see UcxAllocator
   48.73 - */
   48.74 -typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size);
   48.75 -
   48.76 -/**
   48.77 - * A function pointer to the allocators <code>realloc()</code> function.
   48.78 - * @see UcxAllocator
   48.79 - */
   48.80 -typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n);
   48.81 -
   48.82 -/**
   48.83 - * A function pointer to the allocators <code>free()</code> function.
   48.84 - * @see UcxAllocator
   48.85 - */
   48.86 -typedef void(*ucx_allocator_free)(void *pool, void *data);
   48.87 -
   48.88 -/**
   48.89 - * UCX allocator data structure containing memory management functions.
   48.90 - */
   48.91 -typedef struct {
   48.92 -    /** Pointer to an area of memory or a complex memory pool.
   48.93 -     * This pointer will be passed to any memory management function as first
   48.94 -     * argument.
   48.95 -     */
   48.96 -    void *pool;
   48.97 -    /**
   48.98 -     * The <code>malloc()</code> function for this allocator.
   48.99 -     */
  48.100 -    ucx_allocator_malloc  malloc;
  48.101 -    /**
  48.102 -     * The <code>calloc()</code> function for this allocator.
  48.103 -     */
  48.104 -    ucx_allocator_calloc  calloc;
  48.105 -    /**
  48.106 -     * The <code>realloc()</code> function for this allocator.
  48.107 -     */
  48.108 -    ucx_allocator_realloc realloc;
  48.109 -    /**
  48.110 -     * The <code>free()</code> function for this allocator.
  48.111 -     */
  48.112 -    ucx_allocator_free    free;
  48.113 -} UcxAllocator;
  48.114 -
  48.115 -/**
  48.116 - * Returns a pointer to the default allocator.
  48.117 - * 
  48.118 - * The default allocator contains wrappers to the standard libc memory
  48.119 - * management functions. Use this function to get a pointer to a globally
  48.120 - * available allocator. You may also define an own UcxAllocator by assigning
  48.121 - * #UCX_ALLOCATOR_DEFAULT to a variable and pass the address of this variable
  48.122 - * to any function that takes a UcxAllocator as argument. Note that using
  48.123 - * this function is the recommended way of passing a default allocator, thus
  48.124 - * it never runs out of scope.
  48.125 - * 
  48.126 - * @return a pointer to the default allocator
  48.127 - * 
  48.128 - * @see UCX_ALLOCATOR_DEFAULT
  48.129 - */
  48.130 -UcxAllocator *ucx_default_allocator();
  48.131 -
  48.132 -/**
  48.133 - * A wrapper for the standard libc <code>malloc()</code> function.
  48.134 - * @param ignore ignored (may be used by allocators for pooled memory)
  48.135 - * @param n argument passed to <code>malloc()</code>
  48.136 - * @return return value of <code>malloc()</code>
  48.137 - */
  48.138 -void *ucx_default_malloc(void *ignore, size_t n);
  48.139 -/**
  48.140 - * A wrapper for the standard libc <code>calloc()</code> function.
  48.141 - * @param ignore ignored (may be used by allocators for pooled memory)
  48.142 - * @param n argument passed to <code>calloc()</code>
  48.143 - * @param size  argument passed to <code>calloc()</code>
  48.144 - * @return return value of <code>calloc()</code>
  48.145 - */
  48.146 -void *ucx_default_calloc(void *ignore, size_t n, size_t size);
  48.147 -/**
  48.148 - * A wrapper for the standard libc <code>realloc()</code> function.
  48.149 - * @param ignore ignored (may be used by allocators for pooled memory)
  48.150 - * @param data argumend passed to <code>realloc()</code>
  48.151 - * @param n argument passed to <code>realloc()</code>
  48.152 - * @return return value of <code>realloc()</code>
  48.153 - */
  48.154 -void *ucx_default_realloc(void *ignore, void *data, size_t n);
  48.155 -/**
  48.156 - * A wrapper for the standard libc <code>free()</code> function.
  48.157 - * @param ignore ignored (may be used by allocators for pooled memory)
  48.158 - * @param data argument passed to <code>free()</code>
  48.159 - */
  48.160 -void ucx_default_free(void *ignore, void *data);
  48.161 -
  48.162 -/**
  48.163 - * Shorthand for calling an allocators malloc function.
  48.164 - * @param allocator the allocator to use
  48.165 - * @param n size of space to allocate
  48.166 - * @return a pointer to the allocated memory area
  48.167 - */
  48.168 -#define almalloc(allocator, n) ((allocator)->malloc((allocator)->pool, n))
  48.169 -
  48.170 -/**
  48.171 - * Shorthand for calling an allocators calloc function.
  48.172 - * @param allocator the allocator to use
  48.173 - * @param n the count of elements the space should be allocated for
  48.174 - * @param size the size of each element
  48.175 - * @return a pointer to the allocated memory area
  48.176 - */
  48.177 -#define alcalloc(allocator, n, size) \
  48.178 -        ((allocator)->calloc((allocator)->pool, n, size))
  48.179 -
  48.180 -/**
  48.181 - * Shorthand for calling an allocators realloc function.
  48.182 - * @param allocator the allocator to use
  48.183 - * @param ptr the pointer to the memory area that shall be reallocated
  48.184 - * @param n the new size of the allocated memory area
  48.185 - * @return a pointer to the reallocated memory area
  48.186 - */
  48.187 -#define alrealloc(allocator, ptr, n) \
  48.188 -        ((allocator)->realloc((allocator)->pool, ptr, n))
  48.189 -
  48.190 -/**
  48.191 - * Shorthand for calling an allocators free function.
  48.192 - * @param allocator the allocator to use
  48.193 - * @param ptr the pointer to the memory area that shall be freed
  48.194 - */
  48.195 -#define alfree(allocator, ptr) ((allocator)->free((allocator)->pool, ptr))
  48.196 -
  48.197 -/**
  48.198 - * Convenient macro for a default allocator <code>struct</code> definition.
  48.199 - */
  48.200 -#define UCX_ALLOCATOR_DEFAULT {NULL, \
  48.201 -        ucx_default_malloc, ucx_default_calloc, ucx_default_realloc, \
  48.202 -        ucx_default_free }
  48.203 -
  48.204 -#ifdef	__cplusplus
  48.205 -}
  48.206 -#endif
  48.207 -
  48.208 -#endif	/* UCX_ALLOCATOR_H */
  48.209 -
    49.1 --- a/ucx/avl.c	Tue Oct 17 15:15:54 2017 +0200
    49.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3 @@ -1,356 +0,0 @@
    49.4 -/*
    49.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    49.6 - *
    49.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    49.8 - *
    49.9 - * Redistribution and use in source and binary forms, with or without
   49.10 - * modification, are permitted provided that the following conditions are met:
   49.11 - *
   49.12 - *   1. Redistributions of source code must retain the above copyright
   49.13 - *      notice, this list of conditions and the following disclaimer.
   49.14 - *
   49.15 - *   2. Redistributions in binary form must reproduce the above copyright
   49.16 - *      notice, this list of conditions and the following disclaimer in the
   49.17 - *      documentation and/or other materials provided with the distribution.
   49.18 - *
   49.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   49.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   49.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   49.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   49.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   49.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   49.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   49.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   49.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   49.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   49.29 - * POSSIBILITY OF SUCH DAMAGE.
   49.30 - */
   49.31 -
   49.32 -#include <limits.h>
   49.33 -
   49.34 -#include "avl.h"
   49.35 -
   49.36 -#define ptrcast(ptr) ((void*)(ptr))
   49.37 -#define alloc_tree(al) (UcxAVLTree*) almalloc((al), sizeof(UcxAVLTree))
   49.38 -#define alloc_node(al) (UcxAVLNode*) almalloc((al), sizeof(UcxAVLNode))
   49.39 -
   49.40 -static void ucx_avl_connect(UcxAVLTree *tree,
   49.41 -        UcxAVLNode *node, UcxAVLNode *child, intptr_t nullkey) {
   49.42 -    if (child) {
   49.43 -        child->parent = node;
   49.44 -    }
   49.45 -    // if child is NULL, nullkey decides if left or right pointer is cleared
   49.46 -    if (tree->cmpfunc(
   49.47 -        ptrcast(child ? child->key : nullkey),
   49.48 -        ptrcast(node->key), tree->userdata) > 0) {
   49.49 -      node->right = child;
   49.50 -    } else {
   49.51 -      node->left = child;
   49.52 -    }
   49.53 -    size_t lh = node->left ? node->left->height : 0;
   49.54 -    size_t rh = node->right ? node->right->height : 0;
   49.55 -    node->height = 1 + (lh > rh ? lh : rh);
   49.56 -}
   49.57 -
   49.58 -#define avlheight(node) ((node) ? (node)->height : 0)
   49.59 -
   49.60 -static UcxAVLNode* avl_rotright(UcxAVLTree *tree, UcxAVLNode *l0) {
   49.61 -    UcxAVLNode *p = l0->parent;
   49.62 -    UcxAVLNode *l1 = l0->left;
   49.63 -    if (p) {
   49.64 -        ucx_avl_connect(tree, p, l1, 0);
   49.65 -    } else {
   49.66 -        l1->parent = NULL;
   49.67 -    }
   49.68 -    ucx_avl_connect(tree, l0, l1->right, l1->key);
   49.69 -    ucx_avl_connect(tree, l1, l0, 0);
   49.70 -    return l1;
   49.71 -}
   49.72 -
   49.73 -static UcxAVLNode* avl_rotleft(UcxAVLTree *tree, UcxAVLNode *l0) {
   49.74 -    UcxAVLNode *p = l0->parent;
   49.75 -    UcxAVLNode *l1 = l0->right;
   49.76 -    if (p) {
   49.77 -        ucx_avl_connect(tree, p, l1, 0);
   49.78 -    } else {
   49.79 -        l1->parent = NULL;
   49.80 -    }
   49.81 -    ucx_avl_connect(tree, l0, l1->left, l1->key);
   49.82 -    ucx_avl_connect(tree, l1, l0, 0);
   49.83 -    return l1;
   49.84 -}
   49.85 -
   49.86 -static void ucx_avl_balance(UcxAVLTree *tree, UcxAVLNode *n) {
   49.87 -    int lh = avlheight(n->left);
   49.88 -    int rh = avlheight(n->right);
   49.89 -    n->height = 1 + (lh > rh ? lh : rh);
   49.90 -    
   49.91 -    if (lh - rh == 2) {
   49.92 -      UcxAVLNode *c = n->left;
   49.93 -      if (avlheight(c->right) - avlheight(c->left) == 1) {
   49.94 -        avl_rotleft(tree, c);
   49.95 -      }
   49.96 -      n = avl_rotright(tree, n);
   49.97 -    } else if (rh - lh == 2) {  
   49.98 -      UcxAVLNode *c = n->right;
   49.99 -      if (avlheight(c->left) - avlheight(c->right) == 1) {
  49.100 -        avl_rotright(tree, c);
  49.101 -      }
  49.102 -      n = avl_rotleft(tree, n);
  49.103 -    }
  49.104 -
  49.105 -    if (n->parent) {
  49.106 -      ucx_avl_balance(tree, n->parent);
  49.107 -    } else {
  49.108 -      tree->root = n;
  49.109 -    }
  49.110 -}
  49.111 -
  49.112 -UcxAVLTree *ucx_avl_new(cmp_func cmpfunc) {
  49.113 -    return ucx_avl_new_a(cmpfunc, ucx_default_allocator());
  49.114 -}
  49.115 -
  49.116 -UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator) {
  49.117 -    UcxAVLTree* tree = alloc_tree(allocator);
  49.118 -    if (tree) {
  49.119 -        tree->allocator = allocator;
  49.120 -        tree->cmpfunc = cmpfunc;
  49.121 -        tree->root = NULL;
  49.122 -        tree->userdata = NULL;
  49.123 -    }
  49.124 -    
  49.125 -    return tree;
  49.126 -}
  49.127 -
  49.128 -static void ucx_avl_free_node(UcxAllocator *al, UcxAVLNode *node) {
  49.129 -    if (node) {
  49.130 -        ucx_avl_free_node(al, node->left);
  49.131 -        ucx_avl_free_node(al, node->right);
  49.132 -        alfree(al, node);
  49.133 -    }
  49.134 -}
  49.135 -
  49.136 -void ucx_avl_free(UcxAVLTree *tree) {
  49.137 -    UcxAllocator *al = tree->allocator;
  49.138 -    ucx_avl_free_node(al, tree->root);
  49.139 -    alfree(al, tree);
  49.140 -}
  49.141 -
  49.142 -UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key) {
  49.143 -    UcxAVLNode *n = tree->root;
  49.144 -    int cmpresult;
  49.145 -    while (n && (cmpresult = tree->cmpfunc(
  49.146 -            ptrcast(key), ptrcast(n->key), tree->userdata))) {
  49.147 -        n = cmpresult > 0 ? n->right : n->left;
  49.148 -    }
  49.149 -    return n;
  49.150 -}
  49.151 -
  49.152 -void *ucx_avl_get(UcxAVLTree *tree, intptr_t key) {
  49.153 -    UcxAVLNode *n = ucx_avl_get_node(tree, key);
  49.154 -    return n ? n->value : NULL;
  49.155 -}
  49.156 -
  49.157 -UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key,
  49.158 -        distance_func dfnc, int mode) {
  49.159 -    UcxAVLNode *n = tree->root;
  49.160 -    UcxAVLNode *closest = NULL;
  49.161 -
  49.162 -    intmax_t cmpresult;
  49.163 -    intmax_t closest_dist;
  49.164 -    closest_dist = mode == UCX_AVL_FIND_LOWER_BOUNDED ? INTMAX_MIN : INTMAX_MAX;
  49.165 -    
  49.166 -    while (n && (cmpresult = dfnc(
  49.167 -            ptrcast(key), ptrcast(n->key), tree->userdata))) {
  49.168 -        if (mode == UCX_AVL_FIND_CLOSEST) {
  49.169 -            intmax_t dist = cmpresult;
  49.170 -            if (dist < 0) dist *= -1;
  49.171 -            if (dist < closest_dist) {
  49.172 -                closest_dist = dist;
  49.173 -                closest = n;
  49.174 -            }
  49.175 -        } else if (mode == UCX_AVL_FIND_LOWER_BOUNDED && cmpresult <= 0) {
  49.176 -            if (cmpresult > closest_dist) {
  49.177 -                closest_dist = cmpresult;
  49.178 -                closest = n;
  49.179 -            }
  49.180 -        } else if (mode == UCX_AVL_FIND_UPPER_BOUNDED && cmpresult >= 0) {
  49.181 -            if (cmpresult < closest_dist) {
  49.182 -                closest_dist = cmpresult;
  49.183 -                closest = n;
  49.184 -            }
  49.185 -        }
  49.186 -        n = cmpresult > 0 ? n->right : n->left;
  49.187 -    }
  49.188 -    return n ? n : closest;
  49.189 -}
  49.190 -
  49.191 -void *ucx_avl_find(UcxAVLTree *tree, intptr_t key,
  49.192 -        distance_func dfnc, int mode) {
  49.193 -    UcxAVLNode *n = ucx_avl_find_node(tree, key, dfnc, mode);
  49.194 -    return n ? n->value : NULL;
  49.195 -}
  49.196 -
  49.197 -int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value) {
  49.198 -    return ucx_avl_put_s(tree, key, value, NULL);
  49.199 -}
  49.200 -
  49.201 -int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value,
  49.202 -        void **oldvalue) {
  49.203 -    if (tree->root) {
  49.204 -        UcxAVLNode *n = tree->root;
  49.205 -        int cmpresult;
  49.206 -        while ((cmpresult = tree->cmpfunc(
  49.207 -                ptrcast(key), ptrcast(n->key), tree->userdata))) {
  49.208 -            UcxAVLNode *m = cmpresult > 0 ? n->right : n->left;
  49.209 -            if (m) {
  49.210 -                n = m;
  49.211 -            } else {
  49.212 -                break;
  49.213 -            }
  49.214 -        }
  49.215 -
  49.216 -        if (cmpresult) {
  49.217 -            UcxAVLNode* e = alloc_node(tree->allocator);
  49.218 -            if (e) {
  49.219 -                e->key = key; e->value = value; e->height = 1;
  49.220 -                e->parent = e->left = e->right = NULL;
  49.221 -                ucx_avl_connect(tree, n, e, 0);
  49.222 -                ucx_avl_balance(tree, n);
  49.223 -                return 0;
  49.224 -            } else {
  49.225 -                return 1;
  49.226 -            }
  49.227 -        } else {
  49.228 -            if (oldvalue) {
  49.229 -                *oldvalue = n->value;
  49.230 -            }
  49.231 -            n->value = value;
  49.232 -            return 0;
  49.233 -        }
  49.234 -    } else {
  49.235 -        tree->root = alloc_node(tree->allocator);
  49.236 -        if (tree->root) {
  49.237 -            tree->root->key = key; tree->root->value = value;
  49.238 -            tree->root->height = 1;
  49.239 -            tree->root->parent = tree->root->left = tree->root->right = NULL;
  49.240 -            
  49.241 -            if (oldvalue) {
  49.242 -                *oldvalue = NULL;
  49.243 -            }
  49.244 -            
  49.245 -            return 0;
  49.246 -        } else {
  49.247 -            return 1;
  49.248 -        }
  49.249 -    }
  49.250 -}
  49.251 -
  49.252 -int ucx_avl_remove(UcxAVLTree *tree, intptr_t key) {
  49.253 -    return ucx_avl_remove_s(tree, key, NULL, NULL);
  49.254 -}
  49.255 -    
  49.256 -int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node) {
  49.257 -    return ucx_avl_remove_s(tree, node->key, NULL, NULL);
  49.258 -}
  49.259 -
  49.260 -int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key,
  49.261 -        intptr_t *oldkey, void **oldvalue) {
  49.262 -    
  49.263 -    UcxAVLNode *n = tree->root;
  49.264 -    int cmpresult;
  49.265 -    while (n && (cmpresult = tree->cmpfunc(
  49.266 -            ptrcast(key), ptrcast(n->key), tree->userdata))) {
  49.267 -        n = cmpresult > 0 ? n->right : n->left;
  49.268 -    }
  49.269 -    if (n) {
  49.270 -        if (oldkey) {
  49.271 -            *oldkey = n->key;
  49.272 -        }
  49.273 -        if (oldvalue) {
  49.274 -            *oldvalue = n->value;
  49.275 -        }
  49.276 -        
  49.277 -        UcxAVLNode *p = n->parent;
  49.278 -        if (n->left && n->right) {
  49.279 -            UcxAVLNode *s = n->right;
  49.280 -            while (s->left) {
  49.281 -                s = s->left;
  49.282 -            }
  49.283 -            ucx_avl_connect(tree, s->parent, s->right, s->key);
  49.284 -            n->key = s->key; n->value = s->value;
  49.285 -            p = s->parent;
  49.286 -            alfree(tree->allocator, s);
  49.287 -        } else {
  49.288 -            if (p) {
  49.289 -                ucx_avl_connect(tree, p, n->right ? n->right:n->left, n->key);
  49.290 -            } else {
  49.291 -                tree->root = n->right ? n->right : n->left;
  49.292 -                if (tree->root) {
  49.293 -                    tree->root->parent = NULL;
  49.294 -                }
  49.295 -            }
  49.296 -            alfree(tree->allocator, n);
  49.297 -        }
  49.298 -
  49.299 -        if (p) {
  49.300 -            ucx_avl_balance(tree, p);
  49.301 -        }
  49.302 -        
  49.303 -        return 0;
  49.304 -    } else {
  49.305 -        return 1;
  49.306 -    }
  49.307 -}
  49.308 -
  49.309 -static size_t ucx_avl_countn(UcxAVLNode *node) {
  49.310 -    if (node) {
  49.311 -        return 1 + ucx_avl_countn(node->left) + ucx_avl_countn(node->right);
  49.312 -    } else {
  49.313 -        return 0;
  49.314 -    }
  49.315 -}
  49.316 -
  49.317 -size_t ucx_avl_count(UcxAVLTree *tree) {
  49.318 -    return ucx_avl_countn(tree->root);
  49.319 -}
  49.320 -
  49.321 -UcxAVLNode* ucx_avl_pred(UcxAVLNode* node) {
  49.322 -    if (node->left) {
  49.323 -        UcxAVLNode* n = node->left;
  49.324 -        while (n->right) {
  49.325 -            n = n->right;
  49.326 -        }
  49.327 -        return n;
  49.328 -    } else {
  49.329 -        UcxAVLNode* n = node;
  49.330 -        while (n->parent) {
  49.331 -            if (n->parent->right == n) {
  49.332 -                return n->parent;
  49.333 -            } else {
  49.334 -                n = n->parent;
  49.335 -            }
  49.336 -        }
  49.337 -        return NULL;
  49.338 -    }
  49.339 -}
  49.340 -
  49.341 -UcxAVLNode* ucx_avl_succ(UcxAVLNode* node) {
  49.342 -    if (node->right) {
  49.343 -        UcxAVLNode* n = node->right;
  49.344 -        while (n->left) {
  49.345 -            n = n->left;
  49.346 -        }
  49.347 -        return n;
  49.348 -    } else {
  49.349 -        UcxAVLNode* n = node;
  49.350 -        while (n->parent) {
  49.351 -            if (n->parent->left == n) {
  49.352 -                return n->parent;
  49.353 -            } else {
  49.354 -                n = n->parent;
  49.355 -            }
  49.356 -        }
  49.357 -        return NULL;
  49.358 -    }
  49.359 -}
    50.1 --- a/ucx/avl.h	Tue Oct 17 15:15:54 2017 +0200
    50.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3 @@ -1,327 +0,0 @@
    50.4 -/*
    50.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    50.6 - *
    50.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    50.8 - *
    50.9 - * Redistribution and use in source and binary forms, with or without
   50.10 - * modification, are permitted provided that the following conditions are met:
   50.11 - *
   50.12 - *   1. Redistributions of source code must retain the above copyright
   50.13 - *      notice, this list of conditions and the following disclaimer.
   50.14 - *
   50.15 - *   2. Redistributions in binary form must reproduce the above copyright
   50.16 - *      notice, this list of conditions and the following disclaimer in the
   50.17 - *      documentation and/or other materials provided with the distribution.
   50.18 - *
   50.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   50.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   50.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   50.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   50.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   50.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   50.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   50.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   50.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   50.29 - * POSSIBILITY OF SUCH DAMAGE.
   50.30 - */
   50.31 -
   50.32 -
   50.33 -/**
   50.34 - * @file avl.h
   50.35 - * 
   50.36 - * AVL tree implementation.
   50.37 - * 
   50.38 - * This binary search tree implementation allows average O(1) insertion and
   50.39 - * removal of elements (excluding binary search time).
   50.40 - * 
   50.41 - * @author Mike Becker
   50.42 - * @author Olaf Wintermann
   50.43 - */
   50.44 -
   50.45 -#ifndef UCX_AVL_H
   50.46 -#define UCX_AVL_H
   50.47 -
   50.48 -#include "ucx.h"
   50.49 -#include "allocator.h"
   50.50 -#include <inttypes.h>
   50.51 -
   50.52 -#ifdef	__cplusplus
   50.53 -extern "C" {
   50.54 -#endif
   50.55 -
   50.56 -/**
   50.57 - * UCX AVL Node type.
   50.58 - * 
   50.59 - * @see UcxAVLNode
   50.60 - */
   50.61 -typedef struct UcxAVLNode UcxAVLNode;
   50.62 -
   50.63 -/**
   50.64 - * UCX AVL Node.
   50.65 - */
   50.66 -struct UcxAVLNode {
   50.67 -    /**
   50.68 -     * The key for this node.
   50.69 -     */
   50.70 -    intptr_t key;
   50.71 -    /**
   50.72 -     * Data contained by this node.
   50.73 -     */
   50.74 -    void *value;
   50.75 -    /**
   50.76 -     * The height of this (sub)-tree.
   50.77 -     */
   50.78 -    size_t height;
   50.79 -    /**
   50.80 -     * Parent node.
   50.81 -     */
   50.82 -    UcxAVLNode *parent;
   50.83 -    /**
   50.84 -     * Root node of left subtree.
   50.85 -     */
   50.86 -    UcxAVLNode *left;
   50.87 -    /**
   50.88 -     * Root node of right subtree.
   50.89 -     */
   50.90 -    UcxAVLNode *right;
   50.91 -};
   50.92 -
   50.93 -/**
   50.94 - * UCX AVL Tree.
   50.95 - */
   50.96 -typedef struct {
   50.97 -    /**
   50.98 -     * The UcxAllocator that shall be used to manage the memory for node data.
   50.99 -     */
  50.100 -    UcxAllocator *allocator;
  50.101 -    /**
  50.102 -     * Root node of the tree.
  50.103 -     */
  50.104 -    UcxAVLNode *root;
  50.105 -    /**
  50.106 -     * Compare function that shall be used to compare the UcxAVLNode keys.
  50.107 -     * @see UcxAVLNode.key
  50.108 -     */
  50.109 -    cmp_func cmpfunc;
  50.110 -    /**
  50.111 -     * Custom user data.
  50.112 -     * This data will also be provided to the cmpfunc.
  50.113 -     */
  50.114 -    void *userdata;
  50.115 -} UcxAVLTree;
  50.116 -
  50.117 -/**
  50.118 - * Initializes a new UcxAVLTree with a default allocator.
  50.119 - * 
  50.120 - * @param cmpfunc the compare function that shall be used
  50.121 - * @return a new UcxAVLTree object
  50.122 - * @see ucx_avl_new_a()
  50.123 - */
  50.124 -UcxAVLTree *ucx_avl_new(cmp_func cmpfunc);
  50.125 -
  50.126 -/**
  50.127 - * Initializes a new UcxAVLTree with the specified allocator.
  50.128 - * 
  50.129 - * The cmpfunc should be capable of comparing two keys within this AVL tree.
  50.130 - * So if you want to use null terminated strings as keys, you could use the
  50.131 - * ucx_strcmp() function here.
  50.132 - * 
  50.133 - * @param cmpfunc the compare function that shall be used
  50.134 - * @param allocator the UcxAllocator that shall be used
  50.135 - * @return a new UcxAVLTree object
  50.136 - */
  50.137 -UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator);
  50.138 -
  50.139 -/**
  50.140 - * Destroys a UcxAVLTree.
  50.141 - * @param tree the tree to destroy
  50.142 - */
  50.143 -void ucx_avl_free(UcxAVLTree *tree);
  50.144 -
  50.145 -/**
  50.146 - * Macro for initializing a new UcxAVLTree with the default allocator and a
  50.147 - * ucx_ptrcmp() compare function.
  50.148 - * 
  50.149 - * @return a new default UcxAVLTree object
  50.150 - */
  50.151 -#define ucx_avl_default_new() ucx_avl_new_a(ucx_ptrcmp, ucx_default_allocator())
  50.152 -
  50.153 -/**
  50.154 - * Gets the node from the tree, that is associated with the specified key.
  50.155 - * @param tree the UcxAVLTree
  50.156 - * @param key the key
  50.157 - * @return the node (or <code>NULL</code>, if the key is not present)
  50.158 - */
  50.159 -UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key);
  50.160 -
  50.161 -/**
  50.162 - * Gets the value from the tree, that is associated with the specified key.
  50.163 - * @param tree the UcxAVLTree
  50.164 - * @param key the key
  50.165 - * @return the value (or <code>NULL</code>, if the key is not present)
  50.166 - */
  50.167 -void *ucx_avl_get(UcxAVLTree *tree, intptr_t key);
  50.168 -
  50.169 -/**
  50.170 - * A mode for #ucx_avl_find_node() with the same behavior as
  50.171 - * #ucx_avl_get_node().
  50.172 - */
  50.173 -#define UCX_AVL_FIND_EXACT         0
  50.174 -/**
  50.175 - * A mode for #ucx_avl_find_node() finding the node whose key is at least
  50.176 - * as large as the specified key.
  50.177 - */
  50.178 -#define UCX_AVL_FIND_LOWER_BOUNDED 1
  50.179 -/**
  50.180 - * A mode for #ucx_avl_find_node() finding the node whose key is at most
  50.181 - * as large as the specified key.
  50.182 - */
  50.183 -#define UCX_AVL_FIND_UPPER_BOUNDED 2
  50.184 -/**
  50.185 - * A mode for #ucx_avl_find_node() finding the node with a key that is as close
  50.186 - * to the specified key as possible. If the key is present, the behavior is
  50.187 - * like #ucx_avl_get_node(). This mode only returns <code>NULL</code> on
  50.188 - * empty trees.
  50.189 - */
  50.190 -#define UCX_AVL_FIND_CLOSEST       3
  50.191 -
  50.192 -/**
  50.193 - * Finds a node within the tree. The following modes are supported:
  50.194 - * <ul>
  50.195 - * <li>#UCX_AVL_FIND_EXACT: the same behavior as #ucx_avl_get_node()</li>
  50.196 - * <li>#UCX_AVL_FIND_LOWER_BOUNDED: finds the node whose key is at least
  50.197 - * as large as the specified key</li>
  50.198 - * <li>#UCX_AVL_FIND_UPPER_BOUNDED: finds the node whose key is at most
  50.199 - * as large as the specified key</li>
  50.200 - * <li>#UCX_AVL_FIND_CLOSEST: finds the node with a key that is as close to
  50.201 - * the specified key as possible. If the key is present, the behavior is
  50.202 - * like #ucx_avl_get_node(). This mode only returns <code>NULL</code> on
  50.203 - * empty trees.</li> 
  50.204 - * </ul>
  50.205 - * 
  50.206 - * The distance function provided MUST agree with the compare function of
  50.207 - * the AVL tree.
  50.208 - * 
  50.209 - * @param tree the UcxAVLTree
  50.210 - * @param key the key
  50.211 - * @param dfnc the distance function
  50.212 - * @param mode the find mode
  50.213 - * @return the node (or <code>NULL</code>, if no node can be found)
  50.214 - */
  50.215 -UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key,
  50.216 -        distance_func dfnc, int mode);
  50.217 -
  50.218 -/**
  50.219 - * Finds a value within the tree.
  50.220 - * See #ucx_avl_find_node() for details.
  50.221 - * 
  50.222 - * @param tree the UcxAVLTree
  50.223 - * @param key the key
  50.224 - * @param dfnc the distance function
  50.225 - * @param mode the find mode
  50.226 - * @return the value (or <code>NULL</code>, if no value can be found)
  50.227 - */
  50.228 -void *ucx_avl_find(UcxAVLTree *tree, intptr_t key,
  50.229 -        distance_func dfnc, int mode);
  50.230 -
  50.231 -/**
  50.232 - * Puts a key/value pair into the tree.
  50.233 - * 
  50.234 - * Attention: use this function only, if a possible old value does not need
  50.235 - * to be preserved.
  50.236 - * 
  50.237 - * @param tree the UcxAVLTree
  50.238 - * @param key the key
  50.239 - * @param value the new value
  50.240 - * @return zero, if and only if the operation succeeded
  50.241 - */
  50.242 -int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value);
  50.243 -
  50.244 -/**
  50.245 - * Puts a key/value pair into the tree.
  50.246 - * 
  50.247 - * This is a secure function which saves the old value to the variable pointed
  50.248 - * at by oldvalue.
  50.249 - * 
  50.250 - * @param tree the UcxAVLTree
  50.251 - * @param key the key
  50.252 - * @param value the new value
  50.253 - * @param oldvalue optional: a pointer to the location where a possible old
  50.254 - * value shall be stored
  50.255 - * @return zero, if and only if the operation succeeded
  50.256 - */
  50.257 -int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value, void **oldvalue);
  50.258 -
  50.259 -/**
  50.260 - * Removes a node from the AVL tree.
  50.261 - * 
  50.262 - * Note: the specified node is logically removed. The tree implementation
  50.263 - * decides which memory area is freed. In most cases the here provided node
  50.264 - * is freed, so its further use is generally undefined.
  50.265 - * 
  50.266 - * @param tree the UcxAVLTree
  50.267 - * @param node the node to remove
  50.268 - * @return zero, if and only if an element has been removed
  50.269 - */
  50.270 -int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node);
  50.271 -
  50.272 -/**
  50.273 - * Removes an element from the AVL tree.
  50.274 - * 
  50.275 - * @param tree the UcxAVLTree
  50.276 - * @param key the key
  50.277 - * @return zero, if and only if an element has been removed
  50.278 - */
  50.279 -int ucx_avl_remove(UcxAVLTree *tree, intptr_t key);
  50.280 -
  50.281 -/**
  50.282 - * Removes an element from the AVL tree.
  50.283 - * 
  50.284 - * This is a secure function which saves the old key and value data from node
  50.285 - * to the variables at the location of oldkey and oldvalue (if specified), so
  50.286 - * they can be freed afterwards (if necessary).
  50.287 - * 
  50.288 - * Note: the returned key in oldkey is possibly not the same as the provided
  50.289 - * key for the lookup (in terms of memory location).
  50.290 - * 
  50.291 - * @param tree the UcxAVLTree
  50.292 - * @param key the key of the element to remove
  50.293 - * @param oldkey optional: a pointer to the location where the old key shall be
  50.294 - * stored
  50.295 - * @param oldvalue optional: a pointer to the location where the old value
  50.296 - * shall be stored
  50.297 - * @return zero, if and only if an element has been removed
  50.298 - */
  50.299 -int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key,
  50.300 -        intptr_t *oldkey, void **oldvalue);
  50.301 -
  50.302 -/**
  50.303 - * Counts the nodes in the specified UcxAVLTree.
  50.304 - * @param tree the AVL tree
  50.305 - * @return the node count
  50.306 - */
  50.307 -size_t ucx_avl_count(UcxAVLTree *tree);
  50.308 -
  50.309 -/**
  50.310 - * Finds the in-order predecessor of the given node.
  50.311 - * @param node an AVL node
  50.312 - * @return the in-order predecessor of the given node, or <code>NULL</code> if
  50.313 - * the given node is the in-order minimum
  50.314 - */
  50.315 -UcxAVLNode* ucx_avl_pred(UcxAVLNode* node);
  50.316 -
  50.317 -/**
  50.318 - * Finds the in-order successor of the given node.
  50.319 - * @param node an AVL node
  50.320 - * @return the in-order successor of the given node, or <code>NULL</code> if
  50.321 - * the given node is the in-order maximum
  50.322 - */
  50.323 -UcxAVLNode* ucx_avl_succ(UcxAVLNode* node);
  50.324 -
  50.325 -#ifdef	__cplusplus
  50.326 -}
  50.327 -#endif
  50.328 -
  50.329 -#endif	/* UCX_AVL_H */
  50.330 -
    51.1 --- a/ucx/buffer.c	Tue Oct 17 15:15:54 2017 +0200
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,235 +0,0 @@
    51.4 -/*
    51.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    51.6 - *
    51.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    51.8 - *
    51.9 - * Redistribution and use in source and binary forms, with or without
   51.10 - * modification, are permitted provided that the following conditions are met:
   51.11 - *
   51.12 - *   1. Redistributions of source code must retain the above copyright
   51.13 - *      notice, this list of conditions and the following disclaimer.
   51.14 - *
   51.15 - *   2. Redistributions in binary form must reproduce the above copyright
   51.16 - *      notice, this list of conditions and the following disclaimer in the
   51.17 - *      documentation and/or other materials provided with the distribution.
   51.18 - *
   51.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   51.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   51.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   51.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   51.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   51.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   51.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   51.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   51.29 - * POSSIBILITY OF SUCH DAMAGE.
   51.30 - */
   51.31 -
   51.32 -#include "buffer.h"
   51.33 -#include <stdarg.h>
   51.34 -#include <stdlib.h>
   51.35 -#include <string.h>
   51.36 -
   51.37 -UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) {
   51.38 -    UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
   51.39 -    if (buffer) {
   51.40 -        buffer->flags = flags;
   51.41 -        if (!space) {
   51.42 -            buffer->space = (char*)malloc(capacity);
   51.43 -            if (!buffer->space) {
   51.44 -                free(buffer);
   51.45 -                return NULL;
   51.46 -            }
   51.47 -            memset(buffer->space, 0, capacity);
   51.48 -            buffer->flags |= UCX_BUFFER_AUTOFREE;
   51.49 -        } else {
   51.50 -            buffer->space = (char*)space;
   51.51 -        }
   51.52 -        buffer->capacity = capacity;
   51.53 -        buffer->size = 0;
   51.54 -
   51.55 -        buffer->pos = 0;
   51.56 -    }
   51.57 -
   51.58 -    return buffer;
   51.59 -}
   51.60 -
   51.61 -void ucx_buffer_free(UcxBuffer *buffer) {
   51.62 -    if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) {
   51.63 -        free(buffer->space);
   51.64 -    }
   51.65 -    free(buffer);
   51.66 -}
   51.67 -
   51.68 -UcxBuffer* ucx_buffer_extract(
   51.69 -        UcxBuffer *src, size_t start, size_t length, int flags) {
   51.70 -    if (src->size == 0 || length == 0 ||
   51.71 -        ((size_t)-1) - start < length || start+length > src->capacity)
   51.72 -    {
   51.73 -        return NULL;
   51.74 -    }
   51.75 -
   51.76 -    UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
   51.77 -    if (dst) {
   51.78 -        dst->space = (char*)malloc(length);
   51.79 -        if (!dst->space) {
   51.80 -            free(dst);
   51.81 -            return NULL;
   51.82 -        }
   51.83 -        dst->capacity = length;
   51.84 -        dst->size = length;
   51.85 -        dst->flags = flags | UCX_BUFFER_AUTOFREE;
   51.86 -        dst->pos = 0;
   51.87 -        memcpy(dst->space, src->space+start, length);
   51.88 -    }
   51.89 -    return dst;
   51.90 -}
   51.91 -
   51.92 -int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
   51.93 -    size_t npos;
   51.94 -    switch (whence) {
   51.95 -    case SEEK_CUR:
   51.96 -        npos = buffer->pos;
   51.97 -        break;
   51.98 -    case SEEK_END:
   51.99 -        npos = buffer->size;
  51.100 -        break;
  51.101 -    case SEEK_SET:
  51.102 -        npos = 0;
  51.103 -        break;
  51.104 -    default:
  51.105 -        return -1;
  51.106 -    }
  51.107 -
  51.108 -    size_t opos = npos;
  51.109 -    npos += offset;
  51.110 -    
  51.111 -    if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
  51.112 -        return -1;
  51.113 -    }
  51.114 -    
  51.115 -    if (npos >= buffer->size) {
  51.116 -        return -1;
  51.117 -    } else {
  51.118 -        buffer->pos = npos;
  51.119 -        return 0;
  51.120 -    }
  51.121 -
  51.122 -}
  51.123 -
  51.124 -int ucx_buffer_eof(UcxBuffer *buffer) {
  51.125 -    return buffer->pos >= buffer->size;
  51.126 -}
  51.127 -
  51.128 -int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
  51.129 -    size_t newcap = buffer->capacity;
  51.130 -    
  51.131 -    if (buffer->capacity + len < buffer->capacity) {
  51.132 -        return -1;
  51.133 -    }
  51.134 -    
  51.135 -    while (buffer->capacity + len > newcap) {
  51.136 -        newcap <<= 1;
  51.137 -        if (newcap < buffer->capacity) {
  51.138 -            return -1;
  51.139 -        }
  51.140 -    }
  51.141 -    
  51.142 -    char *newspace = (char*)realloc(buffer->space, newcap);
  51.143 -    if (newspace) {
  51.144 -        memset(newspace+buffer->size, 0, newcap-buffer->size);
  51.145 -        buffer->space = newspace;
  51.146 -        buffer->capacity = newcap;
  51.147 -    } else {
  51.148 -        return -1;
  51.149 -    }
  51.150 -    
  51.151 -    return 0;
  51.152 -}
  51.153 -
  51.154 -size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
  51.155 -        UcxBuffer *buffer) {
  51.156 -    size_t len = size * nitems;
  51.157 -    size_t required = buffer->pos + len;
  51.158 -    if (buffer->pos > required) {
  51.159 -        return 0;
  51.160 -    }
  51.161 -    
  51.162 -    if (required > buffer->capacity) {
  51.163 -        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
  51.164 -            if (ucx_buffer_extend(buffer, required - buffer->capacity)) {
  51.165 -                return 0;
  51.166 -            }
  51.167 -        } else {
  51.168 -            len = buffer->capacity - buffer->pos;
  51.169 -            if (size > 1) {
  51.170 -                len -= len%size;
  51.171 -            }
  51.172 -        }
  51.173 -    }
  51.174 -    
  51.175 -    if (len == 0) {
  51.176 -        return len;
  51.177 -    }
  51.178 -    
  51.179 -    memcpy(buffer->space + buffer->pos, ptr, len);
  51.180 -    buffer->pos += len;
  51.181 -    if(buffer->pos > buffer->size) {
  51.182 -        buffer->size = buffer->pos;
  51.183 -    }
  51.184 -    
  51.185 -    return len / size;
  51.186 -}
  51.187 -
  51.188 -size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
  51.189 -        UcxBuffer *buffer) {
  51.190 -    size_t len = size * nitems;
  51.191 -    if (buffer->pos + len > buffer->size) {
  51.192 -        len = buffer->size - buffer->pos;
  51.193 -        if (size > 1) len -= len%size;
  51.194 -    }
  51.195 -    
  51.196 -    if (len <= 0) {
  51.197 -        return len;
  51.198 -    }
  51.199 -    
  51.200 -    memcpy(ptr, buffer->space + buffer->pos, len);
  51.201 -    buffer->pos += len;
  51.202 -    
  51.203 -    return len / size;
  51.204 -}
  51.205 -
  51.206 -int ucx_buffer_putc(UcxBuffer *buffer, int c) {
  51.207 -    if(buffer->pos >= buffer->capacity) {
  51.208 -        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
  51.209 -            if(ucx_buffer_extend(buffer, 1)) {
  51.210 -                return EOF;
  51.211 -            }
  51.212 -        } else {
  51.213 -            return EOF;
  51.214 -        }
  51.215 -    }
  51.216 -    
  51.217 -    c &= 0xFF;
  51.218 -    buffer->space[buffer->pos] = (char) c;
  51.219 -    buffer->pos++;
  51.220 -    if(buffer->pos > buffer->size) {
  51.221 -        buffer->size = buffer->pos;
  51.222 -    }
  51.223 -    return c;
  51.224 -}
  51.225 -
  51.226 -int ucx_buffer_getc(UcxBuffer *buffer) {
  51.227 -    if (ucx_buffer_eof(buffer)) {
  51.228 -        return EOF;
  51.229 -    } else {
  51.230 -        int c = buffer->space[buffer->pos];
  51.231 -        buffer->pos++;
  51.232 -        return c;
  51.233 -    }
  51.234 -}
  51.235 -
  51.236 -size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) {
  51.237 -    return ucx_buffer_write((const void*)str, 1, strlen(str), buffer);
  51.238 -}
    52.1 --- a/ucx/buffer.h	Tue Oct 17 15:15:54 2017 +0200
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,270 +0,0 @@
    52.4 -/*
    52.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    52.6 - *
    52.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    52.8 - *
    52.9 - * Redistribution and use in source and binary forms, with or without
   52.10 - * modification, are permitted provided that the following conditions are met:
   52.11 - *
   52.12 - *   1. Redistributions of source code must retain the above copyright
   52.13 - *      notice, this list of conditions and the following disclaimer.
   52.14 - *
   52.15 - *   2. Redistributions in binary form must reproduce the above copyright
   52.16 - *      notice, this list of conditions and the following disclaimer in the
   52.17 - *      documentation and/or other materials provided with the distribution.
   52.18 - *
   52.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   52.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   52.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   52.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   52.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   52.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   52.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   52.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   52.29 - * POSSIBILITY OF SUCH DAMAGE.
   52.30 - */
   52.31 -
   52.32 -/**
   52.33 - * @file buffer.h
   52.34 - * 
   52.35 - * Advanced buffer implementation.
   52.36 - * 
   52.37 - * Instances of UcxBuffer can be used to read from or to write to like one
   52.38 - * would do with a stream. This allows the use of ucx_stream_copy() to copy
   52.39 - * contents from one buffer to another.
   52.40 - * 
   52.41 - * Some features for convenient use of the buffer
   52.42 - * can be enabled. See the documentation of the macro constants for more
   52.43 - * information.
   52.44 - * 
   52.45 - * @author Mike Becker
   52.46 - * @author Olaf Wintermann
   52.47 - */
   52.48 -
   52.49 -#ifndef UCX_BUFFER_H
   52.50 -#define	UCX_BUFFER_H
   52.51 -
   52.52 -#include "ucx.h"
   52.53 -#include <sys/types.h>
   52.54 -#include <stdio.h>
   52.55 -
   52.56 -#ifdef	__cplusplus
   52.57 -extern "C" {
   52.58 -#endif
   52.59 -
   52.60 -/**
   52.61 - * No buffer features enabled (all flags cleared).
   52.62 - */
   52.63 -#define UCX_BUFFER_DEFAULT      0x00
   52.64 -
   52.65 -/**
   52.66 - * If this flag is enabled, the buffer will automatically free its contents.
   52.67 - */
   52.68 -#define UCX_BUFFER_AUTOFREE     0x01
   52.69 -
   52.70 -/**
   52.71 - * If this flag is enabled, the buffer will automatically extends its capacity.
   52.72 - */
   52.73 -#define UCX_BUFFER_AUTOEXTEND   0x02
   52.74 -
   52.75 -/** UCX Buffer. */
   52.76 -typedef struct {
   52.77 -    /** A pointer to the buffer contents. */
   52.78 -    char *space;
   52.79 -    /** Current position of the buffer. */
   52.80 -    size_t pos;
   52.81 -    /** Current capacity (i.e. maximum size) of the buffer. */
   52.82 -    size_t capacity;
   52.83 -    /** Current size of the buffer content. */
   52.84 -    size_t size;
   52.85 -    /**
   52.86 -     * Flag register for buffer features.
   52.87 -     * @see #UCX_BUFFER_DEFAULT
   52.88 -     * @see #UCX_BUFFER_AUTOFREE
   52.89 -     * @see #UCX_BUFFER_AUTOEXTEND
   52.90 -     */
   52.91 -    int flags;
   52.92 -} UcxBuffer;
   52.93 -
   52.94 -/**
   52.95 - * Creates a new buffer.
   52.96 - * 
   52.97 - * <b>Note:</b> you may provide <code>NULL</code> as argument for
   52.98 - * <code>space</code>. Then this function will allocate the space and enforce
   52.99 - * the #UCX_BUFFER_AUTOFREE flag.
  52.100 - * 
  52.101 - * @param space pointer to the memory area, or <code>NULL</code> to allocate
  52.102 - * new memory
  52.103 - * @param capacity the capacity of the buffer
  52.104 - * @param flags buffer features (see UcxBuffer.flags)
  52.105 - * @return the new buffer
  52.106 - */
  52.107 -UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags);
  52.108 -
  52.109 -/**
  52.110 - * Destroys a buffer.
  52.111 - * 
  52.112 - * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer
  52.113 - * are also freed.
  52.114 - * 
  52.115 - * @param buffer the buffer to destroy
  52.116 - */
  52.117 -void ucx_buffer_free(UcxBuffer* buffer);
  52.118 -
  52.119 -/**
  52.120 - * Creates a new buffer and fills it with extracted content from another buffer.
  52.121 - * 
  52.122 - * <b>Note:</b> the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer.
  52.123 - * 
  52.124 - * @param src the source buffer
  52.125 - * @param start the start position of extraction
  52.126 - * @param length the count of bytes to extract (must not be zero)
  52.127 - * @param flags feature mask for the new buffer
  52.128 - * @return a new buffer containing the extraction
  52.129 - */
  52.130 -UcxBuffer* ucx_buffer_extract(UcxBuffer *src,
  52.131 -        size_t start, size_t length, int flags);
  52.132 -
  52.133 -/**
  52.134 - * A shorthand macro for the full extraction of the buffer.
  52.135 - * 
  52.136 - * @param src the source buffer
  52.137 - * @param flags feature mask for the new buffer
  52.138 - * @return a new buffer with the extracted content
  52.139 - */
  52.140 -#define ucx_buffer_clone(src,flags) \
  52.141 -    ucx_buffer_extract(src, 0, (src)->capacity, flags)
  52.142 -
  52.143 -/**
  52.144 - * Moves the position of the buffer.
  52.145 - * 
  52.146 - * The new position is relative to the <code>whence</code> argument.
  52.147 - *
  52.148 - * SEEK_SET marks the start of the buffer.
  52.149 - * SEEK_CUR marks the current position.
  52.150 - * SEEK_END marks the end of the buffer.
  52.151 - * 
  52.152 - * With an offset of zero, this function sets the buffer position to zero
  52.153 - * (SEEK_SET), the buffer size (SEEK_END) or leaves the buffer position
  52.154 - * unchanged (SEEK_CUR).
  52.155 - * 
  52.156 - * @param buffer
  52.157 - * @param offset position offset relative to <code>whence</code>
  52.158 - * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END
  52.159 - * @return 0 on success, non-zero if the position is invalid
  52.160 - *
  52.161 - */
  52.162 -int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence);
  52.163 -
  52.164 -/**
  52.165 - * Clears the buffer by resetting the position and deleting the data.
  52.166 - * 
  52.167 - * The data is deleted by a zeroing it with call to <code>memset()</code>.
  52.168 - * 
  52.169 - * @param buffer the buffer to be cleared
  52.170 - */
  52.171 -#define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \
  52.172 -        buffer->size = 0; buffer->pos = 0;
  52.173 -
  52.174 -/**
  52.175 - * Tests, if the buffer position has exceeded the buffer capacity.
  52.176 - * 
  52.177 - * @param buffer the buffer to test
  52.178 - * @return non-zero, if the current buffer position has exceeded the last
  52.179 - * available byte of the buffer.
  52.180 - */
  52.181 -int ucx_buffer_eof(UcxBuffer *buffer);
  52.182 -
  52.183 -
  52.184 -/**
  52.185 - * Extends the capacity of the buffer.
  52.186 - * 
  52.187 - * <b>Note:</b> The buffer capacity increased by a power of two. I.e.
  52.188 - * the buffer capacity is doubled, as long as it would not hold the current
  52.189 - * content plus the additional required bytes.
  52.190 - * 
  52.191 - * <b>Attention:</b> the argument provided is the number of <i>additional</i>
  52.192 - * bytes the buffer shall hold. It is <b>NOT</b> the total number of bytes the
  52.193 - * buffer shall hold.
  52.194 - * 
  52.195 - * @param buffer the buffer to extend
  52.196 - * @param additional_bytes the number of additional bytes the buffer shall
  52.197 - * <i>at least</i> hold
  52.198 - * @return 0 on success or a non-zero value on failure
  52.199 - */
  52.200 -int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes);
  52.201 -
  52.202 -/**
  52.203 - * Writes data to a UcxBuffer.
  52.204 - * 
  52.205 - * The position of the buffer is increased by the number of bytes written.
  52.206 - * 
  52.207 - * @param ptr a pointer to the memory area containing the bytes to be written
  52.208 - * @param size the length of one element
  52.209 - * @param nitems the element count
  52.210 - * @param buffer the UcxBuffer to write to
  52.211 - * @return the total count of bytes written
  52.212 - */
  52.213 -size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
  52.214 -        UcxBuffer *buffer);
  52.215 -
  52.216 -/**
  52.217 - * Reads data from a UcxBuffer.
  52.218 - * 
  52.219 - * The position of the buffer is increased by the number of bytes read.
  52.220 - * 
  52.221 - * @param ptr a pointer to the memory area where to store the read data
  52.222 - * @param size the length of one element
  52.223 - * @param nitems the element count
  52.224 - * @param buffer the UcxBuffer to read from
  52.225 - * @return the total number of elements read
  52.226 - */
  52.227 -size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
  52.228 -        UcxBuffer *buffer);
  52.229 -
  52.230 -/**
  52.231 - * Writes a character to a buffer.
  52.232 - * 
  52.233 - * The least significant byte of the argument is written to the buffer. If the
  52.234 - * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled,
  52.235 - * the buffer capacity is extended by ucx_buffer_extend(). If the feature is
  52.236 - * disabled or buffer extension fails, <code>EOF</code> is returned.
  52.237 - * 
  52.238 - * On successful write the position of the buffer is increased.
  52.239 - * 
  52.240 - * @param buffer the buffer to write to
  52.241 - * @param c the character to write as <code>int</code> value
  52.242 - * @return the byte that has bean written as <code>int</code> value or
  52.243 - * <code>EOF</code> when the end of the stream is reached and automatic
  52.244 - * extension is not enabled or not possible
  52.245 - */
  52.246 -int ucx_buffer_putc(UcxBuffer *buffer, int c);
  52.247 -
  52.248 -/**
  52.249 - * Gets a character from a buffer.
  52.250 - * 
  52.251 - * The current position of the buffer is increased after a successful read.
  52.252 - * 
  52.253 - * @param buffer the buffer to read from
  52.254 - * @return the character as <code>int</code> value or <code>EOF</code>, if the
  52.255 - * end of the buffer is reached
  52.256 - */
  52.257 -int ucx_buffer_getc(UcxBuffer *buffer);
  52.258 -
  52.259 -/**
  52.260 - * Writes a string to a buffer.
  52.261 - * 
  52.262 - * @param buffer the buffer
  52.263 - * @param str the string
  52.264 - * @return the number of bytes written
  52.265 - */
  52.266 -size_t ucx_buffer_puts(UcxBuffer *buffer, char *str);
  52.267 -
  52.268 -#ifdef	__cplusplus
  52.269 -}
  52.270 -#endif
  52.271 -
  52.272 -#endif	/* UCX_BUFFER_H */
  52.273 -
    53.1 --- a/ucx/list.c	Tue Oct 17 15:15:54 2017 +0200
    53.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.3 @@ -1,370 +0,0 @@
    53.4 -/*
    53.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    53.6 - *
    53.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    53.8 - *
    53.9 - * Redistribution and use in source and binary forms, with or without
   53.10 - * modification, are permitted provided that the following conditions are met:
   53.11 - *
   53.12 - *   1. Redistributions of source code must retain the above copyright
   53.13 - *      notice, this list of conditions and the following disclaimer.
   53.14 - *
   53.15 - *   2. Redistributions in binary form must reproduce the above copyright
   53.16 - *      notice, this list of conditions and the following disclaimer in the
   53.17 - *      documentation and/or other materials provided with the distribution.
   53.18 - *
   53.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   53.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   53.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   53.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   53.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   53.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   53.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   53.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   53.29 - * POSSIBILITY OF SUCH DAMAGE.
   53.30 - */
   53.31 -
   53.32 -#include "list.h"
   53.33 -
   53.34 -UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
   53.35 -    return ucx_list_clone_a(ucx_default_allocator(), l, fnc, data);
   53.36 -}
   53.37 -
   53.38 -UcxList *ucx_list_clone_a(UcxAllocator *alloc, UcxList *l,
   53.39 -        copy_func fnc, void *data) {
   53.40 -    UcxList *ret = NULL;
   53.41 -    while (l) {
   53.42 -        if (fnc) {
   53.43 -            ret = ucx_list_append_a(alloc, ret, fnc(l->data, data));
   53.44 -        } else {
   53.45 -            ret = ucx_list_append_a(alloc, ret, l->data);
   53.46 -        }
   53.47 -        l = l->next;
   53.48 -    }
   53.49 -    return ret;
   53.50 -}
   53.51 -
   53.52 -int ucx_list_equals(const UcxList *l1, const UcxList *l2,
   53.53 -        cmp_func fnc, void* data) {
   53.54 -    if (l1 == l2) return 1;
   53.55 -    
   53.56 -    while (l1 != NULL && l2 != NULL) {
   53.57 -        if (fnc == NULL) {
   53.58 -            if (l1->data != l2->data) return 0;
   53.59 -        } else {
   53.60 -            if (fnc(l1->data, l2->data, data) != 0) return 0;
   53.61 -        }
   53.62 -        l1 = l1->next;
   53.63 -        l2 = l2->next;
   53.64 -    }
   53.65 -    
   53.66 -    return (l1 == NULL && l2 == NULL);
   53.67 -}
   53.68 -
   53.69 -void ucx_list_free(UcxList *l) {
   53.70 -    ucx_list_free_a(ucx_default_allocator(), l);
   53.71 -}
   53.72 -
   53.73 -void ucx_list_free_a(UcxAllocator *alloc, UcxList *l) {
   53.74 -    UcxList *e = l, *f;
   53.75 -    while (e != NULL) {
   53.76 -        f = e;
   53.77 -        e = e->next;
   53.78 -        alfree(alloc, f);
   53.79 -    }
   53.80 -}
   53.81 -
   53.82 -void ucx_list_free_content(UcxList* list, ucx_destructor destr) {
   53.83 -    while (list != NULL) {
   53.84 -        destr(list->data);
   53.85 -        list = list->next;
   53.86 -    }
   53.87 -}
   53.88 -
   53.89 -UcxList *ucx_list_append(UcxList *l, void *data)  {
   53.90 -    return ucx_list_append_a(ucx_default_allocator(), l, data);
   53.91 -}
   53.92 -
   53.93 -UcxList *ucx_list_append_a(UcxAllocator *alloc, UcxList *l, void *data)  {
   53.94 -    UcxList *nl = (UcxList*) almalloc(alloc, sizeof(UcxList));
   53.95 -    if (!nl) {
   53.96 -        return NULL;
   53.97 -    }
   53.98 -    
   53.99 -    nl->data = data;
  53.100 -    nl->next = NULL;
  53.101 -    if (l) {
  53.102 -        UcxList *t = ucx_list_last(l);
  53.103 -        t->next = nl;
  53.104 -        nl->prev = t;
  53.105 -        return l;
  53.106 -    } else {
  53.107 -        nl->prev = NULL;
  53.108 -        return nl;
  53.109 -    }
  53.110 -}
  53.111 -
  53.112 -UcxList *ucx_list_append_once(UcxList *l, void *data,
  53.113 -        cmp_func cmpfnc, void *cmpdata) {
  53.114 -    return ucx_list_append_once_a(ucx_default_allocator(), l,
  53.115 -            data, cmpfnc, cmpdata);
  53.116 -}
  53.117 -
  53.118 -UcxList *ucx_list_append_once_a(UcxAllocator *alloc, UcxList *l, void *data,
  53.119 -        cmp_func cmpfnc, void *cmpdata) {
  53.120 -
  53.121 -    UcxList *last = NULL;
  53.122 -    {
  53.123 -        UcxList *e = l;
  53.124 -        while (e) {
  53.125 -            if (cmpfnc(e->data, data, cmpdata) == 0) {
  53.126 -                return l;
  53.127 -            }
  53.128 -            last = e;
  53.129 -            e = e->next;
  53.130 -        }
  53.131 -    }
  53.132 -    
  53.133 -    UcxList *nl = ucx_list_append_a(alloc, NULL, data);
  53.134 -    if (!nl) {
  53.135 -        return NULL;
  53.136 -    }
  53.137 -
  53.138 -    if (last == NULL) {
  53.139 -        return nl;
  53.140 -    } else {
  53.141 -        nl->prev = last;
  53.142 -        last->next = nl;
  53.143 -        return l;
  53.144 -    }
  53.145 -}
  53.146 -
  53.147 -UcxList *ucx_list_prepend(UcxList *l, void *data) {
  53.148 -    return ucx_list_prepend_a(ucx_default_allocator(), l, data);
  53.149 -}
  53.150 -
  53.151 -UcxList *ucx_list_prepend_a(UcxAllocator *alloc, UcxList *l, void *data) {
  53.152 -    UcxList *nl = ucx_list_append_a(alloc, NULL, data);
  53.153 -    if (!nl) {
  53.154 -        return NULL;
  53.155 -    }
  53.156 -    l = ucx_list_first(l);
  53.157 -    
  53.158 -    if (l) {
  53.159 -        nl->next = l;
  53.160 -        l->prev = nl;
  53.161 -    }
  53.162 -    return nl;
  53.163 -}
  53.164 -
  53.165 -UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
  53.166 -    if (l1) {
  53.167 -        UcxList *last = ucx_list_last(l1);
  53.168 -        last->next = l2;
  53.169 -        if (l2) {
  53.170 -            l2->prev = last;
  53.171 -        }
  53.172 -        return l1;
  53.173 -    } else {
  53.174 -        return l2;
  53.175 -    }
  53.176 -}
  53.177 -
  53.178 -UcxList *ucx_list_last(const UcxList *l) {
  53.179 -    if (l == NULL) return NULL;
  53.180 -    
  53.181 -    const UcxList *e = l;
  53.182 -    while (e->next != NULL) {
  53.183 -        e = e->next;
  53.184 -    }
  53.185 -    return (UcxList*)e;
  53.186 -}
  53.187 -
  53.188 -ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem) {
  53.189 -    ssize_t index = 0;
  53.190 -    while (list) {
  53.191 -        if (list == elem) {
  53.192 -            return index;
  53.193 -        }
  53.194 -        list = list->next;
  53.195 -        index++;
  53.196 -    }
  53.197 -    return -1;
  53.198 -}
  53.199 -
  53.200 -UcxList *ucx_list_get(const UcxList *l, size_t index) {
  53.201 -    if (l == NULL) return NULL;
  53.202 -
  53.203 -    const UcxList *e = l;
  53.204 -    while (e->next && index > 0) {
  53.205 -        e = e->next;
  53.206 -        index--;
  53.207 -    }
  53.208 -    
  53.209 -    return (UcxList*)(index == 0 ? e : NULL);
  53.210 -}
  53.211 -
  53.212 -ssize_t ucx_list_find(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
  53.213 -    ssize_t index = 0;
  53.214 -    UCX_FOREACH(e, l) {
  53.215 -        if (fnc) {
  53.216 -            if (fnc(elem, e->data, cmpdata) == 0) {
  53.217 -                return index;
  53.218 -            }
  53.219 -        } else {
  53.220 -            if (elem == e->data) {
  53.221 -                return index;
  53.222 -            }
  53.223 -        }
  53.224 -        index++;
  53.225 -    }
  53.226 -    return -1;
  53.227 -}
  53.228 -
  53.229 -int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
  53.230 -    return ucx_list_find(l, elem, fnc, cmpdata) > -1;
  53.231 -}
  53.232 -
  53.233 -size_t ucx_list_size(const UcxList *l) {
  53.234 -    if (l == NULL) return 0;
  53.235 -    
  53.236 -    const UcxList *e = l;
  53.237 -    size_t s = 1;
  53.238 -    while (e->next != NULL) {
  53.239 -        e = e->next;
  53.240 -        s++;
  53.241 -    }
  53.242 -
  53.243 -    return s;
  53.244 -}
  53.245 -
  53.246 -static UcxList *ucx_list_sort_merge(int length,
  53.247 -        UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
  53.248 -        cmp_func fnc, void* data) {
  53.249 -
  53.250 -    UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
  53.251 -    UcxList *rc, *lc;
  53.252 -
  53.253 -    lc = ls; rc = le;
  53.254 -    int n = 0;
  53.255 -    while (lc && lc != le && rc != re) {
  53.256 -        if (fnc(lc->data, rc->data, data) <= 0) {
  53.257 -            sorted[n] = lc;
  53.258 -            lc = lc->next;
  53.259 -        } else {
  53.260 -            sorted[n] = rc;
  53.261 -            rc = rc->next;
  53.262 -        }
  53.263 -        n++;
  53.264 -    }
  53.265 -    while (lc && lc != le) {
  53.266 -        sorted[n] = lc;
  53.267 -        lc = lc->next;
  53.268 -        n++;
  53.269 -    }
  53.270 -    while (rc && rc != re) {
  53.271 -        sorted[n] = rc;
  53.272 -        rc = rc->next;
  53.273 -        n++;
  53.274 -    }
  53.275 -
  53.276 -    // Update pointer
  53.277 -    sorted[0]->prev = NULL;
  53.278 -    for (int i = 0 ; i < length-1 ; i++) {
  53.279 -        sorted[i]->next = sorted[i+1];
  53.280 -        sorted[i+1]->prev = sorted[i];
  53.281 -    }
  53.282 -    sorted[length-1]->next = NULL;
  53.283 -
  53.284 -    UcxList *ret = sorted[0];
  53.285 -    free(sorted);
  53.286 -    return ret;
  53.287 -}
  53.288 -
  53.289 -UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
  53.290 -    if (l == NULL) {
  53.291 -        return NULL;
  53.292 -    }
  53.293 -
  53.294 -    UcxList *lc;
  53.295 -    int ln = 1;
  53.296 -
  53.297 -    UcxList *restrict ls = l, *restrict le, *restrict re;
  53.298 -    
  53.299 -    // check how many elements are already sorted
  53.300 -    lc = ls;
  53.301 -    while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
  53.302 -        lc = lc->next;
  53.303 -        ln++;
  53.304 -    }
  53.305 -    le = lc->next;
  53.306 -
  53.307 -    if (le == NULL) {
  53.308 -        return l; // this list is already sorted :)
  53.309 -    } else {
  53.310 -        UcxList *rc;
  53.311 -        int rn = 1;
  53.312 -        rc = le;
  53.313 -        // skip already sorted elements
  53.314 -        while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
  53.315 -            rc = rc->next;
  53.316 -            rn++;
  53.317 -        }
  53.318 -        re = rc->next;
  53.319 -
  53.320 -        // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
  53.321 -        UcxList *sorted = ucx_list_sort_merge(ln+rn,
  53.322 -                ls, le, re,
  53.323 -                fnc, data);
  53.324 -        
  53.325 -        // Something left? Sort it!
  53.326 -        size_t remainder_length = ucx_list_size(re);
  53.327 -        if (remainder_length > 0) {
  53.328 -            UcxList *remainder = ucx_list_sort(re, fnc, data);
  53.329 -
  53.330 -            // merge sorted list with (also sorted) remainder
  53.331 -            l = ucx_list_sort_merge(ln+rn+remainder_length,
  53.332 -                    sorted, remainder, NULL, fnc, data);
  53.333 -        } else {
  53.334 -            // no remainder - we've got our sorted list
  53.335 -            l = sorted;
  53.336 -        }
  53.337 -
  53.338 -        return l;
  53.339 -    }
  53.340 -}
  53.341 -
  53.342 -UcxList *ucx_list_first(const UcxList *l) {
  53.343 -    if (!l) {
  53.344 -        return NULL;
  53.345 -    }
  53.346 -    
  53.347 -    const UcxList *e = l;
  53.348 -    while (e->prev) {
  53.349 -        e = e->prev;
  53.350 -    }
  53.351 -    return (UcxList *)e;
  53.352 -}
  53.353 -
  53.354 -UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
  53.355 -    return ucx_list_remove_a(ucx_default_allocator(), l, e);
  53.356 -}
  53.357 -    
  53.358 -UcxList *ucx_list_remove_a(UcxAllocator *alloc, UcxList *l, UcxList *e) {
  53.359 -    if (l == e) {
  53.360 -        l = e->next;
  53.361 -    }
  53.362 -    
  53.363 -    if (e->next) {
  53.364 -        e->next->prev = e->prev;
  53.365 -    }
  53.366 -    
  53.367 -    if (e->prev) {
  53.368 -        e->prev->next = e->next;
  53.369 -    }
  53.370 -    
  53.371 -    alfree(alloc, e);
  53.372 -    return l;
  53.373 -}
    54.1 --- a/ucx/list.h	Tue Oct 17 15:15:54 2017 +0200
    54.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3 @@ -1,428 +0,0 @@
    54.4 -/*
    54.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    54.6 - *
    54.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    54.8 - *
    54.9 - * Redistribution and use in source and binary forms, with or without
   54.10 - * modification, are permitted provided that the following conditions are met:
   54.11 - *
   54.12 - *   1. Redistributions of source code must retain the above copyright
   54.13 - *      notice, this list of conditions and the following disclaimer.
   54.14 - *
   54.15 - *   2. Redistributions in binary form must reproduce the above copyright
   54.16 - *      notice, this list of conditions and the following disclaimer in the
   54.17 - *      documentation and/or other materials provided with the distribution.
   54.18 - *
   54.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   54.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   54.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   54.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   54.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   54.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   54.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   54.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   54.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   54.29 - * POSSIBILITY OF SUCH DAMAGE.
   54.30 - */
   54.31 -/**
   54.32 - * Doubly linked list implementation.
   54.33 - * 
   54.34 - * @file   list.h
   54.35 - * @author Mike Becker
   54.36 - * @author Olaf Wintermann
   54.37 - */
   54.38 -
   54.39 -#ifndef UCX_LIST_H
   54.40 -#define	UCX_LIST_H
   54.41 -
   54.42 -#include "ucx.h"
   54.43 -#include "allocator.h"
   54.44 -
   54.45 -#ifdef	__cplusplus
   54.46 -extern "C" {
   54.47 -#endif
   54.48 -
   54.49 -/**
   54.50 - * Loop statement for UCX lists.
   54.51 - * 
   54.52 - * The first argument is the name of the iteration variable. The scope of
   54.53 - * this variable is limited to the <code>UCX_FOREACH</code> statement.
   54.54 - * 
   54.55 - * The second argument is a pointer to the list. In most cases this will be the
   54.56 - * pointer to the first element of the list, but it may also be an arbitrary
   54.57 - * element of the list. The iteration will then start with that element.
   54.58 - * 
   54.59 - * @param list The first element of the list
   54.60 - * @param elem The variable name of the element
   54.61 - */
   54.62 -#define UCX_FOREACH(elem,list) \
   54.63 -        for (UcxList* elem = list ; elem != NULL ; elem = elem->next)
   54.64 -
   54.65 -/**
   54.66 - * UCX list type.
   54.67 - * @see UcxList
   54.68 - */
   54.69 -typedef struct UcxList UcxList;
   54.70 -
   54.71 -/**
   54.72 - * UCX list structure.
   54.73 - */
   54.74 -struct UcxList {
   54.75 -    /**
   54.76 -     * List element payload.
   54.77 -     */
   54.78 -    void    *data;
   54.79 -    /**
   54.80 -     * Pointer to the next list element or <code>NULL</code>, if this is the
   54.81 -     * last element.
   54.82 -     */
   54.83 -    UcxList *next;
   54.84 -    /**
   54.85 -     * Pointer to the previous list element or <code>NULL</code>, if this is
   54.86 -     * the first element.
   54.87 -     */
   54.88 -    UcxList *prev;
   54.89 -};
   54.90 -
   54.91 -/**
   54.92 - * Creates an element-wise copy of a list.
   54.93 - * 
   54.94 - * This function clones the specified list by creating new list elements and
   54.95 - * copying the data with the specified copy_func(). If no copy_func() is
   54.96 - * specified, a shallow copy is created and the new list will reference the
   54.97 - * same data as the source list.
   54.98 - * 
   54.99 - * @param list the list to copy
  54.100 - * @param cpyfnc a pointer to the function that shall copy an element (may be
  54.101 - * <code>NULL</code>)
  54.102 - * @param data additional data for the copy_func()
  54.103 - * @return a pointer to the copy
  54.104 - */
  54.105 -UcxList *ucx_list_clone(UcxList *list, copy_func cpyfnc, void* data);
  54.106 -
  54.107 -/**
  54.108 - * Creates an element-wise copy of a list using a UcxAllocator.
  54.109 - * 
  54.110 - * See ucx_list_clone() for details.
  54.111 - * 
  54.112 - * You might want to pass the allocator via the <code>data</code> parameter,
  54.113 - * to access it within the copy function for making deep copies.
  54.114 - * 
  54.115 - * @param allocator the allocator to use
  54.116 - * @param list the list to copy
  54.117 - * @param cpyfnc a pointer to the function that shall copy an element (may be
  54.118 - * <code>NULL</code>)
  54.119 - * @param data additional data for the copy_func()
  54.120 - * @return a pointer to the copy
  54.121 - * @see ucx_list_clone()
  54.122 - */
  54.123 -UcxList *ucx_list_clone_a(UcxAllocator *allocator, UcxList *list,
  54.124 -        copy_func cpyfnc, void* data);
  54.125 -
  54.126 -/**
  54.127 - * Compares two UCX lists element-wise by using a compare function.
  54.128 - * 
  54.129 - * Each element of the two specified lists are compared by using the specified
  54.130 - * compare function and the additional data. The type and content of this
  54.131 - * additional data depends on the cmp_func() used.
  54.132 - * 
  54.133 - * If the list pointers denote elements within a list, the lists are compared
  54.134 - * starting with the denoted elements. Thus any previous elements are not taken
  54.135 - * into account. This might be useful to check, if certain list tails match
  54.136 - * each other.
  54.137 - * 
  54.138 - * @param list1 the first list
  54.139 - * @param list2 the second list
  54.140 - * @param cmpfnc the compare function
  54.141 - * @param data additional data for the compare function
  54.142 - * @return 1, if and only if the two lists equal element-wise, 0 otherwise
  54.143 - */
  54.144 -int ucx_list_equals(const UcxList *list1, const UcxList *list2,
  54.145 -        cmp_func cmpfnc, void* data);
  54.146 -
  54.147 -/**
  54.148 - * Destroys the entire list.
  54.149 - * 
  54.150 - * The members of the list are not automatically freed, so ensure they are
  54.151 - * otherwise referenced or destroyed by ucx_list_free_contents().
  54.152 - * Otherwise, a memory leak is likely to occur.
  54.153 - * 
  54.154 - * <b>Caution:</b> the argument <b>MUST</b> denote an entire list (i.e. a call
  54.155 - * to ucx_list_first() on the argument must return the argument itself)
  54.156 - * 
  54.157 - * @param list the list to free
  54.158 - * @see ucx_list_free_contents()
  54.159 - */
  54.160 -void ucx_list_free(UcxList *list);
  54.161 -
  54.162 -/**
  54.163 - * Destroys the entire list using a UcxAllocator.
  54.164 - * 
  54.165 - * See ucx_list_free() for details.
  54.166 - * 
  54.167 - * @param allocator the allocator to use
  54.168 - * @param list the list to free
  54.169 - * @see ucx_list_free()
  54.170 - */
  54.171 -void ucx_list_free_a(UcxAllocator *allocator, UcxList *list);
  54.172 -
  54.173 -/**
  54.174 - * Destroys the contents of the specified list by calling the specified
  54.175 - * destructor on each of them.
  54.176 - * 
  54.177 - * Note, that the contents are not usable afterwards and the list should be
  54.178 - * destroyed with ucx_list_free().
  54.179 - * 
  54.180 - * @param list the list for which the contents shall be freed
  54.181 - * @param destr the destructor function (e.g. stdlib free())
  54.182 - * @see ucx_list_free()
  54.183 - */
  54.184 -void ucx_list_free_content(UcxList* list, ucx_destructor destr);
  54.185 -
  54.186 -
  54.187 -/**
  54.188 - * Inserts an element at the end of the list.
  54.189 - * 
  54.190 - * This is generally an O(n) operation, as the end of the list is retrieved with
  54.191 - * ucx_list_last().
  54.192 - * 
  54.193 - * @param list the list where to append the data, or <code>NULL</code> to
  54.194 - * create a new list
  54.195 - * @param data the data to insert
  54.196 - * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  54.197 - * the newly created list otherwise
  54.198 - */
  54.199 -UcxList *ucx_list_append(UcxList *list, void *data);
  54.200 -
  54.201 -/**
  54.202 - * Inserts an element at the end of the list using a UcxAllocator.
  54.203 - * 
  54.204 - * See ucx_list_append() for details.
  54.205 - * 
  54.206 - * @param allocator the allocator to use
  54.207 - * @param list the list where to append the data, or <code>NULL</code> to
  54.208 - * create a new list
  54.209 - * @param data the data to insert
  54.210 - * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  54.211 - * the newly created list otherwise
  54.212 - * @see ucx_list_append()
  54.213 - */
  54.214 -UcxList *ucx_list_append_a(UcxAllocator *allocator, UcxList *list, void *data);
  54.215 -
  54.216 -/**
  54.217 - * Inserts an element at the end of the list, if it is not present in the list.
  54.218 - * 
  54.219 - * 
  54.220 - * @param list the list where to append the data, or <code>NULL</code> to
  54.221 - * create a new list
  54.222 - * @param data the data to insert
  54.223 - * @param cmpfnc the compare function
  54.224 - * @param cmpdata additional data for the compare function
  54.225 - * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  54.226 - * the newly created list otherwise
  54.227 - * @see ucx_list_append()
  54.228 - */
  54.229 -UcxList *ucx_list_append_once(UcxList *list, void *data,
  54.230 -        cmp_func cmpfnc, void *cmpdata);
  54.231 -
  54.232 -/**
  54.233 - * Inserts an element at the end of the list, if it is not present in the list,
  54.234 - * using a UcxAllocator.
  54.235 - * 
  54.236 - * See ucx_list_append() for details.
  54.237 - * 
  54.238 - * @param allocator the allocator to use
  54.239 - * @param list the list where to append the data, or <code>NULL</code> to
  54.240 - * create a new list
  54.241 - * @param data the data to insert
  54.242 - * @param cmpfnc the compare function
  54.243 - * @param cmpdata additional data for the compare function
  54.244 - * @return <code>list</code>, if it is not <code>NULL</code> or a pointer to
  54.245 - * the newly created list otherwise
  54.246 - * @see ucx_list_append_a()
  54.247 - */
  54.248 -UcxList *ucx_list_append_once_a(UcxAllocator *allocator,
  54.249 -        UcxList *list, void *data, cmp_func cmpfnc, void *cmpdata);
  54.250 -
  54.251 -/**
  54.252 - * Inserts an element at the beginning of the list.
  54.253 - * 
  54.254 - * You <i>should</i> overwrite the old list pointer by calling
  54.255 - * <code>mylist = ucx_list_prepend(mylist, mydata);</code>. However, you may
  54.256 - * also perform successive calls of ucx_list_prepend() on the same list pointer,
  54.257 - * as this function always searchs for the head of the list with
  54.258 - * ucx_list_first().
  54.259 - * 
  54.260 - * @param list the list where to insert the data or <code>NULL</code> to create
  54.261 - * a new list
  54.262 - * @param data the data to insert
  54.263 - * @return a pointer to the new list head
  54.264 - */
  54.265 -UcxList *ucx_list_prepend(UcxList *list, void *data);
  54.266 -
  54.267 -/**
  54.268 - * Inserts an element at the beginning of the list using a UcxAllocator.
  54.269 - * 
  54.270 - * See ucx_list_prepend() for details.
  54.271 - * 
  54.272 - * @param allocator the allocator to use
  54.273 - * @param list the list where to insert the data or <code>NULL</code> to create
  54.274 - * a new list
  54.275 - * @param data the data to insert
  54.276 - * @return a pointer to the new list head
  54.277 - * @see ucx_list_prepend()
  54.278 - */
  54.279 -UcxList *ucx_list_prepend_a(UcxAllocator *allocator, UcxList *list, void *data);
  54.280 -
  54.281 -/**
  54.282 - * Concatenates two lists.
  54.283 - * 
  54.284 - * Either of the two arguments may be <code>NULL</code>.
  54.285 - * 
  54.286 - * This function modifies the references to the next/previous element of
  54.287 - * the last/first element of <code>list1</code>/<code>
  54.288 - * list2</code>.
  54.289 - * 
  54.290 - * @param list1 first list
  54.291 - * @param list2 second list
  54.292 - * @return if <code>list1</code> is <code>NULL</code>, <code>list2</code> is
  54.293 - * returned, otherwise <code>list1</code> is returned
  54.294 - */
  54.295 -UcxList *ucx_list_concat(UcxList *list1, UcxList *list2);
  54.296 -
  54.297 -/**
  54.298 - * Returns the first element of a list.
  54.299 - * 
  54.300 - * If the argument is the list pointer, it is directly returned. Otherwise
  54.301 - * this function traverses to the first element of the list and returns the
  54.302 - * list pointer.
  54.303 - * 
  54.304 - * @param elem one element of the list
  54.305 - * @return the first element of the list, the specified element is a member of
  54.306 - */
  54.307 -UcxList *ucx_list_first(const UcxList *elem);
  54.308 -
  54.309 -/**
  54.310 - * Returns the last element of a list.
  54.311 - * 
  54.312 - * If the argument has no successor, it is the last element and therefore
  54.313 - * directly returned. Otherwise this function traverses to the last element of
  54.314 - * the list and returns it.
  54.315 - * 
  54.316 - * @param elem one element of the list
  54.317 - * @return the last element of the list, the specified element is a member of
  54.318 - */
  54.319 -UcxList *ucx_list_last(const UcxList *elem);
  54.320 -
  54.321 -/**
  54.322 - * Returns the list element at the specified index.
  54.323 - * 
  54.324 - * @param list the list to retrieve the element from
  54.325 - * @param index index of the element to return
  54.326 - * @return the element at the specified index or <code>NULL</code>, if the
  54.327 - * index is greater than the list size
  54.328 - */
  54.329 -UcxList *ucx_list_get(const UcxList *list, size_t index);
  54.330 -
  54.331 -/**
  54.332 - * Returns the index of an element.
  54.333 - * 
  54.334 - * @param list the list where to search for the element
  54.335 - * @param elem the element to find
  54.336 - * @return the index of the element or -1 if the list does not contain the
  54.337 - * element
  54.338 - */
  54.339 -ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem);
  54.340 -
  54.341 -/**
  54.342 - * Returns the element count of the list.
  54.343 - * 
  54.344 - * @param list the list whose elements are counted
  54.345 - * @return the element count
  54.346 - */
  54.347 -size_t ucx_list_size(const UcxList *list);
  54.348 -
  54.349 -/**
  54.350 - * Returns the index of an element containing the specified data.
  54.351 - *
  54.352 - * This function uses a cmp_func() to compare the data of each list element
  54.353 - * with the specified data. If no cmp_func is provided, the pointers are
  54.354 - * compared.
  54.355 - * 
  54.356 - * If the list contains the data more than once, the index of the first
  54.357 - * occurrence is returned.
  54.358 - *  
  54.359 - * @param list the list where to search for the data
  54.360 - * @param elem the element data
  54.361 - * @param cmpfnc the compare function
  54.362 - * @param data additional data for the compare function
  54.363 - * @return the index of the element containing the specified data or -1 if the
  54.364 - * data is not found in this list
  54.365 - */
  54.366 -ssize_t ucx_list_find(UcxList *list, void *elem, cmp_func cmpfnc, void *data);
  54.367 -
  54.368 -/**
  54.369 - * Checks, if a list contains a specific element.
  54.370 - * 
  54.371 - * An element is found, if ucx_list_find() returns a value greater than -1.
  54.372 - * 
  54.373 - * @param list the list where to search for the data
  54.374 - * @param elem the element data
  54.375 - * @param cmpfnc the compare function
  54.376 - * @param data additional data for the compare function
  54.377 - * @return 1, if and only if the list contains the specified element data
  54.378 - * @see ucx_list_find()
  54.379 - */
  54.380 -int ucx_list_contains(UcxList *list, void *elem, cmp_func cmpfnc, void *data);
  54.381 -
  54.382 -/**
  54.383 - * Sorts a UcxList with natural merge sort.
  54.384 - * 
  54.385 - * This function uses O(n) additional temporary memory for merge operations
  54.386 - * that is automatically freed after each merge.
  54.387 - * 
  54.388 - * As the head of the list might change, you <b>MUST</b> call this function
  54.389 - * as follows: <code>mylist = ucx_list_sort(mylist, mycmpfnc, mydata);</code>.
  54.390 - * 
  54.391 - * @param list the list to sort
  54.392 - * @param cmpfnc the function that shall be used to compare the element data
  54.393 - * @param data additional data for the cmp_func()
  54.394 - * @return the sorted list
  54.395 - */
  54.396 -UcxList *ucx_list_sort(UcxList *list, cmp_func cmpfnc, void *data);
  54.397 -
  54.398 -/**
  54.399 - * Removes an element from the list.
  54.400 - * 
  54.401 - * If the first element is removed, the list pointer changes. So it is
  54.402 - * <i>highly recommended</i> to <i>always</i> update the pointer by calling
  54.403 - * <code>mylist = ucx_list_remove(mylist, myelem);</code>.
  54.404 - * 
  54.405 - * @param list the list from which the element shall be removed
  54.406 - * @param element the element to remove
  54.407 - * @return returns the updated list pointer or <code>NULL</code>, if the list
  54.408 - * is now empty
  54.409 - */
  54.410 -UcxList *ucx_list_remove(UcxList *list, UcxList *element);
  54.411 -
  54.412 -/**
  54.413 - * Removes an element from the list using a UcxAllocator.
  54.414 - * 
  54.415 - * See ucx_list_remove() for details.
  54.416 - * 
  54.417 - * @param allocator the allocator to use
  54.418 - * @param list the list from which the element shall be removed
  54.419 - * @param element the element to remove
  54.420 - * @return returns the updated list pointer or <code>NULL</code>, if the list
  54.421 - * @see ucx_list_remove()
  54.422 - */
  54.423 -UcxList *ucx_list_remove_a(UcxAllocator *allocator, UcxList *list,
  54.424 -        UcxList *element);
  54.425 -
  54.426 -#ifdef	__cplusplus
  54.427 -}
  54.428 -#endif
  54.429 -
  54.430 -#endif	/* UCX_LIST_H */
  54.431 -
    55.1 --- a/ucx/logging.c	Tue Oct 17 15:15:54 2017 +0200
    55.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3 @@ -1,105 +0,0 @@
    55.4 -/*
    55.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    55.6 - *
    55.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    55.8 - *
    55.9 - * Redistribution and use in source and binary forms, with or without
   55.10 - * modification, are permitted provided that the following conditions are met:
   55.11 - *
   55.12 - *   1. Redistributions of source code must retain the above copyright
   55.13 - *      notice, this list of conditions and the following disclaimer.
   55.14 - *
   55.15 - *   2. Redistributions in binary form must reproduce the above copyright
   55.16 - *      notice, this list of conditions and the following disclaimer in the
   55.17 - *      documentation and/or other materials provided with the distribution.
   55.18 - *
   55.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   55.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   55.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   55.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   55.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   55.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   55.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   55.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   55.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   55.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   55.29 - * POSSIBILITY OF SUCH DAMAGE.
   55.30 - */
   55.31 -
   55.32 -#include "logging.h"
   55.33 -#include <stdlib.h>
   55.34 -#include <string.h>
   55.35 -#include <stdarg.h>
   55.36 -#include <time.h>
   55.37 -
   55.38 -UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask) {
   55.39 -    UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger));
   55.40 -    if (logger != NULL) {
   55.41 -        logger->stream = stream;
   55.42 -        logger->writer = (write_func)fwrite;
   55.43 -        logger->dateformat = (char*) "%F %T %z ";
   55.44 -        logger->level = level;
   55.45 -        logger->mask = mask;
   55.46 -        logger->levels = ucx_map_new(8);
   55.47 -        
   55.48 -        unsigned int l;
   55.49 -        l = UCX_LOGGER_ERROR;
   55.50 -        ucx_map_int_put(logger->levels, l, (void*) "[ERROR]");
   55.51 -        l = UCX_LOGGER_WARN;
   55.52 -        ucx_map_int_put(logger->levels, l, (void*) "[WARNING]");
   55.53 -        l = UCX_LOGGER_INFO;
   55.54 -        ucx_map_int_put(logger->levels, l, (void*) "[INFO]");
   55.55 -        l = UCX_LOGGER_TRACE;
   55.56 -        ucx_map_int_put(logger->levels, l, (void*) "[TRACE]");
   55.57 -    }
   55.58 -
   55.59 -    return logger;
   55.60 -}
   55.61 -
   55.62 -void ucx_logger_free(UcxLogger *logger) {
   55.63 -    ucx_map_free(logger->levels);
   55.64 -    free(logger);
   55.65 -}
   55.66 -
   55.67 -// estimated max. message length (documented)
   55.68 -#define UCX_LOGGER_MSGMAX 4096
   55.69 -
   55.70 -void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
   55.71 -        const unsigned int line, const char *format, ...) {
   55.72 -    if (level <= logger->level) {
   55.73 -        char msg[UCX_LOGGER_MSGMAX];
   55.74 -        char *text;
   55.75 -        size_t k = 0;
   55.76 -        size_t n;
   55.77 -        
   55.78 -        if ((logger->mask & UCX_LOGGER_LEVEL) > 0) {
   55.79 -            text = (char*) ucx_map_int_get(logger->levels, level);
   55.80 -            n = strlen(text);
   55.81 -            n = n > 256 ? 256 : n;
   55.82 -            memcpy(msg+k, text, n);
   55.83 -            k += n;
   55.84 -            msg[k++] = ' ';
   55.85 -        }
   55.86 -        if ((logger->mask & UCX_LOGGER_TIMESTAMP) > 0) {
   55.87 -            time_t now = time(NULL);
   55.88 -            k += strftime(msg+k, 128, logger->dateformat, localtime(&now));
   55.89 -        }
   55.90 -        if ((logger->mask & UCX_LOGGER_SOURCE) > 0) {
   55.91 -            n = strlen(file);
   55.92 -            memcpy(msg+k, file, n);
   55.93 -            k += n;
   55.94 -            k += sprintf(msg+k, ":%u ", line);
   55.95 -        }
   55.96 -        
   55.97 -        msg[k++] = '-'; msg[k++] = ' ';
   55.98 -        
   55.99 -        va_list args;
  55.100 -        va_start (args, format);
  55.101 -        k += vsnprintf(msg+k, UCX_LOGGER_MSGMAX-k-1, format, args);
  55.102 -        va_end (args);        
  55.103 -        
  55.104 -        msg[k++] = '\n';
  55.105 -        
  55.106 -        logger->writer(msg, 1, k, logger->stream);
  55.107 -    }
  55.108 -}
    56.1 --- a/ucx/logging.h	Tue Oct 17 15:15:54 2017 +0200
    56.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.3 @@ -1,238 +0,0 @@
    56.4 -/*
    56.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    56.6 - *
    56.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    56.8 - *
    56.9 - * Redistribution and use in source and binary forms, with or without
   56.10 - * modification, are permitted provided that the following conditions are met:
   56.11 - *
   56.12 - *   1. Redistributions of source code must retain the above copyright
   56.13 - *      notice, this list of conditions and the following disclaimer.
   56.14 - *
   56.15 - *   2. Redistributions in binary form must reproduce the above copyright
   56.16 - *      notice, this list of conditions and the following disclaimer in the
   56.17 - *      documentation and/or other materials provided with the distribution.
   56.18 - *
   56.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   56.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   56.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   56.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   56.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   56.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   56.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   56.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   56.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   56.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   56.29 - * POSSIBILITY OF SUCH DAMAGE.
   56.30 - */
   56.31 -/**
   56.32 - * Logging API.
   56.33 - * 
   56.34 - * @file   logging.h
   56.35 - * @author Mike Becker, Olaf Wintermann
   56.36 - */
   56.37 -#ifndef UCX_LOGGING_H
   56.38 -#define UCX_LOGGING_H
   56.39 -
   56.40 -#include "ucx.h"
   56.41 -#include "map.h"
   56.42 -#include "string.h"
   56.43 -#include <stdio.h>
   56.44 -
   56.45 -#ifdef __cplusplus
   56.46 -extern "C" {
   56.47 -#endif
   56.48 -
   56.49 -/* leave enough space for custom log levels */
   56.50 -
   56.51 -/** Log level for error messages. */
   56.52 -#define UCX_LOGGER_ERROR        0x00
   56.53 -    
   56.54 -/** Log level for warning messages. */
   56.55 -#define UCX_LOGGER_WARN         0x10
   56.56 -
   56.57 -/** Log level for information messages. */
   56.58 -#define UCX_LOGGER_INFO         0x20
   56.59 -
   56.60 -/** Log level for debug messages. */
   56.61 -#define UCX_LOGGER_DEBUG        0x30
   56.62 -
   56.63 -/** Log level for trace messages. */
   56.64 -#define UCX_LOGGER_TRACE        0x40
   56.65 -
   56.66 -/**
   56.67 - * Output flag for the log level. 
   56.68 - * If this flag is set, the log message will contain the log level.
   56.69 - * @see UcxLogger.mask
   56.70 - */
   56.71 -#define UCX_LOGGER_LEVEL        0x01
   56.72 -
   56.73 -/**
   56.74 - * Output flag for the timestmap.
   56.75 - * If this flag is set, the log message will contain the timestmap.
   56.76 - * @see UcxLogger.mask
   56.77 - */
   56.78 -#define UCX_LOGGER_TIMESTAMP    0x02
   56.79 -
   56.80 -/**
   56.81 - * Output flag for the source.
   56.82 - * If this flag is set, the log message will contain the source file and line
   56.83 - * number.
   56.84 - * @see UcxLogger.mask
   56.85 - */
   56.86 -#define UCX_LOGGER_SOURCE       0x04
   56.87 -
   56.88 -/**
   56.89 - * The UCX Logger object.
   56.90 - */
   56.91 -typedef struct {
   56.92 -    /** The stream this logger writes its messages to.*/
   56.93 -    void *stream;
   56.94 -
   56.95 -    /**
   56.96 -     * The write function that shall be used.
   56.97 -     * For standard file or stdout loggers this might be standard fwrite
   56.98 -     * (default).
   56.99 -     */
  56.100 -    write_func writer;
  56.101 -
  56.102 -    /**
  56.103 -     * The date format for timestamp outputs including the delimiter
  56.104 -     * (default: <code>"%F %T %z "</code>).
  56.105 -     * @see UCX_LOGGER_TIMESTAMP
  56.106 -     */
  56.107 -    char *dateformat;
  56.108 -
  56.109 -    /**
  56.110 -     * The level, this logger operates on.
  56.111 -     * If a log command is issued, the message will only be logged, if the log
  56.112 -     * level of the message is less or equal than the log level of the logger.
  56.113 -     */
  56.114 -    unsigned int level;
  56.115 -
  56.116 -    /**
  56.117 -     * A configuration mask for automatic output. 
  56.118 -     * For each flag that is set, the logger automatically outputs some extra
  56.119 -     * information like the timestamp or the source file and line number.
  56.120 -     * See the documentation for the flags for details.
  56.121 -     */
  56.122 -    unsigned int mask;
  56.123 -
  56.124 -    /**
  56.125 -     * A map of valid log levels for this logger.
  56.126 -     * 
  56.127 -     * The keys represent all valid log levels and the values provide string
  56.128 -     * representations, that are used, if the UCX_LOGGER_LEVEL flag is set.
  56.129 -     * 
  56.130 -     * The exact data types are <code>unsigned int</code> for the key and
  56.131 -     * <code>const char*</code> for the value.
  56.132 -     * 
  56.133 -     * @see UCX_LOGGER_LEVEL
  56.134 -     */
  56.135 -    UcxMap* levels;
  56.136 -} UcxLogger;
  56.137 -
  56.138 -/**
  56.139 - * Creates a new logger.
  56.140 - * @param stream the stream, which the logger shall write to
  56.141 - * @param level the level on which the logger shall operate
  56.142 - * @param mask configuration mask (cf. UcxLogger.mask)
  56.143 - * @return a new logger object
  56.144 - */
  56.145 -UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask);
  56.146 -
  56.147 -/**
  56.148 - * Destroys the logger.
  56.149 - * 
  56.150 - * The map containing the valid log levels is also automatically destroyed.
  56.151 - * 
  56.152 - * @param logger the logger to destroy
  56.153 - */
  56.154 -void ucx_logger_free(UcxLogger* logger);
  56.155 -
  56.156 -/**
  56.157 - * Internal log function - use macros instead.
  56.158 - * 
  56.159 - * This function uses the <code>format</code> and variadic arguments for a
  56.160 - * printf()-style output of the log message.
  56.161 - * 
  56.162 - * Dependent on the UcxLogger.mask some information is prepended. The complete
  56.163 - * format is:
  56.164 - * 
  56.165 - * <code>[LEVEL] [TIMESTAMP] [SOURCEFILE]:[LINENO] message</code>
  56.166 - * 
  56.167 - * <b>Attention:</b> the message (including automatically generated information)
  56.168 - * is limited to 4096 characters. The level description is limited to
  56.169 - * 256 characters and the timestamp string is limited to 128 characters.
  56.170 - * 
  56.171 - * @param logger the logger to use
  56.172 - * @param level the level to log on
  56.173 - * @param file information about the source file
  56.174 - * @param line information about the source line number
  56.175 - * @param format format string
  56.176 - * @param ... arguments
  56.177 - * @see ucx_logger_log()
  56.178 - */
  56.179 -void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
  56.180 -        const unsigned int line, const char* format, ...);
  56.181 -
  56.182 -/**
  56.183 - * Logs a message at the specified level.
  56.184 - * @param logger the logger to use
  56.185 - * @param level the level to log the message on
  56.186 - * @param ... format string and arguments
  56.187 - * @see ucx_logger_logf()
  56.188 - */
  56.189 -#define ucx_logger_log(logger, level, ...) \
  56.190 -    ucx_logger_logf(logger, level, __FILE__, __LINE__, __VA_ARGS__)
  56.191 -
  56.192 -/**
  56.193 - * Shortcut for logging an error message.
  56.194 - * @param logger the logger to use
  56.195 - * @param ... format string and arguments
  56.196 - * @see ucx_logger_logf()
  56.197 - */
  56.198 -#define ucx_logger_error(logger, ...) \
  56.199 -    ucx_logger_log(logger, UCX_LOGGER_ERROR, __VA_ARGS__)
  56.200 -
  56.201 -/**
  56.202 - * Shortcut for logging an information message.
  56.203 - * @param logger the logger to use
  56.204 - * @param ... format string and arguments
  56.205 - * @see ucx_logger_logf()
  56.206 - */
  56.207 -#define ucx_logger_info(logger, ...) \
  56.208 -    ucx_logger_log(logger, UCX_LOGGER_INFO, __VA_ARGS__)
  56.209 -
  56.210 -/**
  56.211 - * Shortcut for logging a warning message.
  56.212 - * @param logger the logger to use
  56.213 - * @param ... format string and arguments
  56.214 - * @see ucx_logger_logf()
  56.215 - */
  56.216 -#define ucx_logger_warn(logger, ...) \
  56.217 -    ucx_logger_log(logger, UCX_LOGGER_WARN, __VA_ARGS__)
  56.218 -
  56.219 -/**
  56.220 - * Shortcut for logging a debug message.
  56.221 - * @param logger the logger to use
  56.222 - * @param ... format string and arguments
  56.223 - * @see ucx_logger_logf()
  56.224 - */
  56.225 -#define ucx_logger_debug(logger, ...) \
  56.226 -    ucx_logger_log(logger, UCX_LOGGER_DEBUG, __VA_ARGS__)
  56.227 -
  56.228 -/**
  56.229 - * Shortcut for logging a trace message.
  56.230 - * @param logger the logger to use
  56.231 - * @param ... format string and arguments
  56.232 - * @see ucx_logger_logf()
  56.233 - */
  56.234 -#define ucx_logger_trace(logger, ...) \
  56.235 -    ucx_logger_log(logger, UCX_LOGGER_TRACE, __VA_ARGS__)
  56.236 -
  56.237 -#ifdef __cplusplus
  56.238 -}
  56.239 -#endif
  56.240 -
  56.241 -#endif /* UCX_LOGGING_H */
    57.1 --- a/ucx/map.c	Tue Oct 17 15:15:54 2017 +0200
    57.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3 @@ -1,328 +0,0 @@
    57.4 -/*
    57.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    57.6 - *
    57.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    57.8 - *
    57.9 - * Redistribution and use in source and binary forms, with or without
   57.10 - * modification, are permitted provided that the following conditions are met:
   57.11 - *
   57.12 - *   1. Redistributions of source code must retain the above copyright
   57.13 - *      notice, this list of conditions and the following disclaimer.
   57.14 - *
   57.15 - *   2. Redistributions in binary form must reproduce the above copyright
   57.16 - *      notice, this list of conditions and the following disclaimer in the
   57.17 - *      documentation and/or other materials provided with the distribution.
   57.18 - *
   57.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   57.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   57.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   57.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   57.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   57.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   57.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   57.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   57.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   57.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   57.29 - * POSSIBILITY OF SUCH DAMAGE.
   57.30 - */
   57.31 -
   57.32 -#include <stdlib.h>
   57.33 -#include <string.h>
   57.34 -
   57.35 -#include "map.h"
   57.36 -
   57.37 -UcxMap *ucx_map_new(size_t size) {
   57.38 -    return ucx_map_new_a(NULL, size);
   57.39 -}
   57.40 -
   57.41 -UcxMap *ucx_map_new_a(UcxAllocator *allocator, size_t size) {
   57.42 -    if(size == 0) {
   57.43 -        size = 16;
   57.44 -    }
   57.45 -       
   57.46 -    if(!allocator) {
   57.47 -        allocator = ucx_default_allocator();
   57.48 -    }
   57.49 -    
   57.50 -    UcxMap *map = (UcxMap*)almalloc(allocator, sizeof(UcxMap));
   57.51 -    if (!map) {
   57.52 -        return NULL;
   57.53 -    }
   57.54 -    
   57.55 -    map->allocator = allocator;
   57.56 -    map->map = (UcxMapElement**)alcalloc(
   57.57 -            allocator, size, sizeof(UcxMapElement*));
   57.58 -    if(map->map == NULL) {
   57.59 -        alfree(allocator, map);
   57.60 -        return NULL;
   57.61 -    }
   57.62 -    map->size = size;
   57.63 -    map->count = 0;
   57.64 -
   57.65 -    return map;
   57.66 -}
   57.67 -
   57.68 -static void ucx_map_free_elmlist_contents(UcxMap *map) {
   57.69 -    for (size_t n = 0 ; n < map->size ; n++) {
   57.70 -        UcxMapElement *elem = map->map[n];
   57.71 -        if (elem != NULL) {
   57.72 -            do {
   57.73 -                UcxMapElement *next = elem->next;
   57.74 -                alfree(map->allocator, elem->key.data);
   57.75 -                alfree(map->allocator, elem);
   57.76 -                elem = next;
   57.77 -            } while (elem != NULL);
   57.78 -        }
   57.79 -    }
   57.80 -}
   57.81 -
   57.82 -void ucx_map_free(UcxMap *map) {
   57.83 -    ucx_map_free_elmlist_contents(map);
   57.84 -    alfree(map->allocator, map->map);
   57.85 -    alfree(map->allocator, map);
   57.86 -}
   57.87 -
   57.88 -void ucx_map_free_content(UcxMap *map, ucx_destructor destr) {
   57.89 -    UcxMapIterator iter = ucx_map_iterator(map);
   57.90 -    void *val;
   57.91 -    UCX_MAP_FOREACH(key, val, iter) {
   57.92 -        destr(val);
   57.93 -    }
   57.94 -}
   57.95 -
   57.96 -void ucx_map_clear(UcxMap *map) {
   57.97 -    if (map->count == 0) {
   57.98 -        return; // nothing to do
   57.99 -    }
  57.100 -    ucx_map_free_elmlist_contents(map);
  57.101 -    memset(map->map, 0, map->size*sizeof(UcxMapElement*));
  57.102 -    map->count = 0;
  57.103 -}
  57.104 -
  57.105 -int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
  57.106 -        copy_func fnc, void *data) {
  57.107 -    UcxMapIterator i = ucx_map_iterator(from);
  57.108 -    void *value;
  57.109 -    UCX_MAP_FOREACH(key, value, i) {
  57.110 -        if (ucx_map_put(to, key, fnc ? fnc(value, data) : value)) {
  57.111 -            return 1;
  57.112 -        }
  57.113 -    }
  57.114 -    return 0;
  57.115 -}
  57.116 -
  57.117 -UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data) {
  57.118 -    size_t bs = (map->count * 5) >> 1;
  57.119 -    UcxMap *newmap = ucx_map_new(bs > map->size ? bs : map->size);
  57.120 -    if (!newmap) {
  57.121 -        return NULL;
  57.122 -    }
  57.123 -    ucx_map_copy(map, newmap, fnc, data);
  57.124 -    return newmap;
  57.125 -}
  57.126 -
  57.127 -int ucx_map_rehash(UcxMap *map) {
  57.128 -    size_t load = (map->size * 3) >> 2;
  57.129 -    if (map->count > load) {
  57.130 -        UcxMap oldmap;
  57.131 -        oldmap.map = map->map;
  57.132 -        oldmap.size = map->size;
  57.133 -        oldmap.count = map->count;
  57.134 -        oldmap.allocator = map->allocator;
  57.135 -        
  57.136 -        map->size = (map->count * 5) >> 1;
  57.137 -        map->map = (UcxMapElement**)alcalloc(
  57.138 -                map->allocator, map->size, sizeof(UcxMapElement*));
  57.139 -        if (!map->map) {
  57.140 -            *map = oldmap;
  57.141 -            return 1;
  57.142 -        }
  57.143 -        map->count = 0;
  57.144 -        ucx_map_copy(&oldmap, map, NULL, NULL);
  57.145 -        
  57.146 -        /* free the UcxMapElement list of oldmap */
  57.147 -        ucx_map_free_elmlist_contents(&oldmap);
  57.148 -        alfree(map->allocator, oldmap.map);
  57.149 -    }
  57.150 -    return 0;
  57.151 -}
  57.152 -
  57.153 -int ucx_map_put(UcxMap *map, UcxKey key, void *data) {
  57.154 -    UcxAllocator *allocator = map->allocator;
  57.155 -    
  57.156 -    if (key.hash == 0) {
  57.157 -        key.hash = ucx_hash((char*)key.data, key.len);
  57.158 -    }
  57.159 -
  57.160 -    size_t slot = key.hash%map->size;
  57.161 -    UcxMapElement *restrict elm = map->map[slot];
  57.162 -    UcxMapElement *restrict prev = NULL;
  57.163 -
  57.164 -    while (elm && elm->key.hash < key.hash) {
  57.165 -        prev = elm;
  57.166 -        elm = elm->next;
  57.167 -    }
  57.168 -    
  57.169 -    if (!elm || elm->key.hash != key.hash) {
  57.170 -        UcxMapElement *e = (UcxMapElement*)almalloc(
  57.171 -                allocator, sizeof(UcxMapElement));
  57.172 -        if (!e) {
  57.173 -            return -1;
  57.174 -        }
  57.175 -        e->key.data = NULL;
  57.176 -        if (prev) {
  57.177 -            prev->next = e;
  57.178 -        } else {
  57.179 -            map->map[slot] = e;
  57.180 -        }
  57.181 -        e->next = elm;
  57.182 -        elm = e;
  57.183 -    }
  57.184 -    
  57.185 -    if (!elm->key.data) {
  57.186 -        void *kd = almalloc(allocator, key.len);
  57.187 -        if (!kd) {
  57.188 -            return -1;
  57.189 -        }
  57.190 -        memcpy(kd, key.data, key.len);
  57.191 -        key.data = kd;
  57.192 -        elm->key = key;
  57.193 -        map->count++;
  57.194 -    }
  57.195 -    elm->data = data;
  57.196 -
  57.197 -    return 0;
  57.198 -}
  57.199 -
  57.200 -void* ucx_map_get_and_remove(UcxMap *map, UcxKey key, _Bool remove) {
  57.201 -    if(key.hash == 0) {
  57.202 -        key.hash = ucx_hash((char*)key.data, key.len);
  57.203 -    }
  57.204 -    
  57.205 -    size_t slot = key.hash%map->size;
  57.206 -    UcxMapElement *restrict elm = map->map[slot];
  57.207 -    UcxMapElement *restrict pelm = NULL;
  57.208 -    while (elm && elm->key.hash <= key.hash) {
  57.209 -        if(elm->key.hash == key.hash) {
  57.210 -            int n = (key.len > elm->key.len) ? elm->key.len : key.len;
  57.211 -            if (memcmp(elm->key.data, key.data, n) == 0) {
  57.212 -                void *data = elm->data;
  57.213 -                if (remove) {
  57.214 -                    if (pelm) {
  57.215 -                        pelm->next = elm->next;
  57.216 -                    } else {
  57.217 -                        map->map[slot] = elm->next;
  57.218 -                    }
  57.219 -                    alfree(map->allocator, elm->key.data);
  57.220 -                    alfree(map->allocator, elm);
  57.221 -                    map->count--;
  57.222 -                }
  57.223 -
  57.224 -                return data;
  57.225 -            }
  57.226 -        }
  57.227 -        pelm = elm;
  57.228 -        elm = pelm->next;
  57.229 -    }
  57.230 -
  57.231 -    return NULL;
  57.232 -}
  57.233 -
  57.234 -void *ucx_map_get(UcxMap *map, UcxKey key) {
  57.235 -    return ucx_map_get_and_remove(map, key, 0);
  57.236 -}
  57.237 -
  57.238 -void *ucx_map_remove(UcxMap *map, UcxKey key) {
  57.239 -    return ucx_map_get_and_remove(map, key, 1);
  57.240 -}
  57.241 -
  57.242 -UcxKey ucx_key(void *data, size_t len) {
  57.243 -    UcxKey key;
  57.244 -    key.data = data;
  57.245 -    key.len = len;
  57.246 -    key.hash = ucx_hash((const char*) data, len);
  57.247 -    return key;
  57.248 -}
  57.249 -
  57.250 -
  57.251 -int ucx_hash(const char *data, size_t len) {
  57.252 -    /* murmur hash 2 */
  57.253 -
  57.254 -    int m = 0x5bd1e995;
  57.255 -    int r = 24;
  57.256 -
  57.257 -    int h = 25 ^ len;
  57.258 -
  57.259 -    int i = 0;
  57.260 -    while (len >= 4) {
  57.261 -        int k = data[i + 0] & 0xFF;
  57.262 -        k |= (data[i + 1] & 0xFF) << 8;
  57.263 -        k |= (data[i + 2] & 0xFF) << 16;
  57.264 -        k |= (data[i + 3] & 0xFF) << 24;
  57.265 -
  57.266 -        k *= m;
  57.267 -        k ^= k >> r;
  57.268 -        k *= m;
  57.269 -
  57.270 -        h *= m;
  57.271 -        h ^= k;
  57.272 -
  57.273 -        i += 4;
  57.274 -        len -= 4;
  57.275 -    }
  57.276 -
  57.277 -    switch (len) {
  57.278 -        case 3: h ^= (data[i + 2] & 0xFF) << 16;
  57.279 -        /* no break */
  57.280 -        case 2: h ^= (data[i + 1] & 0xFF) << 8;
  57.281 -        /* no break */
  57.282 -        case 1: h ^= (data[i + 0] & 0xFF); h *= m;
  57.283 -        /* no break */
  57.284 -    }
  57.285 -
  57.286 -    h ^= h >> 13;
  57.287 -    h *= m;
  57.288 -    h ^= h >> 15;
  57.289 -
  57.290 -    return h;
  57.291 -}
  57.292 -
  57.293 -UcxMapIterator ucx_map_iterator(UcxMap *map) {
  57.294 -    UcxMapIterator i;
  57.295 -    i.map = map;
  57.296 -    i.cur = NULL;
  57.297 -    i.index = 0;
  57.298 -    return i;
  57.299 -}
  57.300 -
  57.301 -int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm) {
  57.302 -    UcxMapElement *e = i->cur;
  57.303 -    
  57.304 -    if (e) {
  57.305 -        e = e->next;
  57.306 -    } else {
  57.307 -        e = i->map->map[0];
  57.308 -    }
  57.309 -    
  57.310 -    while (i->index < i->map->size) {
  57.311 -        if (e) {
  57.312 -            if (e->data) {
  57.313 -                i->cur = e;
  57.314 -                *elm = e->data;
  57.315 -                *key = e->key;
  57.316 -                return 1;
  57.317 -            }
  57.318 -
  57.319 -            e = e->next;
  57.320 -        } else {
  57.321 -            i->index++;
  57.322 -            
  57.323 -            if (i->index < i->map->size) {
  57.324 -                e = i->map->map[i->index];
  57.325 -            }
  57.326 -        }
  57.327 -    }
  57.328 -    
  57.329 -    return 0;
  57.330 -}
  57.331 -
    58.1 --- a/ucx/map.h	Tue Oct 17 15:15:54 2017 +0200
    58.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.3 @@ -1,423 +0,0 @@
    58.4 -/*
    58.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    58.6 - *
    58.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    58.8 - *
    58.9 - * Redistribution and use in source and binary forms, with or without
   58.10 - * modification, are permitted provided that the following conditions are met:
   58.11 - *
   58.12 - *   1. Redistributions of source code must retain the above copyright
   58.13 - *      notice, this list of conditions and the following disclaimer.
   58.14 - *
   58.15 - *   2. Redistributions in binary form must reproduce the above copyright
   58.16 - *      notice, this list of conditions and the following disclaimer in the
   58.17 - *      documentation and/or other materials provided with the distribution.
   58.18 - *
   58.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   58.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   58.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   58.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   58.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   58.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   58.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   58.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   58.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   58.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   58.29 - * POSSIBILITY OF SUCH DAMAGE.
   58.30 - */
   58.31 -
   58.32 -/**
   58.33 - * @file map.h
   58.34 - * 
   58.35 - * Hash map implementation.
   58.36 - * 
   58.37 - * This implementation uses murmur hash 2 and separate chaining with linked
   58.38 - * lists.
   58.39 - * 
   58.40 - * @author Mike Becker
   58.41 - * @author Olaf Wintermann
   58.42 - */
   58.43 -
   58.44 -#ifndef UCX_MAP_H
   58.45 -#define	UCX_MAP_H
   58.46 -
   58.47 -#include "ucx.h"
   58.48 -#include "string.h"
   58.49 -#include "allocator.h"
   58.50 -#include <stdio.h>
   58.51 -
   58.52 -#ifdef	__cplusplus
   58.53 -extern "C" {
   58.54 -#endif
   58.55 -
   58.56 -/**
   58.57 - * Loop statement for UCX maps.
   58.58 - * 
   58.59 - * The <code>key</code> variable is implicitly defined, but the
   58.60 - * <code>value</code> variable must be already declared as type information
   58.61 - * cannot be inferred.
   58.62 - * 
   58.63 - * @param key the variable name for the key
   58.64 - * @param value the variable name for the value
   58.65 - * @param iter a UcxMapIterator
   58.66 - * @see ucx_map_iterator()
   58.67 - */
   58.68 -#define UCX_MAP_FOREACH(key,value,iter) \
   58.69 -        for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&value);)
   58.70 -
   58.71 -/** Type for the UCX map. @see UcxMap */
   58.72 -typedef struct UcxMap          UcxMap;
   58.73 -
   58.74 -/** Type for a key of a UcxMap. @see UcxKey */
   58.75 -typedef struct UcxKey          UcxKey;
   58.76 -
   58.77 -/** Type for an element of a UcxMap. @see UcxMapElement */
   58.78 -typedef struct UcxMapElement   UcxMapElement;
   58.79 -
   58.80 -/** Type for an iterator over a UcxMap. @see UcxMapIterator */
   58.81 -typedef struct UcxMapIterator  UcxMapIterator;
   58.82 -
   58.83 -/** Structure for the UCX map. */
   58.84 -struct UcxMap {
   58.85 -    /** An allocator that is used for the map elements. */
   58.86 -    UcxAllocator  *allocator;
   58.87 -    /** The array of map element lists. */
   58.88 -    UcxMapElement **map;
   58.89 -    /** The size of the map is the length of the element list array. */
   58.90 -    size_t        size;
   58.91 -    /** The count of elements currently stored in this map. */
   58.92 -    size_t        count;
   58.93 -};
   58.94 -
   58.95 -/** Structure for a key of a UcxMap. */
   58.96 -struct UcxKey {
   58.97 -    /** The key data. */
   58.98 -    void   *data;
   58.99 -    /** The length of the key data. */
  58.100 -    size_t len;
  58.101 -    /** The hash value of the key data. */
  58.102 -    int    hash;
  58.103 -};
  58.104 -
  58.105 -/** Structure for an element of a UcxMap. */
  58.106 -struct UcxMapElement {
  58.107 -    /** The value data. */
  58.108 -    void          *data;
  58.109 -    
  58.110 -    /** A pointer to the next element in the current list. */
  58.111 -    UcxMapElement *next;
  58.112 -    
  58.113 -    /** The corresponding key. */
  58.114 -    UcxKey        key;
  58.115 -};
  58.116 -
  58.117 -/** Structure for an iterator over a UcxMap. */
  58.118 -struct UcxMapIterator {
  58.119 -    /** The map to iterate over. */
  58.120 -    UcxMap        *map;
  58.121 -    
  58.122 -    /** The current map element. */
  58.123 -    UcxMapElement *cur;
  58.124 -    
  58.125 -    /**
  58.126 -     * The current index of the element list array.
  58.127 -     * <b>Attention: </b> this is <b>NOT</b> the element index! Do <b>NOT</b>
  58.128 -     * manually iterate over the map by increasing this index. Use
  58.129 -     * ucx_map_iter_next().
  58.130 -     * @see UcxMap.map*/
  58.131 -    size_t        index;
  58.132 -};
  58.133 -
  58.134 -/**
  58.135 - * Creates a new hash map with the specified size.
  58.136 - * @param size the size of the hash map
  58.137 - * @return a pointer to the new hash map
  58.138 - */
  58.139 -UcxMap *ucx_map_new(size_t size);
  58.140 -
  58.141 -/**
  58.142 - * Creates a new hash map with the specified size using a UcxAllocator.
  58.143 - * @param allocator the allocator to use
  58.144 - * @param size the size of the hash map
  58.145 - * @return a pointer to the new hash map
  58.146 - */
  58.147 -UcxMap *ucx_map_new_a(UcxAllocator *allocator, size_t size);
  58.148 -
  58.149 -/**
  58.150 - * Frees a hash map.
  58.151 - * 
  58.152 - * <b>Note:</b> the contents are <b>not</b> freed, use ucx_map_free_content()
  58.153 - * before calling this function to achieve that.
  58.154 - * 
  58.155 - * @param map the map to be freed
  58.156 - * @see ucx_map_free_content()
  58.157 - */
  58.158 -void ucx_map_free(UcxMap *map);
  58.159 -
  58.160 -/**
  58.161 - * Frees the contents of a hash map.
  58.162 - * 
  58.163 - * This is a convenience function that iterates over the map and passes all
  58.164 - * values to the specified destructor function (e.g. stdlib free()).
  58.165 - * 
  58.166 - * You must ensure, that it is valid to pass each value in the map to the same
  58.167 - * destructor function.
  58.168 - * 
  58.169 - * You should free or clear the map afterwards, as the contents will be invalid.
  58.170 - * 
  58.171 - * @param map for which the contents shall be freed
  58.172 - * @param destr pointer to the destructor function
  58.173 - * @see ucx_map_free()
  58.174 - * @see ucx_map_clear()
  58.175 - */
  58.176 -void ucx_map_free_content(UcxMap *map, ucx_destructor destr);
  58.177 -
  58.178 -/**
  58.179 - * Clears a hash map.
  58.180 - * 
  58.181 - * <b>Note:</b> the contents are <b>not</b> freed, use ucx_map_free_content()
  58.182 - * before calling this function to achieve that.
  58.183 - * 
  58.184 - * @param map the map to be cleared
  58.185 - * @see ucx_map_free_content()
  58.186 - */
  58.187 -void ucx_map_clear(UcxMap *map);
  58.188 -
  58.189 -
  58.190 -/**
  58.191 - * Copies contents from a map to another map using a copy function.
  58.192 - * 
  58.193 - * <b>Note:</b> The destination map does not need to be empty. However, if it
  58.194 - * contains data with keys that are also present in the source map, the contents
  58.195 - * are overwritten.
  58.196 - * 
  58.197 - * @param from the source map
  58.198 - * @param to the destination map
  58.199 - * @param fnc the copy function or <code>NULL</code> if the pointer address
  58.200 - * shall be copied
  58.201 - * @param data additional data for the copy function
  58.202 - * @return 0 on success or a non-zero value on memory allocation errors
  58.203 - */
  58.204 -int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
  58.205 -        copy_func fnc, void *data);
  58.206 -
  58.207 -/**
  58.208 - * Clones the map and rehashes if necessary.
  58.209 - * 
  58.210 - * <b>Note:</b> In contrast to ucx_map_rehash() the load factor is irrelevant.
  58.211 - * This function <i>always</i> ensures a new UcxMap.size of at least
  58.212 - * 2.5*UcxMap.count.
  58.213 - * 
  58.214 - * @param map the map to clone
  58.215 - * @param fnc the copy function to use or <code>NULL</code> if the new and
  58.216 - * the old map shall share the data pointers
  58.217 - * @param data additional data for the copy function
  58.218 - * @return the cloned map
  58.219 - * @see ucx_map_copy()
  58.220 - */
  58.221 -UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data);
  58.222 -
  58.223 -/**
  58.224 - * Increases size of the hash map, if necessary.
  58.225 - * 
  58.226 - * The load value is 0.75*UcxMap.size. If the element count exceeds the load
  58.227 - * value, the map needs to be rehashed. Otherwise no action is performed and
  58.228 - * this function simply returns 0.
  58.229 - * 
  58.230 - * The rehashing process ensures, that the UcxMap.size is at least
  58.231 - * 2.5*UcxMap.count. So there is enough room for additional elements without
  58.232 - * the need of another soon rehashing.
  58.233 - * 
  58.234 - * You can use this function to dramatically increase access performance.
  58.235 - * 
  58.236 - * @param map the map to rehash
  58.237 - * @return 1, if a memory allocation error occurred, 0 otherwise
  58.238 - */
  58.239 -int ucx_map_rehash(UcxMap *map);
  58.240 -
  58.241 -/**
  58.242 - * Puts a key/value-pair into the map.
  58.243 - * 
  58.244 - * @param map the map
  58.245 - * @param key the key
  58.246 - * @param value the value
  58.247 - * @return 0 on success, non-zero value on failure
  58.248 - */
  58.249 -int ucx_map_put(UcxMap *map, UcxKey key, void *value);
  58.250 -
  58.251 -/**
  58.252 - * Retrieves a value by using a key.
  58.253 - * 
  58.254 - * @param map the map
  58.255 - * @param key the key
  58.256 - * @return the value
  58.257 - */
  58.258 -void* ucx_map_get(UcxMap *map, UcxKey key);
  58.259 -
  58.260 -/**
  58.261 - * Removes a key/value-pair from the map by using the key.
  58.262 - * 
  58.263 - * @param map the map
  58.264 - * @param key the key
  58.265 - * @return the removed value
  58.266 - */
  58.267 -void* ucx_map_remove(UcxMap *map, UcxKey key);
  58.268 -
  58.269 -/**
  58.270 - * Shorthand for putting data with a sstr_t key into the map.
  58.271 - * @param map the map
  58.272 - * @param key the key
  58.273 - * @param value the value
  58.274 - * @return 0 on success, non-zero value on failure
  58.275 - * @see ucx_map_put()
  58.276 - */
  58.277 -#define ucx_map_sstr_put(map, key, value) \
  58.278 -    ucx_map_put(map, ucx_key(key.ptr, key.length), (void*)value)
  58.279 -
  58.280 -/**
  58.281 - * Shorthand for putting data with a C string key into the map.
  58.282 - * @param map the map
  58.283 - * @param key the key
  58.284 - * @param value the value
  58.285 - * @return 0 on success, non-zero value on failure
  58.286 - * @see ucx_map_put()
  58.287 - */
  58.288 -#define ucx_map_cstr_put(map, key, value) \
  58.289 -    ucx_map_put(map, ucx_key((void*)key, strlen(key)), (void*)value)
  58.290 -
  58.291 -/**
  58.292 - * Shorthand for putting data with an integer key into the map.
  58.293 - * @param map the map
  58.294 - * @param key the key
  58.295 - * @param value the value
  58.296 - * @return 0 on success, non-zero value on failure
  58.297 - * @see ucx_map_put()
  58.298 - */
  58.299 -#define ucx_map_int_put(map, key, value) \
  58.300 -    ucx_map_put(map, ucx_key((void*)&key, sizeof(key)), (void*)value)
  58.301 -
  58.302 -/**
  58.303 - * Shorthand for getting data from the map with a sstr_t key.
  58.304 - * @param map the map
  58.305 - * @param key the key
  58.306 - * @return the value
  58.307 - * @see ucx_map_get()
  58.308 - */
  58.309 -#define ucx_map_sstr_get(map, key) \
  58.310 -    ucx_map_get(map, ucx_key(key.ptr, key.length))
  58.311 -
  58.312 -/**
  58.313 - * Shorthand for getting data from the map with a C string key.
  58.314 - * @param map the map
  58.315 - * @param key the key
  58.316 - * @return the value
  58.317 - * @see ucx_map_get()
  58.318 - */
  58.319 -#define ucx_map_cstr_get(map, key) \
  58.320 -    ucx_map_get(map, ucx_key((void*)key, strlen(key)))
  58.321 -
  58.322 -/**
  58.323 - * Shorthand for getting data from the map with an integer key.
  58.324 - * @param map the map
  58.325 - * @param key the key
  58.326 - * @return the value
  58.327 - * @see ucx_map_get()
  58.328 - */
  58.329 -#define ucx_map_int_get(map, key) \
  58.330 -    ucx_map_get(map, ucx_key((void*)&key, sizeof(int)))
  58.331 -
  58.332 -/**
  58.333 - * Shorthand for removing data from the map with a sstr_t key.
  58.334 - * @param map the map
  58.335 - * @param key the key
  58.336 - * @return the removed value
  58.337 - * @see ucx_map_remove()
  58.338 - */
  58.339 -#define ucx_map_sstr_remove(map, key) \
  58.340 -    ucx_map_remove(map, ucx_key(key.ptr, key.length))
  58.341 -
  58.342 -/**
  58.343 - * Shorthand for removing data from the map with a C string key.
  58.344 - * @param map the map
  58.345 - * @param key the key
  58.346 - * @return the removed value
  58.347 - * @see ucx_map_remove()
  58.348 - */
  58.349 -#define ucx_map_cstr_remove(map, key) \
  58.350 -    ucx_map_remove(map, ucx_key((void*)key, strlen(key)))
  58.351 -
  58.352 -/**
  58.353 - * Shorthand for removing data from the map with an integer key.
  58.354 - * @param map the map
  58.355 - * @param key the key
  58.356 - * @return the removed value
  58.357 - * @see ucx_map_remove()
  58.358 - */
  58.359 -#define ucx_map_int_remove(map, key) \
  58.360 -    ucx_map_remove(map, ucx_key((void*)&key, sizeof(key)))
  58.361 -
  58.362 -/**
  58.363 - * Creates a UcxKey based on the given data.
  58.364 - * 
  58.365 - * This function implicitly computes the hash.
  58.366 - * 
  58.367 - * @param data the data for the key
  58.368 - * @param len the length of the data
  58.369 - * @return a UcxKey with implicitly computed hash
  58.370 - * @see ucx_hash()
  58.371 - */
  58.372 -UcxKey ucx_key(void *data, size_t len);
  58.373 -
  58.374 -/**
  58.375 - * Computes a murmur hash-2.
  58.376 - * 
  58.377 - * @param data the data to hash
  58.378 - * @param len the length of the data
  58.379 - * @return the murmur hash-2 of the data
  58.380 - */
  58.381 -int ucx_hash(const char *data, size_t len);
  58.382 -
  58.383 -/**
  58.384 - * Creates an iterator for a map.
  58.385 - * 
  58.386 - * <b>Note:</b> A UcxMapIterator iterates over all elements in all element
  58.387 - * lists successively. Therefore the order highly depends on the key hashes and
  58.388 - * may vary under different map sizes. So generally you may <b>NOT</b> rely on
  58.389 - * the iteration order.
  58.390 - * 
  58.391 - * <b>Note:</b> The iterator is <b>NOT</b> initialized. You need to call
  58.392 - * ucx_map_iter_next() at least once before accessing any information. However,
  58.393 - * it is not recommended to access the fields of a UcxMapIterator directly.
  58.394 - * 
  58.395 - * @param map the map to create the iterator for
  58.396 - * @return an iterator initialized on the first element of the
  58.397 - * first element list
  58.398 - * @see ucx_map_iter_next()
  58.399 - */
  58.400 -UcxMapIterator ucx_map_iterator(UcxMap *map);
  58.401 -
  58.402 -/**
  58.403 - * Proceeds to the next element of the map (if any).
  58.404 - * 
  58.405 - * Subsequent calls on the same iterator proceed to the next element and
  58.406 - * store the key/value-pair into the memory specified as arguments of this
  58.407 - * function.
  58.408 - * 
  58.409 - * If no further elements are found, this function returns zero and leaves the
  58.410 - * last found key/value-pair in memory.
  58.411 - * 
  58.412 - * @param iterator the iterator to use
  58.413 - * @param key a pointer to the memory where to store the key
  58.414 - * @param value a pointer to the memory where to store the value
  58.415 - * @return 1, if another element was found, 0 if all elements has been processed
  58.416 - * @see ucx_map_iterator()
  58.417 - */
  58.418 -int ucx_map_iter_next(UcxMapIterator *iterator, UcxKey *key, void **value);
  58.419 -
  58.420 -
  58.421 -#ifdef	__cplusplus
  58.422 -}
  58.423 -#endif
  58.424 -
  58.425 -#endif	/* UCX_MAP_H */
  58.426 -
    59.1 --- a/ucx/mempool.c	Tue Oct 17 15:15:54 2017 +0200
    59.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.3 @@ -1,211 +0,0 @@
    59.4 -/*
    59.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    59.6 - *
    59.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    59.8 - *
    59.9 - * Redistribution and use in source and binary forms, with or without
   59.10 - * modification, are permitted provided that the following conditions are met:
   59.11 - *
   59.12 - *   1. Redistributions of source code must retain the above copyright
   59.13 - *      notice, this list of conditions and the following disclaimer.
   59.14 - *
   59.15 - *   2. Redistributions in binary form must reproduce the above copyright
   59.16 - *      notice, this list of conditions and the following disclaimer in the
   59.17 - *      documentation and/or other materials provided with the distribution.
   59.18 - *
   59.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   59.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   59.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   59.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   59.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   59.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   59.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   59.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   59.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   59.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   59.29 - * POSSIBILITY OF SUCH DAMAGE.
   59.30 - */
   59.31 -
   59.32 -#include <stdlib.h>
   59.33 -#include <string.h>
   59.34 -#include <stdio.h>
   59.35 -#ifdef __cplusplus
   59.36 -#define __STDC_FORMAT_MACROS
   59.37 -#endif
   59.38 -#include <inttypes.h>
   59.39 -
   59.40 -#include "mempool.h"
   59.41 -
   59.42 -/** Capsule for destructible memory chunks. */
   59.43 -typedef struct {
   59.44 -    /** The destructor for the memory chunk. */
   59.45 -    ucx_destructor destructor;
   59.46 -    /**
   59.47 -     * First byte of the memory chunk.
   59.48 -     * Note, that the address <code>&amp;c</code> is also the address
   59.49 -     * of the whole memory chunk.
   59.50 -     */
   59.51 -    char c;
   59.52 -} ucx_memchunk;
   59.53 -
   59.54 -/** Capsule for data and its destructor. */
   59.55 -typedef struct {
   59.56 -    /** The destructor for the data. */
   59.57 -    ucx_destructor destructor;
   59.58 -    /** A pointer to the data. */
   59.59 -    void           *ptr;
   59.60 -} ucx_regdestr;
   59.61 -
   59.62 -UCX_EXTERN void ucx_mempool_shared_destr(void* ptr) {
   59.63 -    ucx_regdestr *rd = (ucx_regdestr*)ptr;
   59.64 -    rd->destructor(rd->ptr);
   59.65 -}
   59.66 -
   59.67 -UcxMempool *ucx_mempool_new(size_t n) {
   59.68 -    UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool));
   59.69 -    if (!pool) {
   59.70 -        return NULL;
   59.71 -    }
   59.72 -    
   59.73 -    pool->data = (void**) malloc(n * sizeof(void*));
   59.74 -    if (pool->data == NULL) {
   59.75 -        free(pool);
   59.76 -        return NULL;
   59.77 -    }
   59.78 -    
   59.79 -    pool->ndata = 0;
   59.80 -    pool->size = n;
   59.81 -    
   59.82 -    UcxAllocator *allocator = (UcxAllocator*)malloc(sizeof(UcxAllocator));
   59.83 -    if(!allocator) {
   59.84 -        free(pool->data);
   59.85 -        free(pool);
   59.86 -        return NULL;
   59.87 -    }
   59.88 -    allocator->malloc = (ucx_allocator_malloc)ucx_mempool_malloc;
   59.89 -    allocator->calloc = (ucx_allocator_calloc)ucx_mempool_calloc;
   59.90 -    allocator->realloc = (ucx_allocator_realloc)ucx_mempool_realloc;
   59.91 -    allocator->free = (ucx_allocator_free)ucx_mempool_free;
   59.92 -    allocator->pool = pool;
   59.93 -    pool->allocator = allocator;
   59.94 -    
   59.95 -    return pool;
   59.96 -}
   59.97 -
   59.98 -int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) {
   59.99 -    if (newcap < pool->ndata) {
  59.100 -        return 1;
  59.101 -    }
  59.102 -    
  59.103 -    void **data = (void**) realloc(pool->data, newcap*sizeof(void*));
  59.104 -    if (data) {
  59.105 -        pool->data = data; 
  59.106 -        pool->size = newcap;
  59.107 -        return 0;
  59.108 -    } else {
  59.109 -        return 1;
  59.110 -    }
  59.111 -}
  59.112 -
  59.113 -void *ucx_mempool_malloc(UcxMempool *pool, size_t n) {
  59.114 -    if (pool->ndata >= pool->size) {
  59.115 -        size_t newcap = pool->size*2;
  59.116 -        if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) {
  59.117 -            return NULL;
  59.118 -        }
  59.119 -    }
  59.120 -
  59.121 -    void *p = malloc(sizeof(ucx_destructor) + n);
  59.122 -    ucx_memchunk *mem = (ucx_memchunk*)p;
  59.123 -    if (!mem) {
  59.124 -        return NULL;
  59.125 -    }
  59.126 -
  59.127 -    mem->destructor = NULL;
  59.128 -    pool->data[pool->ndata] = mem;
  59.129 -    pool->ndata++;
  59.130 -
  59.131 -    return &(mem->c);
  59.132 -}
  59.133 -
  59.134 -void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) {
  59.135 -    void *ptr = ucx_mempool_malloc(pool, nelem*elsize);
  59.136 -    if (!ptr) {
  59.137 -        return NULL;
  59.138 -    }
  59.139 -    memset(ptr, 0, nelem * elsize);
  59.140 -    return ptr;
  59.141 -}
  59.142 -
  59.143 -void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) {
  59.144 -    char *mem = ((char*)ptr) - sizeof(ucx_destructor);
  59.145 -    char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor));
  59.146 -    if (!newm) {
  59.147 -        return NULL;
  59.148 -    }
  59.149 -    if (mem != newm) {
  59.150 -        for(size_t i=0 ; i < pool->ndata ; i++) {
  59.151 -            if(pool->data[i] == mem) {
  59.152 -                pool->data[i] = newm;
  59.153 -                return newm + sizeof(ucx_destructor);
  59.154 -            }
  59.155 -        }
  59.156 -        fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
  59.157 -          (intptr_t)ptr, (intptr_t)pool);
  59.158 -        abort();
  59.159 -    } else {
  59.160 -        return newm + sizeof(ucx_destructor);
  59.161 -    }
  59.162 -}
  59.163 -
  59.164 -void ucx_mempool_free(UcxMempool *pool, void *ptr) {
  59.165 -    ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor));
  59.166 -    for(size_t i=0 ; i<pool->ndata ; i++) {
  59.167 -        if(chunk == pool->data[i]) {
  59.168 -            if(chunk->destructor != NULL) {
  59.169 -                chunk->destructor(&(chunk->c));
  59.170 -            }
  59.171 -            free(chunk);
  59.172 -            size_t last_index = pool->ndata - 1;
  59.173 -            if(i != last_index) {
  59.174 -                pool->data[i] = pool->data[last_index];
  59.175 -                pool->data[last_index] = NULL;
  59.176 -            }
  59.177 -            pool->ndata--;
  59.178 -            return;
  59.179 -        }
  59.180 -    }
  59.181 -    fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
  59.182 -            (intptr_t)ptr, (intptr_t)pool);
  59.183 -    abort();
  59.184 -}
  59.185 -
  59.186 -void ucx_mempool_destroy(UcxMempool *pool) {
  59.187 -    ucx_memchunk *chunk;
  59.188 -    for(size_t i=0 ; i<pool->ndata ; i++) {
  59.189 -        chunk = (ucx_memchunk*) pool->data[i];
  59.190 -        if(chunk) {
  59.191 -            if(chunk->destructor) {
  59.192 -                chunk->destructor(&(chunk->c));
  59.193 -            }
  59.194 -            free(chunk);
  59.195 -        }
  59.196 -    }
  59.197 -    free(pool->data);
  59.198 -    free(pool->allocator);
  59.199 -    free(pool);
  59.200 -}
  59.201 -
  59.202 -void ucx_mempool_set_destr(void *ptr, ucx_destructor func) {
  59.203 -    *(ucx_destructor*)((char*)ptr-sizeof(ucx_destructor)) = func;
  59.204 -}
  59.205 -
  59.206 -void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr) {
  59.207 -    ucx_regdestr *rd = (ucx_regdestr*)ucx_mempool_malloc(
  59.208 -            pool,
  59.209 -            sizeof(ucx_regdestr));
  59.210 -    rd->destructor = destr;
  59.211 -    rd->ptr = ptr;
  59.212 -    ucx_mempool_set_destr(rd, ucx_mempool_shared_destr);
  59.213 -}
  59.214 -
    60.1 --- a/ucx/mempool.h	Tue Oct 17 15:15:54 2017 +0200
    60.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.3 @@ -1,200 +0,0 @@
    60.4 -/*
    60.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    60.6 - *
    60.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    60.8 - *
    60.9 - * Redistribution and use in source and binary forms, with or without
   60.10 - * modification, are permitted provided that the following conditions are met:
   60.11 - *
   60.12 - *   1. Redistributions of source code must retain the above copyright
   60.13 - *      notice, this list of conditions and the following disclaimer.
   60.14 - *
   60.15 - *   2. Redistributions in binary form must reproduce the above copyright
   60.16 - *      notice, this list of conditions and the following disclaimer in the
   60.17 - *      documentation and/or other materials provided with the distribution.
   60.18 - *
   60.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   60.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   60.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   60.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   60.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   60.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   60.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   60.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   60.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   60.29 - * POSSIBILITY OF SUCH DAMAGE.
   60.30 - */
   60.31 -
   60.32 -/**
   60.33 - * @file mempool.h
   60.34 - * 
   60.35 - * Memory pool implementation.
   60.36 - * 
   60.37 - * @author Mike Becker
   60.38 - * @author Olaf Wintermann
   60.39 - */
   60.40 -
   60.41 -#ifndef UCX_MEMPOOL_H
   60.42 -#define	UCX_MEMPOOL_H
   60.43 -
   60.44 -#include "ucx.h"
   60.45 -#include <stddef.h>
   60.46 -#include "allocator.h"
   60.47 -
   60.48 -#ifdef	__cplusplus
   60.49 -extern "C" {
   60.50 -#endif
   60.51 -
   60.52 -/**
   60.53 - * UCX mempool structure.
   60.54 - */
   60.55 -typedef struct {
   60.56 -    /** UcxAllocator based on this pool */
   60.57 -    UcxAllocator *allocator;
   60.58 -    
   60.59 -    /** List of pointers to pooled memory. */
   60.60 -    void         **data;
   60.61 -    
   60.62 -    /** Count of pooled memory items. */
   60.63 -    size_t       ndata;
   60.64 -    
   60.65 -    /** Memory pool size. */
   60.66 -    size_t       size;
   60.67 -} UcxMempool;
   60.68 -
   60.69 -/** Shorthand for a new default memory pool with a capacity of 16 elements. */
   60.70 -#define ucx_mempool_new_default() ucx_mempool_new(16)
   60.71 -
   60.72 -
   60.73 -/**
   60.74 - * Creates a memory pool with the specified initial size.
   60.75 - * 
   60.76 - * As the created memory pool automatically grows in size by factor two when
   60.77 - * trying to allocate memory on a full pool, it is recommended that you use
   60.78 - * a power of two for the initial size.
   60.79 - * 
   60.80 - * @param n initial pool size (should be a power of two, e.g. 16)
   60.81 - * @return a pointer to the new memory pool
   60.82 - * @see ucx_mempool_new_default()
   60.83 - */
   60.84 -UcxMempool *ucx_mempool_new(size_t n);
   60.85 -
   60.86 -/**
   60.87 - * Resizes a memory pool.
   60.88 - * 
   60.89 - * This function will fail if the new capacity is not sufficient for the
   60.90 - * present data.
   60.91 - * 
   60.92 - * @param pool the pool to resize
   60.93 - * @param newcap the new capacity
   60.94 - * @return zero on success or non-zero on failure
   60.95 - */
   60.96 -int ucx_mempool_chcap(UcxMempool *pool, size_t newcap);
   60.97 -
   60.98 -/**
   60.99 - * Allocates pooled memory.
  60.100 - * 
  60.101 - * @param pool the memory pool
  60.102 - * @param n amount of memory to allocate
  60.103 - * @return a pointer to the allocated memory
  60.104 - * @see ucx_allocator_malloc()
  60.105 - */
  60.106 -void *ucx_mempool_malloc(UcxMempool *pool, size_t n);
  60.107 -/**
  60.108 - * Allocates a pooled memory array.
  60.109 - * 
  60.110 - * The content of the allocated memory is set to zero.
  60.111 - * 
  60.112 - * @param pool the memory pool
  60.113 - * @param nelem amount of elements to allocate
  60.114 - * @param elsize amount of memory per element
  60.115 - * @return a pointer to the allocated memory
  60.116 - * @see ucx_allocator_calloc()
  60.117 - */
  60.118 -void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize);
  60.119 -
  60.120 -/**
  60.121 - * Reallocates pooled memory.
  60.122 - * 
  60.123 - * If the memory to be reallocated is not contained by the specified pool, the
  60.124 - * behavior is undefined.
  60.125 - * 
  60.126 - * @param pool the memory pool
  60.127 - * @param ptr a pointer to the memory that shall be reallocated
  60.128 - * @param n the new size of the memory
  60.129 - * @return a pointer to the new location of the memory
  60.130 - * @see ucx_allocator_realloc()
  60.131 - */
  60.132 -void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n);
  60.133 -
  60.134 -/**
  60.135 - * Frees pooled memory.
  60.136 - * 
  60.137 - * Before freeing the memory, the specified destructor function (if any)
  60.138 - * is called.
  60.139 - * 
  60.140 - * If you specify memory, that is not pooled by the specified memory pool, the
  60.141 - * program will terminate with a call to <code>abort()</code>.
  60.142 - * 
  60.143 - * @param pool the memory pool
  60.144 - * @param ptr a pointer to the memory that shall be freed
  60.145 - * @see ucx_mempool_set_destr()
  60.146 - */
  60.147 -void ucx_mempool_free(UcxMempool *pool, void *ptr);
  60.148 -
  60.149 -/**
  60.150 - * Destroys a memory pool.
  60.151 - * 
  60.152 - * For each element the destructor function (if any) is called and the element
  60.153 - * is freed.
  60.154 - * 
  60.155 - * Each of the registered destructor function that has no corresponding element
  60.156 - * within the pool (namely those registered by ucx_mempool_reg_destr) is
  60.157 - * called interleaving with the element destruction, but with guarantee to the
  60.158 - * order in which they were registered (FIFO order).
  60.159 - * 
  60.160 - * 
  60.161 - * @param pool the mempool to destroy
  60.162 - */
  60.163 -void ucx_mempool_destroy(UcxMempool *pool);
  60.164 -
  60.165 -/**
  60.166 - * Sets a destructor function for the specified memory.
  60.167 - * 
  60.168 - * The destructor is automatically called when the memory is freed or the
  60.169 - * pool is destroyed.
  60.170 - * 
  60.171 - * The only requirement for the specified memory is, that it <b>MUST</b> be
  60.172 - * pooled memory by a UcxMempool or an element-compatible mempool. The pointer
  60.173 - * to the destructor function is saved in a reserved area before the actual
  60.174 - * memory.
  60.175 - * 
  60.176 - * @param ptr pooled memory
  60.177 - * @param func a pointer to the destructor function
  60.178 - * @see ucx_mempool_free()
  60.179 - * @see ucx_mempool_destroy()
  60.180 - */
  60.181 -void ucx_mempool_set_destr(void *ptr, ucx_destructor func);
  60.182 -
  60.183 -/**
  60.184 - * Registers a destructor function for the specified (non-pooled) memory.
  60.185 - * 
  60.186 - * This is useful, if you have memory that has not been allocated by a mempool,
  60.187 - * but shall be managed by a mempool.
  60.188 - * 
  60.189 - * This function creates an entry in the specified mempool and the memory will
  60.190 - * therefore (logically) convert to pooled memory.
  60.191 - * 
  60.192 - * @param pool the memory pool
  60.193 - * @param ptr data the destructor is registered for
  60.194 - * @param destr a pointer to the destructor function
  60.195 - */
  60.196 -void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr);
  60.197 -
  60.198 -#ifdef	__cplusplus
  60.199 -}
  60.200 -#endif
  60.201 -
  60.202 -#endif	/* UCX_MEMPOOL_H */
  60.203 -
    61.1 --- a/ucx/properties.c	Tue Oct 17 15:15:54 2017 +0200
    61.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.3 @@ -1,264 +0,0 @@
    61.4 -/*
    61.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    61.6 - *
    61.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    61.8 - *
    61.9 - * Redistribution and use in source and binary forms, with or without
   61.10 - * modification, are permitted provided that the following conditions are met:
   61.11 - *
   61.12 - *   1. Redistributions of source code must retain the above copyright
   61.13 - *      notice, this list of conditions and the following disclaimer.
   61.14 - *
   61.15 - *   2. Redistributions in binary form must reproduce the above copyright
   61.16 - *      notice, this list of conditions and the following disclaimer in the
   61.17 - *      documentation and/or other materials provided with the distribution.
   61.18 - *
   61.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   61.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   61.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   61.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   61.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   61.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   61.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   61.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   61.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   61.29 - * POSSIBILITY OF SUCH DAMAGE.
   61.30 - */
   61.31 -
   61.32 -#include <stdio.h>
   61.33 -#include <stdlib.h>
   61.34 -#include <string.h>
   61.35 -
   61.36 -#include "properties.h"
   61.37 -
   61.38 -UcxProperties *ucx_properties_new() {
   61.39 -    UcxProperties *parser = (UcxProperties*)malloc(
   61.40 -            sizeof(UcxProperties));
   61.41 -    if(!parser) {
   61.42 -        return NULL;
   61.43 -    }
   61.44 -    
   61.45 -    parser->buffer = NULL;
   61.46 -    parser->buflen = 0;
   61.47 -    parser->pos = 0;
   61.48 -    parser->tmp = NULL;
   61.49 -    parser->tmplen = 0;
   61.50 -    parser->tmpcap = 0;
   61.51 -    parser->error = 0;
   61.52 -    parser->delimiter = '=';
   61.53 -    parser->comment1 = '#';
   61.54 -    parser->comment2 = 0;
   61.55 -    parser->comment3 = 0;   
   61.56 -    
   61.57 -    return parser;
   61.58 -}
   61.59 -
   61.60 -void ucx_properties_free(UcxProperties *parser) {
   61.61 -    if(parser->tmp) {
   61.62 -        free(parser->tmp);
   61.63 -    }
   61.64 -    free(parser);
   61.65 -}
   61.66 -
   61.67 -void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len) {
   61.68 -    parser->buffer = buf;
   61.69 -    parser->buflen = len;
   61.70 -    parser->pos = 0;
   61.71 -}
   61.72 -
   61.73 -static void parser_tmp_append(UcxProperties *parser, char *buf, size_t len) {
   61.74 -    if(parser->tmpcap - parser->tmplen < len) {
   61.75 -        size_t newcap = parser->tmpcap + len + 64;
   61.76 -        parser->tmp = (char*)realloc(parser->tmp, newcap);
   61.77 -        parser->tmpcap = newcap;
   61.78 -    }
   61.79 -    memcpy(parser->tmp + parser->tmplen, buf, len);
   61.80 -    parser->tmplen += len;
   61.81 -}
   61.82 -
   61.83 -int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value)  {   
   61.84 -    if(parser->tmplen > 0) {
   61.85 -        char *buf = parser->buffer + parser->pos;
   61.86 -        size_t len = parser->buflen - parser->pos;
   61.87 -        sstr_t str = sstrn(buf, len);
   61.88 -        sstr_t nl = sstrchr(str, '\n');
   61.89 -        if(nl.ptr) {
   61.90 -            size_t newlen = (size_t)(nl.ptr - buf) + 1;
   61.91 -            parser_tmp_append(parser, buf, newlen);
   61.92 -            // the tmp buffer contains exactly one line now
   61.93 -            
   61.94 -            char *orig_buf = parser->buffer;
   61.95 -            size_t orig_len = parser->buflen;
   61.96 -            
   61.97 -            parser->buffer = parser->tmp;
   61.98 -            parser->buflen = parser->tmplen;
   61.99 -            parser->pos = 0;    
  61.100 -            parser->tmp = NULL;
  61.101 -            parser->tmpcap = 0;
  61.102 -            parser->tmplen = 0;
  61.103 -            // run ucx_properties_next with the tmp buffer as main buffer
  61.104 -            int ret = ucx_properties_next(parser, name, value);
  61.105 -            
  61.106 -            // restore original buffer
  61.107 -            parser->tmp = parser->buffer;
  61.108 -            parser->buffer = orig_buf;
  61.109 -            parser->buflen = orig_len;
  61.110 -            parser->pos = newlen;
  61.111 -            
  61.112 -            /*
  61.113 -             * if ret == 0 the tmp buffer contained just space or a comment
  61.114 -             * we parse again with the original buffer to get a name/value
  61.115 -             * or a new tmp buffer
  61.116 -             */
  61.117 -            return ret ? ret : ucx_properties_next(parser, name, value);
  61.118 -        } else {
  61.119 -            parser_tmp_append(parser, buf, len);
  61.120 -            return 0;
  61.121 -        }
  61.122 -    } else if(parser->tmp) {
  61.123 -        free(parser->tmp);
  61.124 -        parser->tmp = NULL;
  61.125 -    }
  61.126 -    
  61.127 -    char comment1 = parser->comment1;
  61.128 -    char comment2 = parser->comment2;
  61.129 -    char comment3 = parser->comment3;
  61.130 -    char delimiter = parser->delimiter;
  61.131 -    
  61.132 -    // get one line and parse it
  61.133 -    while(parser->pos < parser->buflen) {
  61.134 -        char *buf = parser->buffer + parser->pos;
  61.135 -        size_t len = parser->buflen - parser->pos;
  61.136 -        
  61.137 -        /*
  61.138 -         * First we check if we have at least one line. We also get indices of
  61.139 -         * delimiter and comment chars
  61.140 -         */
  61.141 -        size_t delimiter_index = 0;
  61.142 -        size_t comment_index = 0;
  61.143 -        int has_comment = 0;
  61.144 -
  61.145 -        size_t i = 0;
  61.146 -        char c = 0;
  61.147 -        for(;i<len;i++) {
  61.148 -            c = buf[i];
  61.149 -            if(c == comment1 || c == comment2 || c == comment3) {
  61.150 -                if(comment_index == 0) {
  61.151 -                    comment_index = i;
  61.152 -                    has_comment = 1;
  61.153 -                }
  61.154 -            } else if(c == delimiter) {
  61.155 -                if(delimiter_index == 0 && !has_comment) {
  61.156 -                    delimiter_index = i;
  61.157 -                }
  61.158 -            } else if(c == '\n') {
  61.159 -                break;
  61.160 -            }
  61.161 -        }
  61.162 -
  61.163 -        if(c != '\n') {
  61.164 -            // we don't have enough data for a line
  61.165 -            // store remaining bytes in temporary buffer for next round
  61.166 -            parser->tmpcap = len + 128;
  61.167 -            parser->tmp = (char*)malloc(parser->tmpcap);
  61.168 -            parser->tmplen = len;
  61.169 -            memcpy(parser->tmp, buf, len);
  61.170 -            return 0;
  61.171 -        }
  61.172 -        
  61.173 -        sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i);
  61.174 -        // check line
  61.175 -        if(delimiter_index == 0) {
  61.176 -            line = sstrtrim(line);
  61.177 -            if(line.length != 0) {
  61.178 -                parser->error = 1;
  61.179 -            }
  61.180 -        } else {
  61.181 -            sstr_t n = sstrn(buf, delimiter_index);
  61.182 -            sstr_t v = sstrn(
  61.183 -                    buf + delimiter_index + 1,
  61.184 -                    line.length - delimiter_index - 1); 
  61.185 -            n = sstrtrim(n);
  61.186 -            v = sstrtrim(v);
  61.187 -            if(n.length != 0 || v.length != 0) {
  61.188 -                *name = n;
  61.189 -                *value = v;
  61.190 -                parser->pos += i + 1;
  61.191 -                return 1;
  61.192 -            } else {
  61.193 -                parser->error = 1;
  61.194 -            }
  61.195 -        }
  61.196 -        
  61.197 -        parser->pos += i + 1;
  61.198 -    }
  61.199 -    
  61.200 -    return 0;
  61.201 -}
  61.202 -
  61.203 -int ucx_properties2map(UcxProperties *parser, UcxMap *map) {
  61.204 -    sstr_t name;
  61.205 -    sstr_t value;
  61.206 -    while(ucx_properties_next(parser, &name, &value)) {
  61.207 -        value = sstrdup_a(map->allocator, value);
  61.208 -        if(!value.ptr) {
  61.209 -            return 1;
  61.210 -        }
  61.211 -        if(ucx_map_sstr_put(map, name, value.ptr)) {
  61.212 -            alfree(map->allocator, value.ptr);
  61.213 -            return 1;
  61.214 -        }
  61.215 -    }
  61.216 -    if (parser->error) {
  61.217 -        return parser->error;
  61.218 -    } else {
  61.219 -        return 0;
  61.220 -    }
  61.221 -}
  61.222 -
  61.223 -// buffer size is documented - change doc, when you change bufsize!
  61.224 -#define UCX_PROPLOAD_BUFSIZE  1024
  61.225 -int ucx_properties_load(UcxMap *map, FILE *file) {
  61.226 -    UcxProperties *parser = ucx_properties_new();
  61.227 -    if(!(parser && map && file)) {
  61.228 -        return 1;
  61.229 -    }
  61.230 -    
  61.231 -    int error = 0;
  61.232 -    size_t r;
  61.233 -    char buf[UCX_PROPLOAD_BUFSIZE];
  61.234 -    while((r = fread(buf, 1, UCX_PROPLOAD_BUFSIZE, file)) != 0) {
  61.235 -        ucx_properties_fill(parser, buf, r);
  61.236 -        error = ucx_properties2map(parser, map);
  61.237 -        if (error) {
  61.238 -            break;
  61.239 -        }
  61.240 -    }
  61.241 -    ucx_properties_free(parser);
  61.242 -    return error;
  61.243 -}
  61.244 -
  61.245 -int ucx_properties_store(UcxMap *map, FILE *file) {
  61.246 -    UcxMapIterator iter = ucx_map_iterator(map);
  61.247 -    void *v;
  61.248 -    sstr_t value;
  61.249 -    size_t written;
  61.250 -
  61.251 -    UCX_MAP_FOREACH(k, v, iter) {
  61.252 -        value = sstr((char*)v);
  61.253 -
  61.254 -        written = 0;
  61.255 -        written += fwrite(k.data, 1, k.len, file);
  61.256 -        written += fwrite(" = ", 1, 3, file);
  61.257 -        written += fwrite(value.ptr, 1, value.length, file);
  61.258 -        written += fwrite("\n", 1, 1, file);
  61.259 -
  61.260 -        if (written != k.len + value.length + 4) {
  61.261 -            return 1;
  61.262 -        }
  61.263 -    }
  61.264 -
  61.265 -    return 0;
  61.266 -}
  61.267 -
    62.1 --- a/ucx/properties.h	Tue Oct 17 15:15:54 2017 +0200
    62.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.3 @@ -1,218 +0,0 @@
    62.4 -/*
    62.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    62.6 - *
    62.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    62.8 - *
    62.9 - * Redistribution and use in source and binary forms, with or without
   62.10 - * modification, are permitted provided that the following conditions are met:
   62.11 - *
   62.12 - *   1. Redistributions of source code must retain the above copyright
   62.13 - *      notice, this list of conditions and the following disclaimer.
   62.14 - *
   62.15 - *   2. Redistributions in binary form must reproduce the above copyright
   62.16 - *      notice, this list of conditions and the following disclaimer in the
   62.17 - *      documentation and/or other materials provided with the distribution.
   62.18 - *
   62.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   62.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   62.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   62.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   62.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   62.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   62.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   62.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   62.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   62.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   62.29 - * POSSIBILITY OF SUCH DAMAGE.
   62.30 - */
   62.31 -/**
   62.32 - * @file properties.h
   62.33 - * 
   62.34 - * Load / store utilities for properties files.
   62.35 - * 
   62.36 - * @author Mike Becker
   62.37 - * @author Olaf Wintermann
   62.38 - */
   62.39 -
   62.40 -#ifndef UCX_PROPERTIES_H
   62.41 -#define	UCX_PROPERTIES_H
   62.42 -
   62.43 -#include "ucx.h"
   62.44 -#include "map.h"
   62.45 -
   62.46 -#ifdef	__cplusplus
   62.47 -extern "C" {
   62.48 -#endif
   62.49 -
   62.50 -/**
   62.51 - * UcxProperties object for parsing properties data.
   62.52 - * Most of the fields are for internal use only. You may configure the
   62.53 - * properties parser, e.g. by changing the used delimiter or specifying 
   62.54 - * up to three different characters that shall introduce comments.
   62.55 - */
   62.56 -typedef struct {
   62.57 -    /**
   62.58 -     * Input buffer (don't set manually).
   62.59 -     * Automatically set by calls to ucx_properties_fill().
   62.60 -     */
   62.61 -    char   *buffer;
   62.62 -    
   62.63 -    /**
   62.64 -     * Length of the input buffer (don't set manually).
   62.65 -     * Automatically set by calls to ucx_properties_fill().
   62.66 -     */
   62.67 -    size_t buflen;
   62.68 -    
   62.69 -    /**
   62.70 -     * Current buffer position (don't set manually).
   62.71 -     * Used by ucx_properties_next().
   62.72 -     */
   62.73 -    size_t pos;
   62.74 -    
   62.75 -    /**
   62.76 -     * Internal temporary buffer (don't set manually).
   62.77 -     * Used by ucx_properties_next().
   62.78 -     */
   62.79 -    char   *tmp;
   62.80 -    
   62.81 -    /**
   62.82 -     * Internal temporary buffer length (don't set manually).
   62.83 -     * Used by ucx_properties_next().
   62.84 -     */
   62.85 -    size_t tmplen;
   62.86 -    
   62.87 -    /**
   62.88 -     * Internal temporary buffer capacity (don't set manually).
   62.89 -     * Used by ucx_properties_next().
   62.90 -     */
   62.91 -    size_t tmpcap;
   62.92 -    
   62.93 -    /**
   62.94 -     * Parser error code.
   62.95 -     * This is always 0 on success and a nonzero value on syntax errors.
   62.96 -     * The value is set by ucx_properties_next().
   62.97 -     */
   62.98 -    int    error;
   62.99 -    
  62.100 -    /**
  62.101 -     * The delimiter that shall be used.
  62.102 -     * This is '=' by default.
  62.103 -     */
  62.104 -    char   delimiter;
  62.105 -    
  62.106 -    /**
  62.107 -     * The first comment character.
  62.108 -     * This is '#' by default.
  62.109 -     */
  62.110 -    char   comment1;
  62.111 -    
  62.112 -    /**
  62.113 -     * The second comment character.
  62.114 -     * This is not set by default.
  62.115 -     */
  62.116 -    char   comment2;
  62.117 -    
  62.118 -    /**
  62.119 -     * The third comment character.
  62.120 -     * This is not set by default.
  62.121 -     */
  62.122 -    char   comment3;
  62.123 -} UcxProperties;
  62.124 -
  62.125 -
  62.126 -/**
  62.127 - * Constructs a new UcxProperties object.
  62.128 - * @return a pointer to the new UcxProperties object
  62.129 - */
  62.130 -UcxProperties *ucx_properties_new();
  62.131 -
  62.132 -/**
  62.133 - * Destroys a UcxProperties object.
  62.134 - * @param prop the UcxProperties object to destroy
  62.135 - */
  62.136 -void ucx_properties_free(UcxProperties *prop);
  62.137 -
  62.138 -/**
  62.139 - * Sets the input buffer for the properties parser.
  62.140 - * 
  62.141 - * After calling this function, you may parse the data by calling
  62.142 - * ucx_properties_next() until it returns 0. The function ucx_properties2map()
  62.143 - * is a convenience function that reads as much data as possible by using this
  62.144 - * function.
  62.145 - * 
  62.146 - * 
  62.147 - * @param prop the UcxProperties object
  62.148 - * @param buf a pointer to the new buffer
  62.149 - * @param len the payload length of the buffer
  62.150 - * @see ucx_properties_next()
  62.151 - * @see ucx_properties2map()
  62.152 - */
  62.153 -void ucx_properties_fill(UcxProperties *prop, char *buf, size_t len);
  62.154 -
  62.155 -/**
  62.156 - * Retrieves the next key/value-pair.
  62.157 - * 
  62.158 - * This function returns a nonzero value as long as there are key/value-pairs
  62.159 - * found. If no more key/value-pairs are found, you may refill the input buffer
  62.160 - * with ucx_properties_fill().
  62.161 - * 
  62.162 - * <b>Attention:</b> the sstr_t.ptr pointers of the output parameters point to
  62.163 - * memory within the input buffer of the parser and will get invalid some time.
  62.164 - * If you want long term copies of the key/value-pairs, use sstrdup() after
  62.165 - * calling this function.
  62.166 - * 
  62.167 - * @param prop the UcxProperties object
  62.168 - * @param name a pointer to the sstr_t that shall contain the property name
  62.169 - * @param value a pointer to the sstr_t that shall contain the property value
  62.170 - * @return Nonzero, if a key/value-pair was successfully retrieved
  62.171 - * @see ucx_properties_fill()
  62.172 - */
  62.173 -int ucx_properties_next(UcxProperties *prop, sstr_t *name, sstr_t *value);
  62.174 -
  62.175 -/**
  62.176 - * Retrieves all available key/value-pairs and puts them into a UcxMap.
  62.177 - * 
  62.178 - * This is done by successive calls to ucx_properties_next() until no more
  62.179 - * key/value-pairs can be retrieved. 
  62.180 - * 
  62.181 - * @param prop the UcxProperties object
  62.182 - * @param map the target map
  62.183 - * @return The UcxProperties.error code (i.e. 0 on success).
  62.184 - * @see ucx_properties_fill()
  62.185 - */
  62.186 -int ucx_properties2map(UcxProperties *prop, UcxMap *map);
  62.187 -
  62.188 -/**
  62.189 - * Loads a properties file to a UcxMap.
  62.190 - * 
  62.191 - * This is a convenience function that reads data from an input
  62.192 - * stream until the end of the stream is reached.
  62.193 - * 
  62.194 - * @param map the map object to write the key/value-pairs to
  62.195 - * @param file the <code>FILE*</code> stream to read from
  62.196 - * @return 0 on success, or a non-zero value on error
  62.197 - * 
  62.198 - * @see ucx_properties_fill()
  62.199 - * @see ucx_properties2map()
  62.200 - */
  62.201 -int ucx_properties_load(UcxMap *map, FILE *file);
  62.202 -
  62.203 -/**
  62.204 - * Stores a UcxMap to a file.
  62.205 - * 
  62.206 - * The key/value-pairs are written by using the following format:
  62.207 - * 
  62.208 - * <code>[key] = [value]\\n</code>
  62.209 - * 
  62.210 - * @param map the map to store
  62.211 - * @param file the <code>FILE*</code> stream to write to
  62.212 - * @return 0 on success, or a non-zero value on error
  62.213 - */
  62.214 -int ucx_properties_store(UcxMap *map, FILE *file);
  62.215 -
  62.216 -#ifdef	__cplusplus
  62.217 -}
  62.218 -#endif
  62.219 -
  62.220 -#endif	/* UCX_PROPERTIES_H */
  62.221 -
    63.1 --- a/ucx/stack.c	Tue Oct 17 15:15:54 2017 +0200
    63.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.3 @@ -1,143 +0,0 @@
    63.4 -/*
    63.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    63.6 - *
    63.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    63.8 - *
    63.9 - * Redistribution and use in source and binary forms, with or without
   63.10 - * modification, are permitted provided that the following conditions are met:
   63.11 - *
   63.12 - *   1. Redistributions of source code must retain the above copyright
   63.13 - *      notice, this list of conditions and the following disclaimer.
   63.14 - *
   63.15 - *   2. Redistributions in binary form must reproduce the above copyright
   63.16 - *      notice, this list of conditions and the following disclaimer in the
   63.17 - *      documentation and/or other materials provided with the distribution.
   63.18 - *
   63.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   63.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   63.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   63.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   63.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   63.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   63.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   63.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   63.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   63.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   63.29 - * POSSIBILITY OF SUCH DAMAGE.
   63.30 - */
   63.31 -
   63.32 -#include "stack.h"
   63.33 -#include <string.h>
   63.34 -
   63.35 -static size_t ucx_stack_align(size_t n) {
   63.36 -    int align = n % sizeof(void*);
   63.37 -    if (align) {
   63.38 -        n += sizeof(void*) - align;
   63.39 -    }
   63.40 -    return n;
   63.41 -}
   63.42 -
   63.43 -void ucx_stack_init(UcxStack *stack, char* space, size_t size) {
   63.44 -    stack->size = size - size % sizeof(void*);
   63.45 -    stack->space = space;
   63.46 -    stack->top = NULL;
   63.47 -    
   63.48 -    stack->allocator.pool = stack;
   63.49 -    stack->allocator.malloc = (ucx_allocator_malloc) ucx_stack_malloc;
   63.50 -    stack->allocator.calloc = (ucx_allocator_calloc) ucx_stack_calloc;
   63.51 -    stack->allocator.realloc = (ucx_allocator_realloc) ucx_stack_realloc;
   63.52 -    stack->allocator.free = (ucx_allocator_free) ucx_stack_free;
   63.53 -}
   63.54 -
   63.55 -void *ucx_stack_malloc(UcxStack *stack, size_t n) {
   63.56 -
   63.57 -    if (ucx_stack_avail(stack) < ucx_stack_align(n)) {
   63.58 -        return NULL;
   63.59 -    } else {
   63.60 -        char *prev = stack->top;
   63.61 -        if (stack->top) {
   63.62 -            stack->top += ucx_stack_align(ucx_stack_topsize(stack));
   63.63 -        } else {
   63.64 -            stack->top = stack->space;
   63.65 -        }
   63.66 -        
   63.67 -        ((struct ucx_stack_metadata*)stack->top)->prev = prev;
   63.68 -        ((struct ucx_stack_metadata*)stack->top)->size = n;
   63.69 -        stack->top += sizeof(struct ucx_stack_metadata);
   63.70 -        
   63.71 -        return stack->top;
   63.72 -    }
   63.73 -}
   63.74 -
   63.75 -void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize) {
   63.76 -    void *mem = ucx_stack_malloc(stack, nelem*elsize);
   63.77 -    memset(mem, 0, nelem*elsize);
   63.78 -    return mem;
   63.79 -}
   63.80 -
   63.81 -void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) {
   63.82 -    if (ptr == stack->top) {
   63.83 -        if (stack->size - (stack->top - stack->space) < ucx_stack_align(n)) {
   63.84 -            return NULL;
   63.85 -        } else {
   63.86 -            ((struct ucx_stack_metadata*)stack->top - 1)->size = n;
   63.87 -            return ptr;
   63.88 -        }
   63.89 -    } else {
   63.90 -        if (ucx_stack_align(((struct ucx_stack_metadata*)ptr - 1)->size) <
   63.91 -                ucx_stack_align(n)) {
   63.92 -            void *nptr = ucx_stack_malloc(stack, n);
   63.93 -            if (nptr) {
   63.94 -                memcpy(nptr, ptr, n);
   63.95 -                ucx_stack_free(stack, ptr);
   63.96 -                
   63.97 -                return nptr;
   63.98 -            } else {
   63.99 -                return NULL;
  63.100 -            }
  63.101 -        } else {
  63.102 -            ((struct ucx_stack_metadata*)ptr - 1)->size = n;
  63.103 -            return ptr;
  63.104 -        }
  63.105 -    }
  63.106 -}
  63.107 -
  63.108 -void ucx_stack_free(UcxStack *stack, void *ptr) {
  63.109 -    if (ptr == stack->top) {
  63.110 -        stack->top = ((struct ucx_stack_metadata*) stack->top - 1)->prev;
  63.111 -    } else {
  63.112 -        struct ucx_stack_metadata *next = (struct ucx_stack_metadata*)(
  63.113 -            (char*)ptr +
  63.114 -            ucx_stack_align(((struct ucx_stack_metadata*) ptr - 1)->size)
  63.115 -        );
  63.116 -        next->prev = ((struct ucx_stack_metadata*) ptr - 1)->prev;
  63.117 -    }
  63.118 -}
  63.119 -
  63.120 -void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) {
  63.121 -    if (ucx_stack_empty(stack)) {
  63.122 -        return;
  63.123 -    }
  63.124 -    
  63.125 -    size_t len = ucx_stack_topsize(stack);
  63.126 -    if (len > n) {
  63.127 -        len = n;
  63.128 -    }
  63.129 -    
  63.130 -    memcpy(dest, stack->top, len);
  63.131 -    
  63.132 -    ucx_stack_free(stack, stack->top);
  63.133 -}
  63.134 -
  63.135 -size_t ucx_stack_avail(UcxStack *stack) {
  63.136 -    size_t avail = ((stack->top ? (stack->size
  63.137 -                    - (stack->top - stack->space)
  63.138 -                    - ucx_stack_align(ucx_stack_topsize(stack)))
  63.139 -                    : stack->size));
  63.140 -    
  63.141 -    if (avail > sizeof(struct ucx_stack_metadata)) {
  63.142 -        return avail - sizeof(struct ucx_stack_metadata);
  63.143 -    } else {
  63.144 -        return 0;
  63.145 -    }
  63.146 -}
    64.1 --- a/ucx/stack.h	Tue Oct 17 15:15:54 2017 +0200
    64.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.3 @@ -1,232 +0,0 @@
    64.4 -/*
    64.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    64.6 - *
    64.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    64.8 - *
    64.9 - * Redistribution and use in source and binary forms, with or without
   64.10 - * modification, are permitted provided that the following conditions are met:
   64.11 - *
   64.12 - *   1. Redistributions of source code must retain the above copyright
   64.13 - *      notice, this list of conditions and the following disclaimer.
   64.14 - *
   64.15 - *   2. Redistributions in binary form must reproduce the above copyright
   64.16 - *      notice, this list of conditions and the following disclaimer in the
   64.17 - *      documentation and/or other materials provided with the distribution.
   64.18 - *
   64.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   64.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   64.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   64.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   64.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   64.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   64.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   64.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   64.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   64.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   64.29 - * POSSIBILITY OF SUCH DAMAGE.
   64.30 - */
   64.31 -
   64.32 -/**
   64.33 - * @file stack.h
   64.34 - * 
   64.35 - * Default stack memory allocation implementation.
   64.36 - * 
   64.37 - * @author Mike Becker
   64.38 - * @author Olaf Wintermann
   64.39 - */
   64.40 -
   64.41 -#ifndef UCX_STACK_H
   64.42 -#define	UCX_STACK_H
   64.43 -
   64.44 -#include "ucx.h"
   64.45 -#include "allocator.h"
   64.46 -
   64.47 -#ifdef	__cplusplus
   64.48 -extern "C" {
   64.49 -#endif
   64.50 -
   64.51 -
   64.52 -/**
   64.53 - * UCX stack structure.
   64.54 - */
   64.55 -typedef struct {
   64.56 -    /** UcxAllocator based on this stack */
   64.57 -    UcxAllocator allocator;
   64.58 -    
   64.59 -    /** Stack size. */
   64.60 -    size_t size;
   64.61 -    
   64.62 -    /** Pointer to the bottom of the stack */
   64.63 -    char *space;
   64.64 -    
   64.65 -    /** Pointer to the top of the stack */
   64.66 -    char *top;
   64.67 -} UcxStack;
   64.68 -
   64.69 -/**
   64.70 - * Metadata for each UCX stack element.
   64.71 - */
   64.72 -struct ucx_stack_metadata {
   64.73 -    /**
   64.74 -     * Location of the previous element (<code>NULL</code> if this is the first)
   64.75 -     */
   64.76 -    char *prev;
   64.77 -    
   64.78 -    /** Size of this element */
   64.79 -    size_t size;
   64.80 -};
   64.81 -
   64.82 -/**
   64.83 - * Initializes UcxStack structure with memory.
   64.84 - * 
   64.85 - * @param stack a pointer to an uninitialized stack structure
   64.86 - * @param space the memory area that shall be managed
   64.87 - * @param size size of the memory area
   64.88 - * @return a new UcxStack structure
   64.89 - */
   64.90 -void ucx_stack_init(UcxStack *stack, char* space, size_t size);
   64.91 -
   64.92 -/**
   64.93 - * Allocates stack memory.
   64.94 - * 
   64.95 - * @param stack a pointer to the stack
   64.96 - * @param n amount of memory to allocate
   64.97 - * @return a pointer to the allocated memory
   64.98 - * @see ucx_allocator_malloc()
   64.99 - */
  64.100 -void *ucx_stack_malloc(UcxStack *stack, size_t n);
  64.101 -
  64.102 -/**
  64.103 - * Alias for #ucx_stack_malloc().
  64.104 - * @param stack a pointer to the stack
  64.105 - * @param n amount of memory to allocate
  64.106 - * @return a pointer to the allocated memory
  64.107 - * @see ucx_stack_malloc
  64.108 - */
  64.109 -#define ucx_stack_push(stack, n) ucx_stack_malloc(stack, n)
  64.110 -
  64.111 -/**
  64.112 - * Allocates an array of stack memory
  64.113 - * 
  64.114 - * The content of the allocated memory is set to zero.
  64.115 - * 
  64.116 - * @param stack a pointer to the stack
  64.117 - * @param nelem amount of elements to allocate
  64.118 - * @param elsize amount of memory per element
  64.119 - * @return a pointer to the allocated memory
  64.120 - * @see ucx_allocator_calloc()
  64.121 - */
  64.122 -void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize);
  64.123 -
  64.124 -/**
  64.125 - * Alias for #ucx_stack_calloc().
  64.126 - * 
  64.127 - * @param stack a pointer to the stack
  64.128 - * @param n amount of elements to allocate
  64.129 - * @param elsize amount of memory per element
  64.130 - * @return a pointer to the allocated memory
  64.131 - * @see ucx_stack_calloc
  64.132 - */
  64.133 -#define ucx_stack_pusharr(stack,n,elsize) ucx_stack_calloc(stack,n,elssize)
  64.134 -
  64.135 -/**
  64.136 - * Reallocates memory on the stack.
  64.137 - * 
  64.138 - * Shrinking memory is always safe. Extending memory can be very expensive. 
  64.139 - * 
  64.140 - * @param stack the stack
  64.141 - * @param ptr a pointer to the memory that shall be reallocated
  64.142 - * @param n the new size of the memory
  64.143 - * @return a pointer to the new location of the memory
  64.144 - * @see ucx_allocator_realloc()
  64.145 - */
  64.146 -void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n);
  64.147 -
  64.148 -/**
  64.149 - * Frees memory on the stack.
  64.150 - * 
  64.151 - * Freeing stack memory behaves in a special way.
  64.152 - * 
  64.153 - * If the element, that should be freed, is the top most element of the stack,
  64.154 - * it is removed from the stack. Otherwise it is marked as freed. Marked
  64.155 - * elements are removed, when they become the top most elements of the stack.
  64.156 - * 
  64.157 - * @param stack a pointer to the stack
  64.158 - * @param ptr a pointer to the memory that shall be freed
  64.159 - */
  64.160 -void ucx_stack_free(UcxStack *stack, void *ptr);
  64.161 -
  64.162 -
  64.163 -/**
  64.164 - * Returns the size of the top most element.
  64.165 - * @param stack a pointer to the stack
  64.166 - * @return the size of the top most element
  64.167 - */
  64.168 -#define ucx_stack_topsize(stack) ((stack)->top ? ((struct ucx_stack_metadata*)\
  64.169 -                                  (stack)->top - 1)->size : 0)
  64.170 -
  64.171 -/**
  64.172 - * Removes the top most element from the stack and copies the content to <code>
  64.173 - * dest</code>, if specified.
  64.174 - * 
  64.175 - * Use #ucx_stack_topsize()# to get the amount of memory that must be available
  64.176 - * at the location of <code>dest</code>.
  64.177 - * 
  64.178 - * @param stack a pointer to the stack
  64.179 - * @param dest the location where the contents shall be written to, or <code>
  64.180 - * NULL</code>, if the element shall only be removed.
  64.181 - * @see ucx_stack_free
  64.182 - * @see ucx_stack_popn
  64.183 - */
  64.184 -#define ucx_stack_pop(stack, dest) ucx_stack_popn(stack, dest, (size_t)-1)
  64.185 -
  64.186 -/**
  64.187 - * Removes the top most element from the stack and copies the content to <code>
  64.188 - * dest</code>.
  64.189 - * 
  64.190 - * In contrast to #ucx_stack_pop() the <code>dest</code> pointer <code>MUST
  64.191 - * NOT</code> be <code>NULL</code>.
  64.192 - * 
  64.193 - * @param stack a pointer to the stack
  64.194 - * @param dest the location where the contents shall be written to
  64.195 - * @param n copies at most n elements to <code>dest</code>
  64.196 - * @see ucx_stack_pop
  64.197 - */
  64.198 -void ucx_stack_popn(UcxStack *stack, void *dest, size_t n);
  64.199 -
  64.200 -/**
  64.201 - * Returns the remaining available memory on the specified stack.
  64.202 - * 
  64.203 - * @param stack a pointer to the stack
  64.204 - * @return the remaining available memory
  64.205 - */
  64.206 -size_t ucx_stack_avail(UcxStack *stack);
  64.207 -
  64.208 -/**
  64.209 - * Checks, if the stack is empty.
  64.210 - * 
  64.211 - * @param stack a pointer to the stack
  64.212 - * @return nonzero, if the stack is empty, zero otherwise
  64.213 - */
  64.214 -#define ucx_stack_empty(stack) (!(stack)->top)
  64.215 -
  64.216 -/**
  64.217 - * Computes a recommended size for the stack memory area. Note, that
  64.218 - * reallocations have not been taken into account, so you might need to reserve
  64.219 - * twice as much memory to allow many reallocations.
  64.220 - * 
  64.221 - * @param size the approximate payload
  64.222 - * @param elems the approximate count of element allocations
  64.223 - * @return a recommended size for the stack space based on the information
  64.224 - * provided
  64.225 - */
  64.226 -#define ucx_stack_dim(size, elems) (size+sizeof(struct ucx_stack_metadata) * \
  64.227 -                                    (elems + 1))
  64.228 -
  64.229 -
  64.230 -#ifdef	__cplusplus
  64.231 -}
  64.232 -#endif
  64.233 -
  64.234 -#endif	/* UCX_STACK_H */
  64.235 -
    65.1 --- a/ucx/string.c	Tue Oct 17 15:15:54 2017 +0200
    65.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.3 @@ -1,462 +0,0 @@
    65.4 -/*
    65.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    65.6 - *
    65.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    65.8 - *
    65.9 - * Redistribution and use in source and binary forms, with or without
   65.10 - * modification, are permitted provided that the following conditions are met:
   65.11 - *
   65.12 - *   1. Redistributions of source code must retain the above copyright
   65.13 - *      notice, this list of conditions and the following disclaimer.
   65.14 - *
   65.15 - *   2. Redistributions in binary form must reproduce the above copyright
   65.16 - *      notice, this list of conditions and the following disclaimer in the
   65.17 - *      documentation and/or other materials provided with the distribution.
   65.18 - *
   65.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   65.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   65.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   65.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   65.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   65.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   65.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   65.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   65.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   65.29 - * POSSIBILITY OF SUCH DAMAGE.
   65.30 - */
   65.31 -
   65.32 -#include <stdlib.h>
   65.33 -#include <string.h>
   65.34 -#include <stdarg.h>
   65.35 -#include <stdint.h>
   65.36 -#include <ctype.h>
   65.37 -
   65.38 -#include "string.h"
   65.39 -#include "allocator.h"
   65.40 -
   65.41 -sstr_t sstr(char *cstring) {
   65.42 -    sstr_t string;
   65.43 -    string.ptr = cstring;
   65.44 -    string.length = strlen(cstring);
   65.45 -    return string;
   65.46 -}
   65.47 -
   65.48 -sstr_t sstrn(char *cstring, size_t length) {
   65.49 -    sstr_t string;
   65.50 -    string.ptr = cstring;
   65.51 -    string.length = length;
   65.52 -    return string;
   65.53 -}
   65.54 -
   65.55 -size_t sstrnlen(size_t n, sstr_t s, ...) {
   65.56 -    va_list ap;
   65.57 -    size_t size = s.length;
   65.58 -    va_start(ap, s);
   65.59 -
   65.60 -    for (size_t i = 1 ; i < n ; i++) {
   65.61 -        sstr_t str = va_arg(ap, sstr_t);
   65.62 -        size += str.length;
   65.63 -    }
   65.64 -    va_end(ap);
   65.65 -
   65.66 -    return size;
   65.67 -}
   65.68 -
   65.69 -static sstr_t sstrvcat_a(
   65.70 -        UcxAllocator *a,
   65.71 -        size_t count,
   65.72 -        sstr_t s1,
   65.73 -        sstr_t s2,
   65.74 -        va_list ap) {
   65.75 -    sstr_t str;
   65.76 -    str.ptr = NULL;
   65.77 -    str.length = 0;
   65.78 -    if(count < 2) {
   65.79 -        return str;
   65.80 -    }
   65.81 -    
   65.82 -    sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t));
   65.83 -    if(!strings) {
   65.84 -        return str;
   65.85 -    }
   65.86 -    
   65.87 -    // get all args and overall length
   65.88 -    strings[0] = s1;
   65.89 -    strings[1] = s2;
   65.90 -    size_t strlen = s1.length + s2.length;
   65.91 -    for (size_t i=2;i<count;i++) {
   65.92 -        sstr_t s = va_arg (ap, sstr_t);
   65.93 -        strings[i] = s;
   65.94 -        strlen += s.length;
   65.95 -    }
   65.96 -    
   65.97 -    // create new string
   65.98 -    str.ptr = (char*) almalloc(a, strlen + 1);
   65.99 -    str.length = strlen;
  65.100 -    if(!str.ptr) {
  65.101 -        free(strings);
  65.102 -        str.length = 0;
  65.103 -        return str;
  65.104 -    }
  65.105 -    
  65.106 -    // concatenate strings
  65.107 -    size_t pos = 0;
  65.108 -    for (size_t i=0;i<count;i++) {
  65.109 -        sstr_t s = strings[i];
  65.110 -        memcpy(str.ptr + pos, s.ptr, s.length);
  65.111 -        pos += s.length;
  65.112 -    }
  65.113 -    
  65.114 -    str.ptr[str.length] = '\0';
  65.115 -    
  65.116 -    free(strings);
  65.117 -    
  65.118 -    return str;
  65.119 -}
  65.120 -
  65.121 -sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) {
  65.122 -    va_list ap;
  65.123 -    va_start(ap, s2);
  65.124 -    sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap);
  65.125 -    va_end(ap);
  65.126 -    return s;
  65.127 -}
  65.128 -
  65.129 -sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) {
  65.130 -    va_list ap;
  65.131 -    va_start(ap, s2);
  65.132 -    sstr_t s = sstrvcat_a(a, count, s1, s2, ap);
  65.133 -    va_end(ap);
  65.134 -    return s;
  65.135 -}
  65.136 -
  65.137 -sstr_t sstrsubs(sstr_t s, size_t start) {
  65.138 -    return sstrsubsl (s, start, s.length-start);
  65.139 -}
  65.140 -
  65.141 -sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) {
  65.142 -    sstr_t new_sstr;
  65.143 -    if (start >= s.length) {
  65.144 -        new_sstr.ptr = NULL;
  65.145 -        new_sstr.length = 0;
  65.146 -    } else {
  65.147 -        if (length > s.length-start) {
  65.148 -            length = s.length-start;
  65.149 -        }
  65.150 -        new_sstr.ptr = &s.ptr[start];
  65.151 -        new_sstr.length = length;
  65.152 -    }
  65.153 -    return new_sstr;
  65.154 -}
  65.155 -
  65.156 -sstr_t sstrchr(sstr_t s, int c) {
  65.157 -    for(size_t i=0;i<s.length;i++) {
  65.158 -        if(s.ptr[i] == c) {
  65.159 -            return sstrsubs(s, i);
  65.160 -        }
  65.161 -    }
  65.162 -    sstr_t n;
  65.163 -    n.ptr = NULL;
  65.164 -    n.length = 0;
  65.165 -    return n;
  65.166 -}
  65.167 -
  65.168 -sstr_t sstrrchr(sstr_t s, int c) {
  65.169 -    if (s.length > 0) {
  65.170 -        for(size_t i=s.length;i>0;i--) {
  65.171 -            if(s.ptr[i-1] == c) {
  65.172 -                return sstrsubs(s, i-1);
  65.173 -            }
  65.174 -        }
  65.175 -    }
  65.176 -    sstr_t n;
  65.177 -    n.ptr = NULL;
  65.178 -    n.length = 0;
  65.179 -    return n;
  65.180 -}
  65.181 -
  65.182 -#define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \
  65.183 -    ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index])
  65.184 -
  65.185 -#define ptable_w(useheap, ptable, index, src) do {\
  65.186 -    if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\
  65.187 -    else ((size_t*)ptable)[index] = src;\
  65.188 -    } while (0);
  65.189 -
  65.190 -sstr_t sstrstr(sstr_t string, sstr_t match) {
  65.191 -    if (match.length == 0) {
  65.192 -        return string;
  65.193 -    }
  65.194 -    
  65.195 -    /* prepare default return value in case of no match */
  65.196 -    sstr_t result = sstrn(NULL, 0);
  65.197 -    
  65.198 -    /*
  65.199 -     * IMPORTANT:
  65.200 -     * our prefix table contains the prefix length PLUS ONE
  65.201 -     * this is our decision, because we want to use the full range of size_t
  65.202 -     * the original algorithm needs a (-1) at one single place
  65.203 -     * and we want to avoid that
  65.204 -     */
  65.205 -    
  65.206 -    /* static prefix table */
  65.207 -    static uint8_t s_prefix_table[256];
  65.208 -    
  65.209 -    /* check pattern length and use appropriate prefix table */
  65.210 -    /* if the pattern exceeds static prefix table, allocate on the heap */
  65.211 -    register int useheap = match.length > 255;
  65.212 -    register void* ptable = useheap ?
  65.213 -        calloc(match.length+1, sizeof(size_t)): s_prefix_table;
  65.214 -    
  65.215 -    /* keep counter in registers */
  65.216 -    register size_t i, j;
  65.217 -    
  65.218 -    /* fill prefix table */
  65.219 -    i = 0; j = 0;
  65.220 -    ptable_w(useheap, ptable, i, j);
  65.221 -    while (i < match.length) {
  65.222 -        while (j >= 1 && match.ptr[j-1] != match.ptr[i]) {
  65.223 -            ptable_r(j, useheap, ptable, j-1);
  65.224 -        }
  65.225 -        i++; j++;
  65.226 -        ptable_w(useheap, ptable, i, j);
  65.227 -    }
  65.228 -
  65.229 -    /* search */
  65.230 -    i = 0; j = 1;
  65.231 -    while (i < string.length) {
  65.232 -        while (j >= 1 && string.ptr[i] != match.ptr[j-1]) {
  65.233 -            ptable_r(j, useheap, ptable, j-1);
  65.234 -        }
  65.235 -        i++; j++;
  65.236 -        if (j-1 == match.length) {
  65.237 -            size_t start = i - match.length;
  65.238 -            result.ptr = string.ptr + start;
  65.239 -            result.length = string.length - start;
  65.240 -            break;
  65.241 -        }
  65.242 -    }
  65.243 -
  65.244 -    /* if prefix table was allocated on the heap, free it */
  65.245 -    if (ptable != s_prefix_table) {
  65.246 -        free(ptable);
  65.247 -    }
  65.248 -    
  65.249 -    return result;
  65.250 -}
  65.251 -
  65.252 -#undef ptable_r
  65.253 -#undef ptable_w
  65.254 -
  65.255 -sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) {
  65.256 -    return sstrsplit_a(ucx_default_allocator(), s, d, n);
  65.257 -}
  65.258 -
  65.259 -sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) {
  65.260 -    if (s.length == 0 || d.length == 0) {
  65.261 -        *n = -1;
  65.262 -        return NULL;
  65.263 -    }
  65.264 -    
  65.265 -    /* special cases: delimiter is at least as large as the string */
  65.266 -    if (d.length >= s.length) {
  65.267 -        /* exact match */
  65.268 -        if (sstrcmp(s, d) == 0) {
  65.269 -            *n = 0;
  65.270 -            return NULL;
  65.271 -        } else /* no match possible */ {
  65.272 -            *n = 1;
  65.273 -            sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t));
  65.274 -            *result = sstrdup_a(allocator, s);
  65.275 -            return result;
  65.276 -        }
  65.277 -    }
  65.278 -    
  65.279 -    ssize_t nmax = *n;
  65.280 -    size_t arrlen = 16;
  65.281 -    sstr_t* result = (sstr_t*) almalloc(allocator, arrlen*sizeof(sstr_t));
  65.282 -
  65.283 -    if (result) {
  65.284 -        sstr_t curpos = s;
  65.285 -        ssize_t j = 1;
  65.286 -        while (1) {
  65.287 -            sstr_t match;
  65.288 -            /* optimize for one byte delimiters */
  65.289 -            if (d.length == 1) {
  65.290 -                match = curpos;
  65.291 -                for (size_t i = 0 ; i < curpos.length ; i++) {
  65.292 -                    if (curpos.ptr[i] == *(d.ptr)) {
  65.293 -                        match.ptr = curpos.ptr + i;
  65.294 -                        break;
  65.295 -                    }
  65.296 -                    match.length--;
  65.297 -                }
  65.298 -            } else {
  65.299 -                match = sstrstr(curpos, d);
  65.300 -            }
  65.301 -            if (match.length > 0) {
  65.302 -                /* is this our last try? */
  65.303 -                if (nmax == 0 || j < nmax) {
  65.304 -                    /* copy the current string to the array */
  65.305 -                    sstr_t item = sstrn(curpos.ptr, match.ptr - curpos.ptr);
  65.306 -                    result[j-1] = sstrdup_a(allocator, item);
  65.307 -                    size_t processed = item.length + d.length;
  65.308 -                    curpos.ptr += processed;
  65.309 -                    curpos.length -= processed;
  65.310 -
  65.311 -                    /* allocate memory for the next string */
  65.312 -                    j++;
  65.313 -                    if (j > arrlen) {
  65.314 -                        arrlen *= 2;
  65.315 -                        sstr_t* reallocated = (sstr_t*) alrealloc(
  65.316 -                                allocator, result, arrlen*sizeof(sstr_t));
  65.317 -                        if (reallocated) {
  65.318 -                            result = reallocated;
  65.319 -                        } else {
  65.320 -                            for (ssize_t i = 0 ; i < j-1 ; i++) {
  65.321 -                                alfree(allocator, result[i].ptr);
  65.322 -                            }
  65.323 -                            alfree(allocator, result);
  65.324 -                            *n = -2;
  65.325 -                            return NULL;
  65.326 -                        }
  65.327 -                    }
  65.328 -                } else {
  65.329 -                    /* nmax reached, copy the _full_ remaining string */
  65.330 -                    result[j-1] = sstrdup_a(allocator, curpos);
  65.331 -                    break;
  65.332 -                }
  65.333 -            } else {
  65.334 -                /* no more matches, copy last string */
  65.335 -                result[j-1] = sstrdup_a(allocator, curpos);
  65.336 -                break;
  65.337 -            }
  65.338 -        }
  65.339 -        *n = j;
  65.340 -    } else {
  65.341 -        *n = -2;
  65.342 -    }
  65.343 -
  65.344 -    return result;
  65.345 -}
  65.346 -
  65.347 -int sstrcmp(sstr_t s1, sstr_t s2) {
  65.348 -    if (s1.length == s2.length) {
  65.349 -        return memcmp(s1.ptr, s2.ptr, s1.length);
  65.350 -    } else if (s1.length > s2.length) {
  65.351 -        return 1;
  65.352 -    } else {
  65.353 -        return -1;
  65.354 -    }
  65.355 -}
  65.356 -
  65.357 -int sstrcasecmp(sstr_t s1, sstr_t s2) {
  65.358 -    if (s1.length == s2.length) {
  65.359 -#ifdef _WIN32
  65.360 -        return _strnicmp(s1.ptr, s2.ptr, s1.length);
  65.361 -#else
  65.362 -        return strncasecmp(s1.ptr, s2.ptr, s1.length);
  65.363 -#endif
  65.364 -    } else if (s1.length > s2.length) {
  65.365 -        return 1;
  65.366 -    } else {
  65.367 -        return -1;
  65.368 -    }
  65.369 -}
  65.370 -
  65.371 -sstr_t sstrdup(sstr_t s) {
  65.372 -    return sstrdup_a(ucx_default_allocator(), s);
  65.373 -}
  65.374 -
  65.375 -sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) {
  65.376 -    sstr_t newstring;
  65.377 -    newstring.ptr = (char*)almalloc(allocator, s.length + 1);
  65.378 -    if (newstring.ptr) {
  65.379 -        newstring.length = s.length;
  65.380 -        newstring.ptr[newstring.length] = 0;
  65.381 -        
  65.382 -        memcpy(newstring.ptr, s.ptr, s.length);
  65.383 -    } else {
  65.384 -        newstring.length = 0;
  65.385 -    }
  65.386 -    
  65.387 -    return newstring;
  65.388 -}
  65.389 -
  65.390 -sstr_t sstrtrim(sstr_t string) {
  65.391 -    sstr_t newstr = string;
  65.392 -    
  65.393 -    while (newstr.length > 0 && isspace(*newstr.ptr)) {
  65.394 -        newstr.ptr++;
  65.395 -        newstr.length--;
  65.396 -    }
  65.397 -    while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) {
  65.398 -        newstr.length--;
  65.399 -    }
  65.400 -    
  65.401 -    return newstr;
  65.402 -}
  65.403 -
  65.404 -int sstrprefix(sstr_t string, sstr_t prefix) {
  65.405 -    if (string.length == 0) {
  65.406 -        return prefix.length == 0;
  65.407 -    }
  65.408 -    if (prefix.length == 0) {
  65.409 -        return 1;
  65.410 -    }
  65.411 -    
  65.412 -    if (prefix.length > string.length) {
  65.413 -        return 0;
  65.414 -    } else {
  65.415 -        return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
  65.416 -    }
  65.417 -}
  65.418 -
  65.419 -int sstrsuffix(sstr_t string, sstr_t suffix) {
  65.420 -    if (string.length == 0) {
  65.421 -        return suffix.length == 0;
  65.422 -    }
  65.423 -    if (suffix.length == 0) {
  65.424 -        return 1;
  65.425 -    }
  65.426 -    
  65.427 -    if (suffix.length > string.length) {
  65.428 -        return 0;
  65.429 -    } else {
  65.430 -        return memcmp(string.ptr+string.length-suffix.length,
  65.431 -            suffix.ptr, suffix.length) == 0;
  65.432 -    }
  65.433 -}
  65.434 -
  65.435 -sstr_t sstrlower(sstr_t string) {
  65.436 -    sstr_t ret = sstrdup(string);
  65.437 -    for (size_t i = 0; i < ret.length ; i++) {
  65.438 -        ret.ptr[i] = tolower(ret.ptr[i]);
  65.439 -    }
  65.440 -    return ret;
  65.441 -}
  65.442 -
  65.443 -sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) {
  65.444 -    sstr_t ret = sstrdup_a(allocator, string);
  65.445 -    for (size_t i = 0; i < ret.length ; i++) {
  65.446 -        ret.ptr[i] = tolower(ret.ptr[i]);
  65.447 -    }
  65.448 -    return ret;
  65.449 -}
  65.450 -
  65.451 -sstr_t sstrupper(sstr_t string) {
  65.452 -    sstr_t ret = sstrdup(string);
  65.453 -    for (size_t i = 0; i < ret.length ; i++) {
  65.454 -        ret.ptr[i] = toupper(ret.ptr[i]);
  65.455 -    }
  65.456 -    return ret;
  65.457 -}
  65.458 -
  65.459 -sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) {
  65.460 -    sstr_t ret = sstrdup_a(allocator, string);
  65.461 -    for (size_t i = 0; i < ret.length ; i++) {
  65.462 -        ret.ptr[i] = toupper(ret.ptr[i]);
  65.463 -    }
  65.464 -    return ret;
  65.465 -}
    66.1 --- a/ucx/string.h	Tue Oct 17 15:15:54 2017 +0200
    66.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.3 @@ -1,460 +0,0 @@
    66.4 -/*
    66.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    66.6 - *
    66.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    66.8 - *
    66.9 - * Redistribution and use in source and binary forms, with or without
   66.10 - * modification, are permitted provided that the following conditions are met:
   66.11 - *
   66.12 - *   1. Redistributions of source code must retain the above copyright
   66.13 - *      notice, this list of conditions and the following disclaimer.
   66.14 - *
   66.15 - *   2. Redistributions in binary form must reproduce the above copyright
   66.16 - *      notice, this list of conditions and the following disclaimer in the
   66.17 - *      documentation and/or other materials provided with the distribution.
   66.18 - *
   66.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   66.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   66.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   66.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   66.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   66.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   66.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   66.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   66.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   66.29 - * POSSIBILITY OF SUCH DAMAGE.
   66.30 - */
   66.31 -/**
   66.32 - * Bounded string implementation.
   66.33 - * 
   66.34 - * The UCX strings (<code>sstr_t</code>) provide an alternative to C strings.
   66.35 - * The main difference to C strings is, that <code>sstr_t</code> does <b>not
   66.36 - * need to be <code>NULL</code>-terminated</b>. Instead the length is stored
   66.37 - * within the structure.
   66.38 - * 
   66.39 - * When using <code>sstr_t</code>, developers must be full aware of what type
   66.40 - * of string (<code>NULL</code>-terminated) or not) they are using, when 
   66.41 - * accessing the <code>char* ptr</code> directly.
   66.42 - * 
   66.43 - * The UCX string module provides some common string functions, known from
   66.44 - * standard libc, working with <code>sstr_t</code>.
   66.45 - * 
   66.46 - * @file   string.h
   66.47 - * @author Mike Becker
   66.48 - * @author Olaf Wintermann
   66.49 - */
   66.50 -
   66.51 -#ifndef UCX_STRING_H
   66.52 -#define	UCX_STRING_H
   66.53 -
   66.54 -#include "ucx.h"
   66.55 -#include "allocator.h"
   66.56 -#include <stddef.h>
   66.57 -
   66.58 -/** Shortcut for a <code>sstr_t struct</code> literal. */
   66.59 -#define ST(s) { (char*)s, sizeof(s)-1 }
   66.60 -
   66.61 -/** Shortcut for the conversion of a C string to a <code>sstr_t</code>. */
   66.62 -#define S(s) sstrn((char*)s, sizeof(s)-1)
   66.63 -
   66.64 -#ifdef	__cplusplus
   66.65 -extern "C" {
   66.66 -#endif
   66.67 -
   66.68 -/**
   66.69 - * The UCX string structure.
   66.70 - */
   66.71 -typedef struct {
   66.72 -   /** A reference to the string (<b>not necessarily  <code>NULL</code>
   66.73 -    * -terminated</b>) */
   66.74 -    char   *ptr;
   66.75 -    /** The length of the string */
   66.76 -    size_t length;
   66.77 -} sstr_t;
   66.78 -
   66.79 -/**
   66.80 - * Creates a new sstr_t based on a C string.
   66.81 - * 
   66.82 - * The length is implicitly inferred by using a call to <code>strlen()</code>.
   66.83 - *
   66.84 - * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you
   66.85 - * do want a copy, use sstrdup() on the return value of this function.
   66.86 - * 
   66.87 - * @param cstring the C string to wrap
   66.88 - * @return a new sstr_t containing the C string
   66.89 - * 
   66.90 - * @see sstrn()
   66.91 - */
   66.92 -sstr_t sstr(char *cstring);
   66.93 -
   66.94 -/**
   66.95 - * Creates a new sstr_t of the specified length based on a C string.
   66.96 - *
   66.97 - * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you
   66.98 - * do want a copy, use sstrdup() on the return value of this function.
   66.99 - * 
  66.100 - * @param cstring  the C string to wrap
  66.101 - * @param length   the length of the string
  66.102 - * @return a new sstr_t containing the C string
  66.103 - * 
  66.104 - * @see sstr()
  66.105 - * @see S()
  66.106 - */
  66.107 -sstr_t sstrn(char *cstring, size_t length);
  66.108 -
  66.109 -
  66.110 -/**
  66.111 - * Returns the cumulated length of all specified strings.
  66.112 - *
  66.113 - * At least one string must be specified.
  66.114 - * 
  66.115 - * <b>Attention:</b> if the count argument does not match the count of the
  66.116 - * specified strings, the behavior is undefined.
  66.117 - *
  66.118 - * @param count    the total number of specified strings (so at least 1)
  66.119 - * @param string   the first string
  66.120 - * @param ...      all other strings
  66.121 - * @return the cumulated length of all strings
  66.122 - */
  66.123 -size_t sstrnlen(size_t count, sstr_t string, ...);
  66.124 -
  66.125 -/**
  66.126 - * Concatenates two or more strings.
  66.127 - * 
  66.128 - * The resulting string will be allocated by standard <code>malloc()</code>. 
  66.129 - * So developers <b>MUST</b> pass the sstr_t.ptr to <code>free()</code>.
  66.130 - * 
  66.131 - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>-
  66.132 - * terminated.
  66.133 - *
  66.134 - * @param count   the total number of strings to concatenate
  66.135 - * @param s1      first string
  66.136 - * @param s2      second string
  66.137 - * @param ...     all remaining strings
  66.138 - * @return the concatenated string
  66.139 - */
  66.140 -sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...);
  66.141 -
  66.142 -/**
  66.143 - * Concatenates two or more strings using a UcxAllocator.
  66.144 - * 
  66.145 - * See sstrcat() for details.
  66.146 - *
  66.147 - * @param a       the allocator to use
  66.148 - * @param count   the total number of strings to concatenate
  66.149 - * @param s1      first string
  66.150 - * @param s2      second string
  66.151 - * @param ...     all remaining strings
  66.152 - * @return the concatenated string
  66.153 - */
  66.154 -sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...);
  66.155 -
  66.156 -
  66.157 -/**
  66.158 - * Returns a substring starting at the specified location.
  66.159 - * 
  66.160 - * <b>Attention:</b> the new string references the same memory area as the
  66.161 - * input string and will <b>NOT</b> be <code>NULL</code>-terminated.
  66.162 - * Use sstrdup() to get a copy.
  66.163 - * 
  66.164 - * @param string input string
  66.165 - * @param start  start location of the substring
  66.166 - * @return a substring of <code>string</code> starting at <code>start</code>
  66.167 - * 
  66.168 - * @see sstrsubsl()
  66.169 - * @see sstrchr()
  66.170 - */
  66.171 -sstr_t sstrsubs(sstr_t string, size_t start);
  66.172 -
  66.173 -/**
  66.174 - * Returns a substring with a maximum length starting at the specified location.
  66.175 - * 
  66.176 - * <b>Attention:</b> the new string references the same memory area as the
  66.177 - * input string and will <b>NOT</b> be <code>NULL</code>-terminated.
  66.178 - * Use sstrdup() to get a copy.
  66.179 - * 
  66.180 - * @param string input string
  66.181 - * @param start  start location of the substring
  66.182 - * @param length the maximum length of the substring
  66.183 - * @return a substring of <code>string</code> starting at <code>start</code>
  66.184 - * with a maximum length of <code>length</code>
  66.185 - * 
  66.186 - * @see sstrsubs()
  66.187 - * @see sstrchr()
  66.188 - */
  66.189 -sstr_t sstrsubsl(sstr_t string, size_t start, size_t length);
  66.190 -
  66.191 -/**
  66.192 - * Returns a substring starting at the location of the first occurrence of the
  66.193 - * specified character.
  66.194 - * 
  66.195 - * If the string does not contain the character, an empty string is returned.
  66.196 - * 
  66.197 - * @param string the string where to locate the character
  66.198 - * @param chr    the character to locate
  66.199 - * @return       a substring starting at the first location of <code>chr</code>
  66.200 - * 
  66.201 - * @see sstrsubs()
  66.202 - */
  66.203 -sstr_t sstrchr(sstr_t string, int chr);
  66.204 -
  66.205 -/**
  66.206 - * Returns a substring starting at the location of the last occurrence of the
  66.207 - * specified character.
  66.208 - * 
  66.209 - * If the string does not contain the character, an empty string is returned.
  66.210 - * 
  66.211 - * @param string the string where to locate the character
  66.212 - * @param chr    the character to locate
  66.213 - * @return       a substring starting at the last location of <code>chr</code>
  66.214 - * 
  66.215 - * @see sstrsubs()
  66.216 - */
  66.217 -sstr_t sstrrchr(sstr_t string, int chr);
  66.218 -
  66.219 -/**
  66.220 - * Returns a substring starting at the location of the first occurrence of the
  66.221 - * specified string.
  66.222 - * 
  66.223 - * If the string does not contain the other string, an empty string is returned.
  66.224 - * 
  66.225 - * If <code>match</code> is an empty string, the complete <code>string</code> is
  66.226 - * returned.
  66.227 - * 
  66.228 - * @param string the string to be scanned
  66.229 - * @param match  string containing the sequence of characters to match
  66.230 - * @return       a substring starting at the first occurrence of
  66.231 - *               <code>match</code>, or an empty string, if the sequence is not
  66.232 - *               present in <code>string</code>
  66.233 - */
  66.234 -sstr_t sstrstr(sstr_t string, sstr_t match);
  66.235 -
  66.236 -/**
  66.237 - * Splits a string into parts by using a delimiter string.
  66.238 - * 
  66.239 - * This function will return <code>NULL</code>, if one of the following happens:
  66.240 - * <ul>
  66.241 - *   <li>the string length is zero</li>
  66.242 - *   <li>the delimeter length is zero</li>
  66.243 - *   <li>the string equals the delimeter</li>
  66.244 - *   <li>memory allocation fails</li>
  66.245 - * </ul>
  66.246 - * 
  66.247 - * The integer referenced by <code>count</code> is used as input and determines
  66.248 - * the maximum size of the resulting array, i.e. the maximum count of splits to
  66.249 - * perform + 1.
  66.250 - * 
  66.251 - * The integer referenced by <code>count</code> is also used as output and is
  66.252 - * set to
  66.253 - * <ul>
  66.254 - *   <li>-2, on memory allocation errors</li>
  66.255 - *   <li>-1, if either the string or the delimiter is an empty string</li>
  66.256 - *   <li>0, if the string equals the delimiter</li>
  66.257 - *   <li>1, if the string does not contain the delimiter</li>
  66.258 - *   <li>the count of array items, otherwise</li>
  66.259 - * </ul>
  66.260 - * 
  66.261 - * If the string starts with the delimiter, the first item of the resulting
  66.262 - * array will be an empty string.
  66.263 - * 
  66.264 - * If the string ends with the delimiter and the maximum list size is not
  66.265 - * exceeded, the last array item will be an empty string.
  66.266 - * In case the list size would be exceeded, the last array item will be the
  66.267 - * remaining string after the last split, <i>including</i> the terminating
  66.268 - * delimiter.
  66.269 - * 
  66.270 - * <b>Attention:</b> The array pointer <b>AND</b> all sstr_t.ptr of the array
  66.271 - * items must be manually passed to <code>free()</code>. Use sstrsplit_a() with
  66.272 - * an allocator to managed memory, to avoid this.
  66.273 - *
  66.274 - * @param string the string to split
  66.275 - * @param delim  the delimiter string
  66.276 - * @param count  IN: the maximum size of the resulting array (0 = no limit),
  66.277 - *               OUT: the actual size of the array
  66.278 - * @return a sstr_t array containing the split strings or
  66.279 - *         <code>NULL</code> on error
  66.280 - * 
  66.281 - * @see sstrsplit_a()
  66.282 - */
  66.283 -sstr_t* sstrsplit(sstr_t string, sstr_t delim, ssize_t *count);
  66.284 -
  66.285 -/**
  66.286 - * Performing sstrsplit() using a UcxAllocator.
  66.287 - * 
  66.288 - * <i>Read the description of sstrsplit() for details.</i>
  66.289 - * 
  66.290 - * The memory for the sstr_t.ptr pointers of the array items and the memory for
  66.291 - * the sstr_t array itself are allocated by using the UcxAllocator.malloc()
  66.292 - * function.
  66.293 - * 
  66.294 - * <b>Note:</b> the allocator is not used for memory that is freed within the
  66.295 - * same call of this function (locally scoped variables).
  66.296 - * 
  66.297 - * @param allocator the UcxAllocator used for allocating memory
  66.298 - * @param string the string to split
  66.299 - * @param delim  the delimiter string
  66.300 - * @param count  IN: the maximum size of the resulting array (0 = no limit),
  66.301 - *               OUT: the actual size of the array
  66.302 - * @return a sstr_t array containing the split strings or
  66.303 - *         <code>NULL</code> on error
  66.304 - * 
  66.305 - * @see sstrsplit()
  66.306 - */
  66.307 -sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t string, sstr_t delim,
  66.308 -        ssize_t *count);
  66.309 -
  66.310 -/**
  66.311 - * Compares two UCX strings with standard <code>memcmp()</code>.
  66.312 - * 
  66.313 - * At first it compares the sstr_t.length attribute of the two strings. The
  66.314 - * <code>memcmp()</code> function is called, if and only if the lengths match.
  66.315 - * 
  66.316 - * @param s1 the first string
  66.317 - * @param s2 the second string
  66.318 - * @return -1, if the length of s1 is less than the length of s2 or 1, if the 
  66.319 - * length of s1 is greater than the length of s2 or the result of
  66.320 - * <code>memcmp()</code> otherwise (i.e. 0 if the strings match)
  66.321 - */
  66.322 -int sstrcmp(sstr_t s1, sstr_t s2);
  66.323 -
  66.324 -/**
  66.325 - * Compares two UCX strings ignoring the case.
  66.326 - * 
  66.327 - * At first it compares the sstr_t.length attribute of the two strings. If and
  66.328 - * only if the lengths match, both strings are compared char by char ignoring
  66.329 - * the case.
  66.330 - * 
  66.331 - * @param s1 the first string
  66.332 - * @param s2 the second string
  66.333 - * @return -1, if the length of s1 is less than the length of s2 or 1, if the 
  66.334 - * length of s1 is greater than the length of s2 or the difference between the
  66.335 - * first two differing characters otherwise (i.e. 0 if the strings match and
  66.336 - * no characters differ)
  66.337 - */
  66.338 -int sstrcasecmp(sstr_t s1, sstr_t s2);
  66.339 -
  66.340 -/**
  66.341 - * Creates a duplicate of the specified string.
  66.342 - * 
  66.343 - * The new sstr_t will contain a copy allocated by standard
  66.344 - * <code>malloc()</code>. So developers <b>MUST</b> pass the sstr_t.ptr to
  66.345 - * <code>free()</code>.
  66.346 - * 
  66.347 - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>-
  66.348 - * terminated.
  66.349 - * 
  66.350 - * @param string the string to duplicate
  66.351 - * @return a duplicate of the string
  66.352 - * @see sstrdup_a()
  66.353 - */
  66.354 -sstr_t sstrdup(sstr_t string);
  66.355 -
  66.356 -/**
  66.357 - * Creates a duplicate of the specified string using a UcxAllocator.
  66.358 - * 
  66.359 - * The new sstr_t will contain a copy allocated by the allocators
  66.360 - * ucx_allocator_malloc function. So it is implementation depended, whether the
  66.361 - * returned sstr_t.ptr pointer must be passed to the allocators
  66.362 - * ucx_allocator_free function manually.
  66.363 - * 
  66.364 - * The sstr_t.ptr of the return value will <i>always</i> be <code>NULL</code>-
  66.365 - * terminated.
  66.366 - * 
  66.367 - * @param allocator a valid instance of a UcxAllocator
  66.368 - * @param string the string to duplicate
  66.369 - * @return a duplicate of the string
  66.370 - * @see sstrdup()
  66.371 - */
  66.372 -sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t string);
  66.373 -
  66.374 -/**
  66.375 - * Omits leading and trailing spaces.
  66.376 - * 
  66.377 - * This function returns a new sstr_t containing a trimmed version of the
  66.378 - * specified string.
  66.379 - * 
  66.380 - * <b>Note:</b> the new sstr_t references the same memory, thus you
  66.381 - * <b>MUST NOT</b> pass the sstr_t.ptr of the return value to
  66.382 - * <code>free()</code>. It is also highly recommended to avoid assignments like
  66.383 - * <code>mystr = sstrtrim(mystr);</code> as you lose the reference to the
  66.384 - * source string. Assignments of this type are only permitted, if the
  66.385 - * sstr_t.ptr of the source string does not need to be freed or if another
  66.386 - * reference to the source string exists.
  66.387 - * 
  66.388 - * @param string the string that shall be trimmed
  66.389 - * @return a new sstr_t containing the trimmed string
  66.390 - */
  66.391 -sstr_t sstrtrim(sstr_t string);
  66.392 -
  66.393 -/**
  66.394 - * Checks, if a string has a specific prefix.
  66.395 - * @param string the string to check
  66.396 - * @param prefix the prefix the string should have
  66.397 - * @return 1, if and only if the string has the specified prefix, 0 otherwise
  66.398 - */
  66.399 -int sstrprefix(sstr_t string, sstr_t prefix);
  66.400 -
  66.401 -/**
  66.402 - * Checks, if a string has a specific suffix.
  66.403 - * @param string the string to check
  66.404 - * @param suffix the suffix the string should have
  66.405 - * @return 1, if and only if the string has the specified suffix, 0 otherwise
  66.406 - */
  66.407 -int sstrsuffix(sstr_t string, sstr_t suffix);
  66.408 -
  66.409 -/**
  66.410 - * Returns a lower case version of a string.
  66.411 - * 
  66.412 - * This function creates a duplicate of the input string, first. See the
  66.413 - * documentation of sstrdup() for the implications.
  66.414 - * 
  66.415 - * @param string the input string
  66.416 - * @return the resulting lower case string
  66.417 - * @see sstrdup()
  66.418 - */
  66.419 -sstr_t sstrlower(sstr_t string);
  66.420 -
  66.421 -/**
  66.422 - * Returns a lower case version of a string.
  66.423 - * 
  66.424 - * This function creates a duplicate of the input string, first. See the
  66.425 - * documentation of sstrdup_a() for the implications.
  66.426 - * 
  66.427 - * @param allocator the allocator used for duplicating the string
  66.428 - * @param string the input string
  66.429 - * @return the resulting lower case string
  66.430 - * @see sstrdup_a()
  66.431 - */
  66.432 -sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string);
  66.433 -
  66.434 -/**
  66.435 - * Returns a upper case version of a string.
  66.436 - * 
  66.437 - * This function creates a duplicate of the input string, first. See the
  66.438 - * documentation of sstrdup() for the implications.
  66.439 - * 
  66.440 - * @param string the input string
  66.441 - * @return the resulting upper case string
  66.442 - * @see sstrdup()
  66.443 - */
  66.444 -sstr_t sstrupper(sstr_t string);
  66.445 -
  66.446 -/**
  66.447 - * Returns a upper case version of a string.
  66.448 - * 
  66.449 - * This function creates a duplicate of the input string, first. See the
  66.450 - * documentation of sstrdup_a() for the implications.
  66.451 - * 
  66.452 - * @param allocator the allocator used for duplicating the string
  66.453 - * @param string the input string
  66.454 - * @return the resulting upper case string
  66.455 - * @see sstrdup_a()
  66.456 - */
  66.457 -sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string);
  66.458 -
  66.459 -#ifdef	__cplusplus
  66.460 -}
  66.461 -#endif
  66.462 -
  66.463 -#endif	/* UCX_STRING_H */
    67.1 --- a/ucx/test.c	Tue Oct 17 15:15:54 2017 +0200
    67.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.3 @@ -1,91 +0,0 @@
    67.4 -/*
    67.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    67.6 - *
    67.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    67.8 - *
    67.9 - * Redistribution and use in source and binary forms, with or without
   67.10 - * modification, are permitted provided that the following conditions are met:
   67.11 - *
   67.12 - *   1. Redistributions of source code must retain the above copyright
   67.13 - *      notice, this list of conditions and the following disclaimer.
   67.14 - *
   67.15 - *   2. Redistributions in binary form must reproduce the above copyright
   67.16 - *      notice, this list of conditions and the following disclaimer in the
   67.17 - *      documentation and/or other materials provided with the distribution.
   67.18 - *
   67.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   67.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   67.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   67.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   67.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   67.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   67.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   67.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   67.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   67.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   67.29 - * POSSIBILITY OF SUCH DAMAGE.
   67.30 - */
   67.31 -
   67.32 -#include "test.h"
   67.33 -
   67.34 -UcxTestSuite* ucx_test_suite_new() {
   67.35 -    UcxTestSuite* suite = (UcxTestSuite*) malloc(sizeof(UcxTestSuite));
   67.36 -    if (suite != NULL) {
   67.37 -        suite->success = 0;
   67.38 -        suite->failure = 0;
   67.39 -        suite->tests = NULL;
   67.40 -    }
   67.41 -
   67.42 -    return suite;
   67.43 -}
   67.44 -
   67.45 -void ucx_test_suite_free(UcxTestSuite* suite) {
   67.46 -    UcxTestList *l = suite->tests;
   67.47 -    while (l != NULL) {
   67.48 -        UcxTestList *e = l;
   67.49 -        l = l->next;
   67.50 -        free(e);
   67.51 -    }
   67.52 -    free(suite);
   67.53 -}
   67.54 -
   67.55 -int ucx_test_register(UcxTestSuite* suite, UcxTest test) {
   67.56 -    if (suite->tests) {
   67.57 -        UcxTestList *newelem = (UcxTestList*) malloc(sizeof(UcxTestList));
   67.58 -        if (newelem) {
   67.59 -            newelem->test = test;
   67.60 -            newelem->next = NULL;
   67.61 -            
   67.62 -            UcxTestList *last = suite->tests;
   67.63 -            while (last->next) {
   67.64 -                last = last->next;
   67.65 -            }
   67.66 -            last->next = newelem;
   67.67 -            
   67.68 -            return EXIT_SUCCESS;
   67.69 -        } else {
   67.70 -            return EXIT_FAILURE;
   67.71 -        }
   67.72 -    } else {
   67.73 -        suite->tests = (UcxTestList*) malloc(sizeof(UcxTestList));
   67.74 -        if (suite->tests) {
   67.75 -            suite->tests->test = test;
   67.76 -            suite->tests->next = NULL;
   67.77 -            
   67.78 -            return EXIT_SUCCESS;
   67.79 -        } else {
   67.80 -            return EXIT_FAILURE;
   67.81 -        }
   67.82 -    }
   67.83 -}
   67.84 -
   67.85 -void ucx_test_run(UcxTestSuite* suite, FILE* output) {
   67.86 -    suite->success = 0;
   67.87 -    suite->failure = 0;
   67.88 -    for (UcxTestList* elem = suite->tests ; elem ; elem = elem->next) {
   67.89 -        elem->test(suite, output);
   67.90 -    }
   67.91 -    fwrite("\nAll test completed.\n", 1, 21, output);
   67.92 -    fprintf(output, "  Total:   %u\n  Success: %u\n  Failure: %u\n",
   67.93 -            suite->success+suite->failure, suite->success, suite->failure);
   67.94 -}
    68.1 --- a/ucx/test.h	Tue Oct 17 15:15:54 2017 +0200
    68.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.3 @@ -1,241 +0,0 @@
    68.4 -/*
    68.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    68.6 - *
    68.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    68.8 - *
    68.9 - * Redistribution and use in source and binary forms, with or without
   68.10 - * modification, are permitted provided that the following conditions are met:
   68.11 - *
   68.12 - *   1. Redistributions of source code must retain the above copyright
   68.13 - *      notice, this list of conditions and the following disclaimer.
   68.14 - *
   68.15 - *   2. Redistributions in binary form must reproduce the above copyright
   68.16 - *      notice, this list of conditions and the following disclaimer in the
   68.17 - *      documentation and/or other materials provided with the distribution.
   68.18 - *
   68.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   68.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   68.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   68.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   68.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   68.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   68.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   68.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   68.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   68.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   68.29 - * POSSIBILITY OF SUCH DAMAGE.
   68.30 - */
   68.31 - 
   68.32 -/**
   68.33 - * @file: test.h
   68.34 - * 
   68.35 - * UCX Test Framework.
   68.36 - * 
   68.37 - * Usage of this test framework:
   68.38 - *
   68.39 - * **** IN HEADER FILE: ****
   68.40 - *
   68.41 - * <pre>
   68.42 - * UCX_TEST(function_name)
   68.43 - * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) // optional
   68.44 - * </pre>
   68.45 - *
   68.46 - * **** IN SOURCE FILE: ****
   68.47 - * <pre>
   68.48 - * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) {
   68.49 - *   // tests with UCX_TEST_ASSERT()
   68.50 - * }
   68.51 - * 
   68.52 - * UCX_TEST(function_name) {
   68.53 - *   // memory allocation and other stuff here
   68.54 - *   #UCX_TEST_BEGIN
   68.55 - *   // tests with UCX_TEST_ASSERT() and/or
   68.56 - *   // calls with UCX_TEST_CALL_SUBROUTINE() here
   68.57 - *   #UCX_TEST_END
   68.58 - *   // cleanup of memory here
   68.59 - * }
   68.60 - * </pre>
   68.61 - *
   68.62 - * <b>Note:</b> if a test fails, a longjump is performed
   68.63 - * back to the #UCX_TEST_BEGIN macro!
   68.64 - * 
   68.65 - * <b>Attention:</b> Do not call own functions within a test, that use
   68.66 - * UCX_TEST_ASSERT() macros and are not defined by using UCX_TEST_SUBROUTINE().
   68.67 - * 
   68.68 - *
   68.69 - * @author Mike Becker
   68.70 - * @author Olaf Wintermann
   68.71 - *
   68.72 - */
   68.73 -
   68.74 -#ifndef UCX_TEST_H
   68.75 -#define	UCX_TEST_H
   68.76 -
   68.77 -#include "ucx.h"
   68.78 -#include <stdio.h>
   68.79 -#include <string.h>
   68.80 -#include <setjmp.h>
   68.81 -
   68.82 -#ifdef	__cplusplus
   68.83 -extern "C" {
   68.84 -#endif
   68.85 -
   68.86 -#ifndef __FUNCTION__
   68.87 -
   68.88 -/**
   68.89 - * Alias for the <code>__func__</code> preprocessor macro.
   68.90 - * Some compilers use <code>__func__</code> and others use __FUNCTION__.
   68.91 - * We use __FUNCTION__ so we define it for those compilers which use
   68.92 - * <code>__func__</code>.
   68.93 - */
   68.94 -#define __FUNCTION__ __func__
   68.95 -#endif
   68.96 -
   68.97 -/** Type for the UcxTestSuite. */
   68.98 -typedef struct UcxTestSuite UcxTestSuite;
   68.99 -
  68.100 -/** Pointer to a test function. */
  68.101 -typedef void(*UcxTest)(UcxTestSuite*,FILE*);
  68.102 -
  68.103 -/** Type for the internal list of test cases. */
  68.104 -typedef struct UcxTestList UcxTestList;
  68.105 -
  68.106 -/** Structure for the internal list of test cases. */
  68.107 -struct UcxTestList {
  68.108 -    
  68.109 -    /** Test case. */
  68.110 -    UcxTest test;
  68.111 -    
  68.112 -    /** Pointer to the next list element. */
  68.113 -    UcxTestList *next;
  68.114 -};
  68.115 -
  68.116 -/**
  68.117 - * A test suite containing multiple test cases.
  68.118 - */
  68.119 -struct UcxTestSuite {
  68.120 -    
  68.121 -    /** The number of successful tests after the suite has been run. */
  68.122 -    unsigned int success;
  68.123 -    
  68.124 -    /** The number of failed tests after the suite has been run. */
  68.125 -    unsigned int failure;
  68.126 -    
  68.127 -    /**
  68.128 -     * Internal list of test cases.
  68.129 -     * Use ucx_test_register() to add tests to this list.
  68.130 -     */
  68.131 -    UcxTestList *tests;
  68.132 -};
  68.133 -
  68.134 -/**
  68.135 - * Creates a new test suite.
  68.136 - * @return a new test suite
  68.137 - */
  68.138 -UcxTestSuite* ucx_test_suite_new();
  68.139 -
  68.140 -/**
  68.141 - * Destroys a test suite.
  68.142 - * @param suite the test suite to destroy
  68.143 - */
  68.144 -void ucx_test_suite_free(UcxTestSuite* suite);
  68.145 -
  68.146 -/**
  68.147 - * Registers a test function with the specified test suite.
  68.148 - * 
  68.149 - * @param suite the suite, the test function shall be added to
  68.150 - * @param test the test function to register
  68.151 - * @return <code>EXIT_SUCCESS</code> on success or
  68.152 - * <code>EXIT_FAILURE</code> on failure
  68.153 - */
  68.154 -int ucx_test_register(UcxTestSuite* suite, UcxTest test);
  68.155 -
  68.156 -/**
  68.157 - * Runs a test suite and writes the test log to the specified stream.
  68.158 - * @param suite the test suite to run
  68.159 - * @param outstream the stream the log shall be written to
  68.160 - */
  68.161 -void ucx_test_run(UcxTestSuite* suite, FILE* outstream);
  68.162 -
  68.163 -/**
  68.164 - * Macro for a #UcxTest function header.
  68.165 - * 
  68.166 - * Use this macro to declare and/or define a #UcxTest function.
  68.167 - * 
  68.168 - * @param name the name of the test function
  68.169 - */
  68.170 -#define UCX_TEST(name) void name(UcxTestSuite* _suite_,FILE *_output_)
  68.171 -
  68.172 -/**
  68.173 - * Marks the begin of a test.
  68.174 - * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>after</b>
  68.175 - * #UCX_TEST_BEGIN.
  68.176 - * 
  68.177 - * @see #UCX_TEST_END
  68.178 - */
  68.179 -#define UCX_TEST_BEGIN fwrite("Running ", 1, 8, _output_);\
  68.180 -        fwrite(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\
  68.181 -        fwrite("... ", 1, 4, _output_);\
  68.182 -        jmp_buf _env_; \
  68.183 -        if (!setjmp(_env_)) {
  68.184 -
  68.185 -/**
  68.186 - * Checks a test assertion.
  68.187 - * If the assertion is correct, the test carries on. If the assertion is not
  68.188 - * correct, the specified message (terminated by a dot and a line break) is
  68.189 - * written to the test suites output stream.
  68.190 - * @param condition the condition to check
  68.191 - * @param message the message that shall be printed out on failure
  68.192 - */
  68.193 -#define UCX_TEST_ASSERT(condition,message) if (!(condition)) { \
  68.194 -        fwrite(message".\n", 1, 2+strlen(message), _output_); \
  68.195 -        _suite_->failure++; \
  68.196 -        longjmp(_env_, 1);\
  68.197 -    }
  68.198 -
  68.199 -/**
  68.200 - * Macro for a test subroutine function header.
  68.201 - * 
  68.202 - * Use this to declare and/or define a subroutine that can be called by using
  68.203 - * UCX_TEST_CALL_SUBROUTINE().
  68.204 - * 
  68.205 - * @param name the name of the subroutine
  68.206 - * @param ... the parameter list
  68.207 - * 
  68.208 - * @see UCX_TEST_CALL_SUBROUTINE()
  68.209 - */
  68.210 -#define UCX_TEST_SUBROUTINE(name,...) void name(UcxTestSuite* _suite_,\
  68.211 -        FILE *_output_, jmp_buf _env_, __VA_ARGS__)
  68.212 -
  68.213 -/**
  68.214 - * Macro for calling a test subroutine.
  68.215 - * 
  68.216 - * Subroutines declared with UCX_TEST_SUBROUTINE() can be called by using this
  68.217 - * macro.
  68.218 - * 
  68.219 - * <b>Note:</b> You may <b>only</b> call subroutines within a #UCX_TEST_BEGIN-
  68.220 - * #UCX_TEST_END-block.
  68.221 - * 
  68.222 - * @param name the name of the subroutine
  68.223 - * @param ... the argument list
  68.224 - * 
  68.225 - * @see UCX_TEST_SUBROUTINE()
  68.226 - */
  68.227 -#define UCX_TEST_CALL_SUBROUTINE(name,...) \
  68.228 -        name(_suite_,_output_,_env_,__VA_ARGS__);
  68.229 -
  68.230 -/**
  68.231 - * Marks the end of a test.
  68.232 - * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>before</b>
  68.233 - * #UCX_TEST_END.
  68.234 - * 
  68.235 - * @see #UCX_TEST_BEGIN
  68.236 - */
  68.237 -#define UCX_TEST_END fwrite("success.\n", 1, 9, _output_); _suite_->success++;}
  68.238 -
  68.239 -#ifdef	__cplusplus
  68.240 -}
  68.241 -#endif
  68.242 -
  68.243 -#endif	/* UCX_TEST_H */
  68.244 -
    69.1 --- a/ucx/ucx.c	Tue Oct 17 15:15:54 2017 +0200
    69.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.3 @@ -1,37 +0,0 @@
    69.4 -/**
    69.5 - * @mainpage UAP Common Extensions
    69.6 - * Library with common and useful functions, macros and data structures.
    69.7 - * <p>
    69.8 - * Latest available source:<br/>
    69.9 - * <a href="https://develop.uap-core.de/hg/ucx">
   69.10 - * https://develop.uap-core.de/hg/ucx</a>
   69.11 - * </p>
   69.12 - * 
   69.13 - * <h2>LICENCE</h2>
   69.14 - * 
   69.15 - * Copyright 2017 Olaf Wintermann. All rights reserved.
   69.16 - *
   69.17 - * Redistribution and use in source and binary forms, with or without
   69.18 - * modification, are permitted provided that the following conditions are met:
   69.19 - *
   69.20 - *   1. Redistributions of source code must retain the above copyright
   69.21 - *      notice, this list of conditions and the following disclaimer.
   69.22 - *
   69.23 - *   2. Redistributions in binary form must reproduce the above copyright
   69.24 - *      notice, this list of conditions and the following disclaimer in the
   69.25 - *      documentation and/or other materials provided with the distribution.
   69.26 - *
   69.27 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   69.28 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   69.29 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   69.30 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   69.31 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   69.32 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   69.33 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   69.34 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   69.35 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   69.36 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   69.37 - * POSSIBILITY OF SUCH DAMAGE.
   69.38 - */
   69.39 -
   69.40 -#include "ucx.h"
    70.1 --- a/ucx/ucx.h	Tue Oct 17 15:15:54 2017 +0200
    70.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.3 @@ -1,145 +0,0 @@
    70.4 -/*
    70.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    70.6 - *
    70.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    70.8 - *
    70.9 - * Redistribution and use in source and binary forms, with or without
   70.10 - * modification, are permitted provided that the following conditions are met:
   70.11 - *
   70.12 - *   1. Redistributions of source code must retain the above copyright
   70.13 - *      notice, this list of conditions and the following disclaimer.
   70.14 - *
   70.15 - *   2. Redistributions in binary form must reproduce the above copyright
   70.16 - *      notice, this list of conditions and the following disclaimer in the
   70.17 - *      documentation and/or other materials provided with the distribution.
   70.18 - *
   70.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   70.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   70.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   70.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   70.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   70.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   70.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   70.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   70.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   70.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   70.29 - * POSSIBILITY OF SUCH DAMAGE.
   70.30 - */
   70.31 -/**
   70.32 - * Main UCX Header providing most common definitions.
   70.33 - * 
   70.34 - * @file   ucx.h
   70.35 - * @author Mike Becker
   70.36 - * @author Olaf Wintermann
   70.37 - */
   70.38 -
   70.39 -#ifndef UCX_H
   70.40 -#define	UCX_H
   70.41 -
   70.42 -/** Major UCX version as integer constant. */
   70.43 -#define UCX_VERSION_MAJOR   0
   70.44 -
   70.45 -/** Minor UCX version as integer constant. */
   70.46 -#define UCX_VERSION_MINOR   12
   70.47 -
   70.48 -#include <stdlib.h>
   70.49 -#include <stdint.h>
   70.50 -
   70.51 -#ifdef _WIN32
   70.52 -#if !(defined __ssize_t_defined || defined _SSIZE_T_)
   70.53 -#include <BaseTsd.h>
   70.54 -typedef SSIZE_T ssize_t;
   70.55 -#define __ssize_t_defined
   70.56 -#define _SSIZE_T_
   70.57 -#endif /* __ssize_t_defined and _SSIZE_T */
   70.58 -#else /* !_WIN32 */
   70.59 -#include <sys/types.h>
   70.60 -#endif /* _WIN32 */
   70.61 -
   70.62 -#ifdef	__cplusplus
   70.63 -#ifndef _Bool
   70.64 -#define _Bool bool
   70.65 -#define restrict
   70.66 -#endif
   70.67 -/** Use C naming even when compiling with C++.  */
   70.68 -#define UCX_EXTERN extern "C"
   70.69 -extern "C" {
   70.70 -#else
   70.71 -/** Pointless in C. */
   70.72 -#define UCX_EXTERN
   70.73 -#endif
   70.74 -    
   70.75 -
   70.76 -/**
   70.77 - * A function pointer to a destructor function.
   70.78 - * @see ucx_mempool_setdestr()
   70.79 - * @see ucx_mempool_regdestr()
   70.80 - */
   70.81 -typedef void(*ucx_destructor)(void*);
   70.82 -
   70.83 -/**
   70.84 - * Function pointer to a compare function.
   70.85 - * 
   70.86 - * The compare function shall take three arguments: the two values that shall be
   70.87 - * compared and optional additional data.
   70.88 - * The function shall then return -1 if the first argument is less than the
   70.89 - * second argument, 1 if the first argument is greater than the second argument
   70.90 - * and 0 if both arguments are equal. If the third argument is
   70.91 - * <code>NULL</code>, it shall be ignored.
   70.92 - */
   70.93 -typedef int(*cmp_func)(const void*,const void*,void*);
   70.94 -
   70.95 -/**
   70.96 - * Function pointer to a distance function.
   70.97 - * 
   70.98 - * The distance function shall take three arguments: the two values for which
   70.99 - * the distance shall be computed and optional additional data.
  70.100 - * The function shall then return the signed distance as integer value.
  70.101 - */
  70.102 -typedef intmax_t(*distance_func)(const void*,const void*,void*);
  70.103 -
  70.104 -/**
  70.105 - * Function pointer to a copy function.
  70.106 - * 
  70.107 - * The copy function shall create a copy of the first argument and may use
  70.108 - * additional data provided by the second argument. If the second argument is
  70.109 - * <code>NULL</code>, it shall be ignored.
  70.110 -
  70.111 - * <b>Attention:</b> if pointers returned by functions of this type may be
  70.112 - * passed to <code>free()</code> depends on the implementation of the
  70.113 - * respective <code>copy_func</code>.
  70.114 - */
  70.115 -typedef void*(*copy_func)(const void*,void*);
  70.116 -
  70.117 -/**
  70.118 - * Function pointer to a write function.
  70.119 - * 
  70.120 - * The signature of the write function shall be compatible to the signature
  70.121 - * of standard <code>fwrite</code>, though it may use arbitrary data types for
  70.122 - * source and destination.
  70.123 - * 
  70.124 - * The arguments shall contain (in ascending order): a pointer to the source,
  70.125 - * the length of one element, the element count and a pointer to the
  70.126 - * destination.
  70.127 - */
  70.128 -typedef size_t(*write_func)(const void*, size_t, size_t, void*);
  70.129 -
  70.130 -/**
  70.131 - * Function pointer to a read function.
  70.132 - * 
  70.133 - * The signature of the read function shall be compatible to the signature
  70.134 - * of standard <code>fread</code>, though it may use arbitrary data types for
  70.135 - * source and destination.
  70.136 - * 
  70.137 - * The arguments shall contain (in ascending order): a pointer to the
  70.138 - * destination, the length of one element, the element count and a pointer to
  70.139 - * the source.
  70.140 - */
  70.141 -typedef size_t(*read_func)(void*, size_t, size_t, void*);
  70.142 -
  70.143 -#ifdef	__cplusplus
  70.144 -}
  70.145 -#endif
  70.146 -
  70.147 -#endif	/* UCX_H */
  70.148 -
    71.1 --- a/ucx/utils.c	Tue Oct 17 15:15:54 2017 +0200
    71.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.3 @@ -1,259 +0,0 @@
    71.4 -/*
    71.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    71.6 - *
    71.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    71.8 - *
    71.9 - * Redistribution and use in source and binary forms, with or without
   71.10 - * modification, are permitted provided that the following conditions are met:
   71.11 - *
   71.12 - *   1. Redistributions of source code must retain the above copyright
   71.13 - *      notice, this list of conditions and the following disclaimer.
   71.14 - *
   71.15 - *   2. Redistributions in binary form must reproduce the above copyright
   71.16 - *      notice, this list of conditions and the following disclaimer in the
   71.17 - *      documentation and/or other materials provided with the distribution.
   71.18 - *
   71.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   71.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   71.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   71.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   71.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   71.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   71.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   71.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   71.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   71.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   71.29 - * POSSIBILITY OF SUCH DAMAGE.
   71.30 - */
   71.31 -
   71.32 -#include "utils.h"
   71.33 -#include <math.h>
   71.34 -#include <stdio.h>
   71.35 -#include <limits.h>
   71.36 -#include <errno.h>
   71.37 -
   71.38 -/* COPY FUCNTIONS */
   71.39 -void* ucx_strcpy(const void* s, void* data) {
   71.40 -    const char *str = (const char*) s;
   71.41 -    size_t n = 1+strlen(str);
   71.42 -    char *cpy = (char*) malloc(n);
   71.43 -    memcpy(cpy, str, n);
   71.44 -    return cpy;
   71.45 -}
   71.46 -
   71.47 -void* ucx_memcpy(const void* m, void* n) {
   71.48 -    size_t k = *((size_t*)n);
   71.49 -    void *cpy = malloc(k);
   71.50 -    memcpy(cpy, m, k);
   71.51 -    return cpy;
   71.52 -}
   71.53 -
   71.54 -size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc,
   71.55 -        write_func writefnc, char* buf, size_t bufsize, size_t n) {
   71.56 -    if(n == 0 || bufsize == 0) {
   71.57 -        return 0;
   71.58 -    }
   71.59 -    
   71.60 -    char *lbuf;    
   71.61 -    size_t ncp = 0;
   71.62 -    
   71.63 -    if(buf) {
   71.64 -        lbuf = buf;
   71.65 -    } else {
   71.66 -        lbuf = (char*)malloc(bufsize);
   71.67 -        if(lbuf == NULL) {
   71.68 -            return 0;
   71.69 -        }
   71.70 -    }
   71.71 -    
   71.72 -    size_t r;
   71.73 -    size_t rn = bufsize > n ? n : bufsize;
   71.74 -    while((r = readfnc(lbuf, 1, rn, src)) != 0) {
   71.75 -        r = writefnc(lbuf, 1, r, dest);
   71.76 -        ncp += r;
   71.77 -        n -= r;
   71.78 -        rn = bufsize > n ? n : bufsize;
   71.79 -        if(r == 0 || n == 0) {
   71.80 -            break;
   71.81 -        }
   71.82 -    }
   71.83 -    
   71.84 -    if (lbuf != buf) {
   71.85 -        free(lbuf);
   71.86 -    }
   71.87 -    
   71.88 -    return ncp;
   71.89 -}
   71.90 -
   71.91 -/* COMPARE FUNCTIONS */
   71.92 -
   71.93 -int ucx_strcmp(const void *s1, const void *s2, void *data) {
   71.94 -    return strcmp((const char*)s1, (const char*)s2);
   71.95 -}
   71.96 -
   71.97 -int ucx_strncmp(const void *s1, const void *s2, void *n) {
   71.98 -    return strncmp((const char*)s1, (const char*)s2, *((size_t*) n));
   71.99 -}
  71.100 -
  71.101 -int ucx_intcmp(const void *i1, const void *i2, void *data) {
  71.102 -   int a = *((const int*) i1);
  71.103 -   int b = *((const int*) i2);
  71.104 -   if (a == b) {
  71.105 -       return 0;
  71.106 -   } else {
  71.107 -       return a < b ? -1 : 1;
  71.108 -   }
  71.109 -}
  71.110 -
  71.111 -int ucx_floatcmp(const void *f1, const void *f2, void *epsilon) {
  71.112 -   float a = *((const float*) f1);
  71.113 -   float b = *((const float*) f2);
  71.114 -   float e = !epsilon ? 1e-6f : *((float*)epsilon);
  71.115 -   if (fabsf(a - b) < e) {
  71.116 -       return 0;
  71.117 -   } else {
  71.118 -       return a < b ? -1 : 1;
  71.119 -   }
  71.120 -}
  71.121 -
  71.122 -int ucx_doublecmp(const void *d1, const void *d2, void *epsilon) {
  71.123 -   double a = *((const double*) d1);
  71.124 -   double b = *((const double*) d2);
  71.125 -   double e = !epsilon ? 1e-14 : *((double*)epsilon);
  71.126 -   if (fabs(a - b) < e) {
  71.127 -       return 0;
  71.128 -   } else {
  71.129 -       return a < b ? -1 : 1;
  71.130 -   }
  71.131 -}
  71.132 -
  71.133 -int ucx_ptrcmp(const void *ptr1, const void *ptr2, void *data) {
  71.134 -    const intptr_t p1 = (const intptr_t) ptr1;
  71.135 -    const intptr_t p2 = (const intptr_t) ptr2;
  71.136 -    if (p1 == p2) {
  71.137 -        return 0;
  71.138 -    } else {
  71.139 -        return p1  < p2 ? -1 : 1;
  71.140 -    }
  71.141 -}
  71.142 -
  71.143 -int ucx_memcmp(const void *ptr1, const void *ptr2, void *n) {
  71.144 -    return memcmp(ptr1, ptr2, *((size_t*)n));
  71.145 -}
  71.146 -
  71.147 -/* PRINTF FUNCTIONS */
  71.148 -
  71.149 -#ifdef va_copy
  71.150 -#define UCX_PRINTF_BUFSIZE 256
  71.151 -#else
  71.152 -#pragma message("WARNING: C99 va_copy macro not supported by this platform" \
  71.153 -                " - limiting ucx_*printf to 2 KiB")
  71.154 -#define UCX_PRINTF_BUFSIZE 0x800
  71.155 -#endif
  71.156 -
  71.157 -int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) {
  71.158 -    int ret;
  71.159 -    va_list ap;
  71.160 -    va_start(ap, fmt);
  71.161 -    ret = ucx_vfprintf(stream, wfc, fmt, ap);
  71.162 -    va_end(ap);
  71.163 -    return ret;
  71.164 -}
  71.165 -
  71.166 -int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) {
  71.167 -    char buf[UCX_PRINTF_BUFSIZE];
  71.168 -#ifdef va_copy
  71.169 -    va_list ap2;
  71.170 -    va_copy(ap2, ap);
  71.171 -    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  71.172 -    if (ret < 0) {
  71.173 -        return ret;
  71.174 -    } else if (ret < UCX_PRINTF_BUFSIZE) {
  71.175 -        return (int)wfc(buf, 1, ret, stream);
  71.176 -    } else {
  71.177 -        if (ret == INT_MAX) {
  71.178 -            errno = ENOMEM;
  71.179 -            return -1;
  71.180 -        }
  71.181 -        
  71.182 -        int len = ret + 1;
  71.183 -        char *newbuf = (char*)malloc(len);
  71.184 -        if (!newbuf) {
  71.185 -            return -1;
  71.186 -        }
  71.187 -        
  71.188 -        ret = vsnprintf(newbuf, len, fmt, ap2);
  71.189 -        if (ret > 0) {
  71.190 -            ret = (int)wfc(newbuf, 1, ret, stream);
  71.191 -        }
  71.192 -        free(newbuf);
  71.193 -    }
  71.194 -    return ret;
  71.195 -#else
  71.196 -    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  71.197 -    if (ret < 0) {
  71.198 -        return ret;
  71.199 -    } else if (ret < UCX_PRINTF_BUFSIZE) {
  71.200 -        return (int)wfc(buf, 1, ret, stream);
  71.201 -    } else {
  71.202 -        errno = ENOMEM;
  71.203 -        return -1;
  71.204 -    }
  71.205 -#endif
  71.206 -}
  71.207 -
  71.208 -sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) {
  71.209 -    va_list ap;
  71.210 -    sstr_t ret;
  71.211 -    va_start(ap, fmt);
  71.212 -    ret = ucx_vasprintf(allocator, fmt, ap);
  71.213 -    va_end(ap);
  71.214 -    return ret;
  71.215 -}
  71.216 -
  71.217 -sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) {
  71.218 -    sstr_t s;
  71.219 -    s.ptr = NULL;
  71.220 -    s.length = 0;
  71.221 -    char buf[UCX_PRINTF_BUFSIZE];
  71.222 -#ifdef va_copy
  71.223 -    va_list ap2;
  71.224 -    va_copy(ap2, ap);
  71.225 -    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  71.226 -    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
  71.227 -        s.ptr = (char*)almalloc(a, ret + 1);
  71.228 -        if (s.ptr) {
  71.229 -            s.length = (size_t)ret;
  71.230 -            memcpy(s.ptr, buf, ret);
  71.231 -            s.ptr[s.length] = '\0';
  71.232 -        }
  71.233 -    } else if (ret == INT_MAX) {
  71.234 -        errno = ENOMEM;
  71.235 -    } else  {
  71.236 -        int len = ret + 1;
  71.237 -        s.ptr = (char*)almalloc(a, len);
  71.238 -        if (s.ptr) {
  71.239 -            ret = vsnprintf(s.ptr, len, fmt, ap2);
  71.240 -            if (ret < 0) {
  71.241 -                free(s.ptr);
  71.242 -                s.ptr = NULL;
  71.243 -            } else {
  71.244 -                s.length = (size_t)ret;
  71.245 -            }
  71.246 -        }
  71.247 -    }
  71.248 -#else
  71.249 -    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
  71.250 -    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
  71.251 -        s.ptr = (char*)almalloc(a, ret + 1);
  71.252 -        if (s.ptr) {
  71.253 -            s.length = (size_t)ret;
  71.254 -            memcpy(s.ptr, buf, ret);
  71.255 -            s.ptr[s.length] = '\0';
  71.256 -        }
  71.257 -    } else {
  71.258 -        errno = ENOMEM;
  71.259 -    }
  71.260 -#endif
  71.261 -    return s;
  71.262 -}
    72.1 --- a/ucx/utils.h	Tue Oct 17 15:15:54 2017 +0200
    72.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.3 @@ -1,281 +0,0 @@
    72.4 -/*
    72.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    72.6 - *
    72.7 - * Copyright 2017 Olaf Wintermann. All rights reserved.
    72.8 - *
    72.9 - * Redistribution and use in source and binary forms, with or without
   72.10 - * modification, are permitted provided that the following conditions are met:
   72.11 - *
   72.12 - *   1. Redistributions of source code must retain the above copyright
   72.13 - *      notice, this list of conditions and the following disclaimer.
   72.14 - *
   72.15 - *   2. Redistributions in binary form must reproduce the above copyright
   72.16 - *      notice, this list of conditions and the following disclaimer in the
   72.17 - *      documentation and/or other materials provided with the distribution.
   72.18 - *
   72.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   72.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   72.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   72.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   72.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   72.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   72.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   72.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   72.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   72.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   72.29 - * POSSIBILITY OF SUCH DAMAGE.
   72.30 - */
   72.31 -
   72.32 -/**
   72.33 - * @file utils.h
   72.34 - * 
   72.35 - * Compare, copy and printf functions.
   72.36 - * 
   72.37 - * @author Mike Becker
   72.38 - * @author Olaf Wintermann
   72.39 - */
   72.40 -
   72.41 -#ifndef UCX_UTILS_H
   72.42 -#define UCX_UTILS_H
   72.43 -
   72.44 -#ifdef __cplusplus
   72.45 -extern "C" {
   72.46 -#endif
   72.47 -
   72.48 -#include "ucx.h"
   72.49 -#include "string.h"
   72.50 -#include "allocator.h"
   72.51 -#include <inttypes.h>
   72.52 -#include <string.h>
   72.53 -#include <stdarg.h>
   72.54 -
   72.55 -/**
   72.56 - * Default buffer size for ucx_stream_copy() and ucx_stream_ncopy().
   72.57 - */
   72.58 -#define UCX_STREAM_COPY_BUFSIZE 4096
   72.59 -
   72.60 -/**
   72.61 - * Copies a string.
   72.62 - * @param s the string to copy
   72.63 - * @param data omitted
   72.64 - * @return a pointer to a copy of s1 that can be passed to free(void*)
   72.65 - */
   72.66 -void *ucx_strcpy(const void *s, void *data);
   72.67 -
   72.68 -/**
   72.69 - * Copies a memory area.
   72.70 - * @param m a pointer to the memory area
   72.71 - * @param n a pointer to the size_t containing the size of the memory area
   72.72 - * @return a pointer to a copy of the specified memory area that can
   72.73 - * be passed to free(void*)
   72.74 - */
   72.75 -void *ucx_memcpy(const void *m, void *n);
   72.76 -
   72.77 -
   72.78 -/**
   72.79 - * Reads data from a stream and writes it to another stream.
   72.80 - * 
   72.81 - * @param src the source stream
   72.82 - * @param dest the destination stream
   72.83 - * @param rfnc the read function
   72.84 - * @param wfnc the write function
   72.85 - * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer
   72.86 - * shall be implicitly created on the heap
   72.87 - * @param bufsize the size of the copy buffer - if <code>NULL</code> was
   72.88 - * provided for <code>buf</code>, this is the size of the buffer that shall be
   72.89 - * implicitly created
   72.90 - * @param n the maximum number of bytes that shall be copied
   72.91 - * @return the total number of bytes copied
   72.92 -  */
   72.93 -size_t ucx_stream_bncopy(void *src, void *dest, read_func rfnc, write_func wfnc,
   72.94 -        char* buf, size_t bufsize, size_t n);
   72.95 -
   72.96 -/**
   72.97 - * Shorthand for an unbounded ucx_stream_bncopy call using a default buffer.
   72.98 - * 
   72.99 - * @param src the source stream
  72.100 - * @param dest the destination stream
  72.101 - * @param rfnc the read function
  72.102 - * @param wfnc the write function
  72.103 - * @return total number of bytes copied
  72.104 - * 
  72.105 - * @see #UCX_STREAM_COPY_BUFSIZE
  72.106 - */
  72.107 -#define ucx_stream_copy(src,dest,rfnc,wfnc) ucx_stream_bncopy(\
  72.108 -        src, dest, (read_func)rfnc, (write_func)wfnc, \
  72.109 -        NULL, UCX_STREAM_COPY_BUFSIZE, (size_t)-1)
  72.110 -
  72.111 -/**
  72.112 - * Shorthand for ucx_stream_bncopy using a default copy buffer.
  72.113 - * 
  72.114 - * @param src the source stream
  72.115 - * @param dest the destination stream
  72.116 - * @param rfnc the read function
  72.117 - * @param wfnc the write function
  72.118 - * @param n maximum number of bytes that shall be copied
  72.119 - * @return total number of bytes copied
  72.120 - */
  72.121 -#define ucx_stream_ncopy(src,dest,rfnc,wfnc, n) ucx_stream_bncopy(\
  72.122 -        src, dest, (read_func)rfnc, (write_func)wfnc, \
  72.123 -        NULL, UCX_STREAM_COPY_BUFSIZE, n)
  72.124 -
  72.125 -/**
  72.126 - * Shorthand for an unbounded ucx_stream_bncopy call using the specified buffer.
  72.127 - * 
  72.128 - * @param src the source stream
  72.129 - * @param dest the destination stream
  72.130 - * @param rfnc the read function
  72.131 - * @param wfnc the write function
  72.132 - * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer
  72.133 - * shall be implicitly created on the heap
  72.134 - * @param bufsize the size of the copy buffer - if <code>NULL</code> was
  72.135 - * provided for <code>buf</code>, this is the size of the buffer that shall be
  72.136 - * implicitly created
  72.137 - * @return total number of bytes copied
  72.138 - */
  72.139 -#define ucx_stream_bcopy(src,dest,rfnc,wfnc, buf, bufsize) ucx_stream_bncopy(\
  72.140 -        src, dest, (read_func)rfnc, (write_func)wfnc, \
  72.141 -        buf, bufsize, (size_t)-1)
  72.142 -
  72.143 -/**
  72.144 - * Wraps the strcmp function.
  72.145 - * @param s1 string one
  72.146 - * @param s2 string two
  72.147 - * @param data omitted
  72.148 - * @return the result of strcmp(s1, s2)
  72.149 - */
  72.150 -int ucx_strcmp(const void *s1, const void *s2, void *data);
  72.151 -
  72.152 -/**
  72.153 - * Wraps the strncmp function.
  72.154 - * @param s1 string one
  72.155 - * @param s2 string two
  72.156 - * @param n a pointer to the size_t containing the third strncmp parameter
  72.157 - * @return the result of strncmp(s1, s2, *n)
  72.158 - */
  72.159 -int ucx_strncmp(const void *s1, const void *s2, void *n);
  72.160 -
  72.161 -/**
  72.162 - * Compares two integers of type int.
  72.163 - * @param i1 pointer to integer one
  72.164 - * @param i2 pointer to integer two
  72.165 - * @param data omitted
  72.166 - * @return -1, if *i1 is less than *i2, 0 if both are equal,
  72.167 - * 1 if *i1 is greater than *i2
  72.168 - */
  72.169 -int ucx_intcmp(const void *i1, const void *i2, void *data);
  72.170 -
  72.171 -/**
  72.172 - * Compares two real numbers of type float.
  72.173 - * @param f1 pointer to float one
  72.174 - * @param f2 pointer to float two
  72.175 - * @param data if provided: a pointer to precision (default: 1e-6f)
  72.176 - * @return -1, if *f1 is less than *f2, 0 if both are equal,
  72.177 - * 1 if *f1 is greater than *f2
  72.178 - */
  72.179 -
  72.180 -int ucx_floatcmp(const void *f1, const void *f2, void *data);
  72.181 -
  72.182 -/**
  72.183 - * Compares two real numbers of type double.
  72.184 - * @param d1 pointer to double one
  72.185 - * @param d2 pointer to double two
  72.186 - * @param data if provided: a pointer to precision (default: 1e-14)
  72.187 - * @return -1, if *d1 is less than *d2, 0 if both are equal,
  72.188 - * 1 if *d1 is greater than *d2
  72.189 - */
  72.190 -int ucx_doublecmp(const void *d1, const void *d2, void *data);
  72.191 -
  72.192 -/**
  72.193 - * Compares two pointers.
  72.194 - * @param ptr1 pointer one
  72.195 - * @param ptr2 pointer two
  72.196 - * @param data omitted
  72.197 - * @return -1 if ptr1 is less than ptr2, 0 if both are equal,
  72.198 - * 1 if ptr1 is greater than ptr2
  72.199 - */
  72.200 -int ucx_ptrcmp(const void *ptr1, const void *ptr2, void *data);
  72.201 -
  72.202 -/**
  72.203 - * Compares two memory areas.
  72.204 - * @param ptr1 pointer one
  72.205 - * @param ptr2 pointer two
  72.206 - * @param n a pointer to the size_t containing the third parameter for memcmp
  72.207 - * @return the result of memcmp(ptr1, ptr2, *n)
  72.208 - */
  72.209 -int ucx_memcmp(const void *ptr1, const void *ptr2, void *n);
  72.210 -
  72.211 -/**
  72.212 - * A <code>printf()</code> like function which writes the output to a stream by
  72.213 - * using a write_func().
  72.214 - * @param stream the stream the data is written to
  72.215 - * @param wfc the write function
  72.216 - * @param fmt format string
  72.217 - * @param ... additional arguments
  72.218 - * @return the total number of bytes written
  72.219 - */
  72.220 -int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...);
  72.221 -
  72.222 -/**
  72.223 - * <code>va_list</code> version of ucx_fprintf().
  72.224 - * @param stream the stream the data is written to
  72.225 - * @param wfc the write function
  72.226 - * @param fmt format string
  72.227 - * @param ap argument list
  72.228 - * @return the total number of bytes written
  72.229 - * @see ucx_fprintf()
  72.230 - */
  72.231 -int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap);
  72.232 -
  72.233 -/**
  72.234 - * A <code>printf()</code> like function which allocates space for a sstr_t
  72.235 - * the result is written to.
  72.236 - * 
  72.237 - * <b>Attention</b>: The sstr_t data is allocated with the allocators
  72.238 - * ucx_allocator_malloc() function. So it is implementation dependent, if
  72.239 - * the returned sstr_t.ptr pointer must be passed to the allocators
  72.240 - * ucx_allocator_free() function manually.
  72.241 - * 
  72.242 - * <b>Note</b>: The sstr_t.ptr of the return value will <i>always</i> be
  72.243 - * <code>NULL</code>-terminated.
  72.244 - * 
  72.245 - * @param allocator the UcxAllocator used for allocating the result sstr_t
  72.246 - * @param fmt format string
  72.247 - * @param ... additional arguments
  72.248 - * @return a sstr_t containing the formatted string
  72.249 - */
  72.250 -sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...);
  72.251 -
  72.252 -/**
  72.253 - * <code>va_list</code> version of ucx_asprintf().
  72.254 - * 
  72.255 - * @param allocator the UcxAllocator used for allocating the result sstr_t
  72.256 - * @param fmt format string
  72.257 - * @param ap argument list
  72.258 - * @return a sstr_t containing the formatted string
  72.259 - * @see ucx_asprintf()
  72.260 - */
  72.261 -sstr_t ucx_vasprintf(UcxAllocator *allocator, const char *fmt, va_list ap);
  72.262 -
  72.263 -/** Shortcut for ucx_asprintf() with default allocator. */
  72.264 -#define ucx_sprintf(...) \
  72.265 -    ucx_asprintf(ucx_default_allocator(), __VA_ARGS__)
  72.266 -
  72.267 -/**
  72.268 - * A <code>printf()</code> like function which writes the output to a
  72.269 - * UcxBuffer.
  72.270 - * 
  72.271 - * @param buffer the buffer the data is written to
  72.272 - * @param ... format string and additional arguments
  72.273 - * @return the total number of bytes written
  72.274 - * @see ucx_fprintf()
  72.275 - */
  72.276 -#define ucx_bprintf(buffer, ...) ucx_fprintf((UcxBuffer*)buffer, \
  72.277 -        (write_func)ucx_buffer_write, __VA_ARGS__)
  72.278 -
  72.279 -#ifdef __cplusplus
  72.280 -}
  72.281 -#endif
  72.282 -
  72.283 -#endif /* UCX_UTILS_H */
  72.284 -

mercurial