Tue, 17 Oct 2017 16:15:41 +0200
changes source directory structure in preperation for autotools rollout
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>&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>&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 -