added stack implementation + added g++ config and added some fixes for C++

Mon, 28 Jul 2014 14:36:25 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 28 Jul 2014 14:36:25 +0200
changeset 185
a48428642b4e
parent 184
5c0990c95f74
child 186
05559c99010d

added stack implementation + added g++ config and added some fixes for C++

g++.mk file | annotate | diff | comparison | revisions
test/Makefile file | annotate | diff | comparison | revisions
test/buffer_tests.c file | annotate | diff | comparison | revisions
test/logging_tests.c file | annotate | diff | comparison | revisions
test/main.c file | annotate | diff | comparison | revisions
test/stack_tests.c file | annotate | diff | comparison | revisions
test/stack_tests.h file | annotate | diff | comparison | revisions
ucx/stack.c file | annotate | diff | comparison | revisions
ucx/stack.h file | annotate | diff | comparison | revisions
ucx/string.c file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/g++.mk	Mon Jul 28 14:36:25 2014 +0200
     1.3 @@ -0,0 +1,46 @@
     1.4 +#
     1.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 +#
     1.7 +# Copyright 2014 Olaf Wintermann. All rights reserved.
     1.8 +#
     1.9 +# Redistribution and use in source and binary forms, with or without
    1.10 +# modification, are permitted provided that the following conditions are met:
    1.11 +#
    1.12 +#   1. Redistributions of source code must retain the above copyright
    1.13 +#      notice, this list of conditions and the following disclaimer.
    1.14 +#
    1.15 +#   2. Redistributions in binary form must reproduce the above copyright
    1.16 +#      notice, this list of conditions and the following disclaimer in the
    1.17 +#      documentation and/or other materials provided with the distribution.
    1.18 +#
    1.19 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    1.20 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.21 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.22 +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    1.23 +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.24 +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.25 +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    1.26 +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    1.27 +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.28 +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    1.29 +# POSSIBILITY OF SUCH DAMAGE.
    1.30 +#
    1.31 +
    1.32 +CC    = g++
    1.33 +LD    = g++
    1.34 +AR    = ar
    1.35 +RM    = rm
    1.36 +MKDIR = mkdir
    1.37 +
    1.38 +CFLAGS     = -O2 -fstrict-aliasing -fPIC
    1.39 +CFLAGS_D   = -g -fstrict-aliasing -Wall -Wno-variadic-macros -pedantic -fPIC
    1.40 +LDFLAGS    = 
    1.41 +SOLDFLAGS  = -shared
    1.42 +ARFLAGS    = -r
    1.43 +RMFLAGS    = -f -R
    1.44 +MKDIRFLAGS = -p
    1.45 +
    1.46 +OBJ_EXT = .o
    1.47 +SO_EXT  = .so
    1.48 +LIB_EXT = .a
    1.49 +APP_EXT =
     2.1 --- a/test/Makefile	Mon Jul 21 13:18:32 2014 +0200
     2.2 +++ b/test/Makefile	Mon Jul 28 14:36:25 2014 +0200
     2.3 @@ -32,6 +32,7 @@
     2.4  SRC += allocator_tests.c
     2.5  SRC += list_tests.c
     2.6  SRC += mpool_tests.c
     2.7 +SRC += stack_tests.c
     2.8  SRC += map_tests.c
     2.9  SRC += prop_tests.c
    2.10  SRC += string_tests.c
     3.1 --- a/test/buffer_tests.c	Mon Jul 21 13:18:32 2014 +0200
     3.2 +++ b/test/buffer_tests.c	Mon Jul 28 14:36:25 2014 +0200
     3.3 @@ -70,7 +70,7 @@
     3.4  }
     3.5  
     3.6  UCX_TEST(test_ucx_buffer_eof) {
     3.7 -    char *test = "0123456789ABCDEF";
     3.8 +    char *test = (char*)"0123456789ABCDEF";
     3.9      UcxBuffer *b = ucx_buffer_new(test, 16, UCX_BUFFER_DEFAULT);
    3.10      UCX_TEST_BEGIN
    3.11      b->pos = 9; b->size = 10;
     4.1 --- a/test/logging_tests.c	Mon Jul 21 13:18:32 2014 +0200
     4.2 +++ b/test/logging_tests.c	Mon Jul 28 14:36:25 2014 +0200
     4.3 @@ -50,16 +50,16 @@
     4.4          "incorrect number of registered log levels");
     4.5  
     4.6      int level = UCX_LOGGER_ERROR;
     4.7 -    UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level),
     4.8 +    UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level),
     4.9          "[ERROR]") == 0, "invalid error level");
    4.10      level = UCX_LOGGER_WARN;
    4.11 -    UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level),
    4.12 +    UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level),
    4.13          "[WARNING]") == 0, "invalid warning level");
    4.14      level = UCX_LOGGER_INFO;
    4.15 -    UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level),
    4.16 +    UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level),
    4.17          "[INFO]") == 0, "invalid info level");
    4.18      level = UCX_LOGGER_TRACE;
    4.19 -    UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level),
    4.20 +    UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level),
    4.21          "[TRACE]") == 0, "invalid trace level");
    4.22  
    4.23      UCX_TEST_END
    4.24 @@ -75,7 +75,7 @@
    4.25  
    4.26      UcxLogger *logger = ucx_logger_new(stream,
    4.27              UCX_LOGGER_INFO, UCX_LOGGER_SOURCE | UCX_LOGGER_LEVEL);
    4.28 -    logger->dateformat = "%F:";
    4.29 +    logger->dateformat = (char*) "%F:";
    4.30      
    4.31      UCX_TEST_BEGIN
    4.32      const uint line1 = __LINE__; ucx_logger_info(logger, "allright");
    4.33 @@ -92,7 +92,7 @@
    4.34      size_t r = fread(buffer, 1, 100, stream);
    4.35      
    4.36      const size_t expected_length = 87;
    4.37 -    char expected[expected_length+1];
    4.38 +    char expected[88];
    4.39      snprintf(expected, expected_length+1,
    4.40          "[INFO] logging_tests.c:%u - allright\n"
    4.41          "[ERROR] %slogging_tests.c:%u - error 42!\n", line1, timestr, line2);
     5.1 --- a/test/main.c	Mon Jul 21 13:18:32 2014 +0200
     5.2 +++ b/test/main.c	Mon Jul 28 14:36:25 2014 +0200
     5.3 @@ -38,6 +38,7 @@
     5.4  #include "list_tests.h"
     5.5  #include "string_tests.h"
     5.6  #include "mpool_tests.h"
     5.7 +#include "stack_tests.h"
     5.8  #include "map_tests.h"
     5.9  #include "prop_tests.h"
    5.10  #include "buffer_tests.h"
    5.11 @@ -156,6 +157,14 @@
    5.12          ucx_test_register(suite, test_ucx_mempool_set_destr);
    5.13          ucx_test_register(suite, test_ucx_mempool_reg_destr);
    5.14          ucx_test_register(suite, test_ucx_mempool_realloc);
    5.15 +        
    5.16 +        /* UcxStack Tests */
    5.17 +        ucx_test_register(suite, test_ucx_stack_init);
    5.18 +        ucx_test_register(suite, test_ucx_stack_malloc);
    5.19 +        ucx_test_register(suite, test_ucx_stack_calloc);
    5.20 +        ucx_test_register(suite, test_ucx_stack_free);
    5.21 +        ucx_test_register(suite, test_ucx_stack_realloc);
    5.22 +        ucx_test_register(suite, test_ucx_stack_pop);
    5.23  
    5.24          /* UcxMap Tests */
    5.25          ucx_test_register(suite, test_ucx_map_new);
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/stack_tests.c	Mon Jul 28 14:36:25 2014 +0200
     6.3 @@ -0,0 +1,209 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2014 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 "stack_tests.h"
    6.33 +
    6.34 +#define test_ucx_stack_before \
    6.35 +    char space[100]; \
    6.36 +    UcxStack stack; \
    6.37 +    ucx_stack_init(&stack, space, 100) \
    6.38 +
    6.39 +UCX_TEST(test_ucx_stack_init) {
    6.40 +    
    6.41 +    test_ucx_stack_before;
    6.42 +    
    6.43 +    UCX_TEST_BEGIN
    6.44 +    
    6.45 +    UCX_TEST_ASSERT(
    6.46 +        stack.allocator.malloc == (ucx_allocator_malloc) ucx_stack_malloc &&
    6.47 +        stack.allocator.calloc == (ucx_allocator_calloc) ucx_stack_calloc &&
    6.48 +        stack.allocator.realloc == (ucx_allocator_realloc) ucx_stack_realloc &&
    6.49 +        stack.allocator.free == (ucx_allocator_free) ucx_stack_free &&
    6.50 +        stack.allocator.pool == &stack,
    6.51 +        "allocator not properly set");
    6.52 +    
    6.53 +    UCX_TEST_ASSERT(!stack.top && stack.space == space
    6.54 +        && stack.size == 100 - 100 % sizeof(void*),
    6.55 +        "struct fields not properly set");
    6.56 +    
    6.57 +    UCX_TEST_END
    6.58 +}
    6.59 +
    6.60 +UCX_TEST(test_ucx_stack_malloc) {
    6.61 +
    6.62 +    test_ucx_stack_before;
    6.63 +    
    6.64 +    const size_t metasize = sizeof(struct ucx_stack_metadata);
    6.65 +    
    6.66 +    
    6.67 +    char* first = (char*) ucx_stack_malloc(&stack, 30);
    6.68 +    char* second = (char*) ucx_stack_malloc(&stack, 30);
    6.69 +    char* full = (char*) ucx_stack_malloc(&stack, 30);
    6.70 +    
    6.71 +    memcpy(first,  "012345678901234567890123456789", 30);
    6.72 +    memcpy(second, "abcdefghijklmnopqrstuvwxyzABCD", 30);
    6.73 +    
    6.74 +    UCX_TEST_BEGIN
    6.75 +    
    6.76 +    UCX_TEST_ASSERT(!memcmp(space + metasize,
    6.77 +        "012345678901234567890123456789", 30), "first element corrupted");
    6.78 +    UCX_TEST_ASSERT(!memcmp(space + 32+2*metasize,
    6.79 +        "abcdefghijklmnopqrstuvwxyzABCD", 30), "first element corrupted");
    6.80 +    
    6.81 +    UCX_TEST_ASSERT(!full, "stack can be overflowed");
    6.82 +    UCX_TEST_ASSERT(stack.top == space + 32 + 2*metasize, "wrong top pointer");
    6.83 +
    6.84 +    if (3*metasize < 32) {
    6.85 +        UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 32-3*metasize,
    6.86 +            "wrong remaining available memory");
    6.87 +    } else {
    6.88 +        UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 0,
    6.89 +            "wrong remaining available memory");
    6.90 +    }
    6.91 +
    6.92 +    UCX_TEST_END
    6.93 +}
    6.94 +
    6.95 +UCX_TEST(test_ucx_stack_calloc) {
    6.96 +    
    6.97 +    test_ucx_stack_before;
    6.98 +
    6.99 +    char zeros[100];
   6.100 +    memset(zeros, 0, 100);
   6.101 +    memset(space, 32, 100);
   6.102 +    ucx_stack_calloc(&stack, 4, sizeof(int));
   6.103 +    
   6.104 +    UCX_TEST_BEGIN
   6.105 +    
   6.106 +    UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata),
   6.107 +        zeros, 4*sizeof(int)), "memory not nulled");
   6.108 +    UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata)
   6.109 +        +4*sizeof(int), "          ", 10), "too much memory nulled");
   6.110 +        
   6.111 +    UCX_TEST_END
   6.112 +}
   6.113 +
   6.114 +UCX_TEST(test_ucx_stack_free) {
   6.115 +    
   6.116 +    test_ucx_stack_before;
   6.117 +    
   6.118 +    void *fst = ucx_stack_malloc(&stack, 10);
   6.119 +    void *snd = ucx_stack_malloc(&stack, 10);
   6.120 +    void *thrd = ucx_stack_malloc(&stack, 10);
   6.121 +    
   6.122 +    UCX_TEST_BEGIN
   6.123 +    
   6.124 +    UCX_TEST_ASSERT(stack.top == thrd, "wrong stack");
   6.125 +    UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == snd,
   6.126 +        "wrong thrd prev pointer before free");
   6.127 +    
   6.128 +    ucx_stack_free(&stack, snd);
   6.129 +    
   6.130 +    UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == fst,
   6.131 +        "wrong thrd prev pointer after freeing snd");
   6.132 +    UCX_TEST_ASSERT(stack.top == thrd, "wrong top after freeing snd");
   6.133 +    
   6.134 +    ucx_stack_free(&stack, thrd);
   6.135 +
   6.136 +    UCX_TEST_ASSERT(stack.top == fst, "wrong top after freeing thrd");
   6.137 +    
   6.138 +    UCX_TEST_END
   6.139 +}
   6.140 +
   6.141 +UCX_TEST(test_ucx_stack_realloc) {
   6.142 +    
   6.143 +    test_ucx_stack_before;
   6.144 +    
   6.145 +    void *fst = ucx_stack_malloc(&stack, 10);
   6.146 +    void *snd = ucx_stack_malloc(&stack, 10);
   6.147 +    
   6.148 +    UCX_TEST_BEGIN
   6.149 +    
   6.150 +    void *nfst = ucx_stack_realloc(&stack, fst, 16);
   6.151 +    UCX_TEST_ASSERT(nfst == fst, "unnecessary move on reallocation");
   6.152 +    UCX_TEST_ASSERT(((struct ucx_stack_metadata*)fst - 1)->size == 16,
   6.153 +        "wrong size after reallocation");
   6.154 +    
   6.155 +    void *nsnd = ucx_stack_realloc(&stack, snd, 30);
   6.156 +    UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top reallocation");
   6.157 +    UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 30,
   6.158 +        "wrong size after top reallocation");
   6.159 +    
   6.160 +    nsnd = ucx_stack_realloc(&stack, snd, 5);
   6.161 +    UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top shrink");
   6.162 +    UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 5,
   6.163 +        "wrong size after top shrink");
   6.164 +    UCX_TEST_ASSERT(ucx_stack_avail(&stack) ==
   6.165 +        72-3*sizeof(struct ucx_stack_metadata), "wrong size after top shrink");
   6.166 +    
   6.167 +    nfst = ucx_stack_realloc(&stack, fst, 24);
   6.168 +    UCX_TEST_ASSERT(nfst != fst, "missing move on huge reallocation");
   6.169 +    UCX_TEST_ASSERT(stack.top == nfst, "wrong top after huge reallocation");
   6.170 +    UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 24,
   6.171 +        "wrong size after huge reallocation");
   6.172 +    UCX_TEST_ASSERT(!((struct ucx_stack_metadata*)snd - 1)->prev,
   6.173 +        "element not freed after huge reallocation");
   6.174 +    
   6.175 +    UCX_TEST_END
   6.176 +}
   6.177 +
   6.178 +UCX_TEST(test_ucx_stack_pop) {
   6.179 +    
   6.180 +    test_ucx_stack_before;
   6.181 +    memset(space, 32, 100);
   6.182 +    
   6.183 +    void *fst = ucx_stack_malloc(&stack, 10);
   6.184 +    void *snd = ucx_stack_malloc(&stack, 10);
   6.185 +    ucx_stack_malloc(&stack, 10);
   6.186 +    
   6.187 +    char buf[16];
   6.188 +    
   6.189 +    UCX_TEST_BEGIN
   6.190 +    
   6.191 +    memset(buf, '0', 16);
   6.192 +    ucx_stack_pop(&stack, buf);
   6.193 +    UCX_TEST_ASSERT(memcmp(buf, "          000000", 16) == 0,
   6.194 +        "popped wrong content");
   6.195 +    UCX_TEST_ASSERT(stack.top == snd, "wrong top after pop");
   6.196 +    
   6.197 +    memset(buf, '0', 16);
   6.198 +    ucx_stack_popn(&stack, buf, 5);
   6.199 +    UCX_TEST_ASSERT(memcmp(buf, "     00000000000", 16) == 0,
   6.200 +        "n-popped wrong content");
   6.201 +    UCX_TEST_ASSERT(stack.top == fst, "wrong top after pop");
   6.202 +    
   6.203 +    ucx_stack_pop(&stack, buf);
   6.204 +    UCX_TEST_ASSERT(!stack.top, "top not NULL after last pop");
   6.205 +    
   6.206 +    memset(buf, '0', 16);
   6.207 +    ucx_stack_pop(&stack, buf);
   6.208 +    UCX_TEST_ASSERT(memcmp(buf, "0000000000000000", 16) == 0,
   6.209 +        "content not unchanged after empty pop");
   6.210 +    
   6.211 +    UCX_TEST_END
   6.212 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/stack_tests.h	Mon Jul 28 14:36:25 2014 +0200
     7.3 @@ -0,0 +1,51 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 2014 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 +#ifndef STACK_TESTS_H
    7.33 +#define	STACK_TESTS_H
    7.34 +
    7.35 +#include "ucx/test.h"
    7.36 +#include "ucx/stack.h"
    7.37 +
    7.38 +#ifdef	__cplusplus
    7.39 +extern "C" {
    7.40 +#endif
    7.41 +
    7.42 +UCX_TEST(test_ucx_stack_init);
    7.43 +UCX_TEST(test_ucx_stack_malloc);
    7.44 +UCX_TEST(test_ucx_stack_calloc);
    7.45 +UCX_TEST(test_ucx_stack_free);
    7.46 +UCX_TEST(test_ucx_stack_realloc);
    7.47 +UCX_TEST(test_ucx_stack_pop);
    7.48 +
    7.49 +#ifdef	__cplusplus
    7.50 +}
    7.51 +#endif
    7.52 +
    7.53 +#endif	/* STACK_TESTS_H */
    7.54 +
     8.1 --- a/ucx/stack.c	Mon Jul 21 13:18:32 2014 +0200
     8.2 +++ b/ucx/stack.c	Mon Jul 28 14:36:25 2014 +0200
     8.3 @@ -29,35 +29,43 @@
     8.4  #include "stack.h"
     8.5  #include <string.h>
     8.6  
     8.7 -UcxStack ucx_stack_new(char* space, size_t size) {
     8.8 -    UcxStack stack;
     8.9 -    stack.size = size;
    8.10 -    stack.space = stack.top = space;
    8.11 +static size_t ucx_stack_align(size_t n) {
    8.12 +    int align = n % sizeof(void*);
    8.13 +    if (align) {
    8.14 +        n += sizeof(void*) - align;
    8.15 +    }
    8.16 +    return n;
    8.17 +}
    8.18 +
    8.19 +void ucx_stack_init(UcxStack *stack, char* space, size_t size) {
    8.20 +    stack->size = size - size % sizeof(void*);
    8.21 +    stack->space = space;
    8.22 +    stack->top = NULL;
    8.23      
    8.24 -    UcxAllocator alloc;
    8.25 -    alloc.pool = &stack;
    8.26 -    alloc.malloc = (ucx_allocator_malloc) ucx_stack_malloc;
    8.27 -    alloc.calloc = (ucx_allocator_calloc) ucx_stack_calloc;
    8.28 -    alloc.realloc = (ucx_allocator_realloc) ucx_stack_realloc;
    8.29 -    alloc.free = (ucx_allocator_free) ucx_stack_free;
    8.30 -    
    8.31 -    stack.allocator = alloc;
    8.32 -    
    8.33 -    return stack;
    8.34 +    stack->allocator.pool = stack;
    8.35 +    stack->allocator.malloc = (ucx_allocator_malloc) ucx_stack_malloc;
    8.36 +    stack->allocator.calloc = (ucx_allocator_calloc) ucx_stack_calloc;
    8.37 +    stack->allocator.realloc = (ucx_allocator_realloc) ucx_stack_realloc;
    8.38 +    stack->allocator.free = (ucx_allocator_free) ucx_stack_free;
    8.39  }
    8.40  
    8.41  void *ucx_stack_malloc(UcxStack *stack, size_t n) {
    8.42 -    n += n % sizeof(void*);
    8.43  
    8.44 -    if (stack->top + n + sizeof(size_t) > stack->space + stack->size) {
    8.45 +    if (ucx_stack_avail(stack) < ucx_stack_align(n)) {
    8.46          return NULL;
    8.47      } else {
    8.48 -        void *ptr = stack->top;
    8.49 +        char *prev = stack->top;
    8.50 +        if (stack->top) {
    8.51 +            stack->top += ucx_stack_align(ucx_stack_topsize(stack));
    8.52 +        } else {
    8.53 +            stack->top = stack->space;
    8.54 +        }
    8.55          
    8.56 -        *((size_t*) (stack->top + n)) = n;
    8.57 -        stack->top += n + sizeof(size_t);
    8.58 +        ((struct ucx_stack_metadata*)stack->top)->prev = prev;
    8.59 +        ((struct ucx_stack_metadata*)stack->top)->size = n;
    8.60 +        stack->top += sizeof(struct ucx_stack_metadata);
    8.61          
    8.62 -        return ptr;
    8.63 +        return stack->top;
    8.64      }
    8.65  }
    8.66  
    8.67 @@ -68,41 +76,68 @@
    8.68  }
    8.69  
    8.70  void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) {
    8.71 -    if (ptr == stack->top - sizeof(size_t) - *((size_t*) stack->top - 1)) {
    8.72 -
    8.73 -        stack->top = (char*)ptr + n;
    8.74 -        *((size_t*)stack->top) = n;
    8.75 -        stack->top += sizeof(size_t);
    8.76 -        
    8.77 -        return ptr;
    8.78 +    if (ptr == stack->top) {
    8.79 +        if (stack->size - (stack->top - stack->space) < ucx_stack_align(n)) {
    8.80 +            return NULL;
    8.81 +        } else {
    8.82 +            ((struct ucx_stack_metadata*)stack->top - 1)->size = n;
    8.83 +            return ptr;
    8.84 +        }
    8.85      } else {
    8.86 -        size_t* sptr = (size_t*) (((char*) ptr)-sizeof(size_t));
    8.87 -        if (*sptr < n) {
    8.88 +        if (ucx_stack_align(((struct ucx_stack_metadata*)ptr - 1)->size) <
    8.89 +                ucx_stack_align(n)) {
    8.90              void *nptr = ucx_stack_malloc(stack, n);
    8.91              if (nptr) {
    8.92 -                memcpy(nptr, ptr, *sptr);
    8.93 +                memcpy(nptr, ptr, n);
    8.94                  ucx_stack_free(stack, ptr);
    8.95 +                
    8.96                  return nptr;
    8.97              } else {
    8.98                  return NULL;
    8.99              }
   8.100          } else {
   8.101 -            *sptr = n;
   8.102 +            ((struct ucx_stack_metadata*)ptr - 1)->size = n;
   8.103              return ptr;
   8.104          }
   8.105      }
   8.106  }
   8.107  
   8.108  void ucx_stack_free(UcxStack *stack, void *ptr) {
   8.109 -    if (ptr == stack->top+sizeof(size_t)) {
   8.110 -        
   8.111 +    if (ptr == stack->top) {
   8.112 +        stack->top = ((struct ucx_stack_metadata*) stack->top - 1)->prev;
   8.113      } else {
   8.114 -        
   8.115 +        struct ucx_stack_metadata *next = (struct ucx_stack_metadata*)(
   8.116 +            (char*)ptr +
   8.117 +            ucx_stack_align(((struct ucx_stack_metadata*) ptr - 1)->size)
   8.118 +        );
   8.119 +        next->prev = ((struct ucx_stack_metadata*) ptr - 1)->prev;
   8.120      }
   8.121  }
   8.122  
   8.123 -void ucx_stack_pop(UcxStack *stack, void *dest) {
   8.124 +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) {
   8.125 +    if (ucx_stack_empty(stack)) {
   8.126 +        return;
   8.127 +    }
   8.128 +    
   8.129 +    size_t len = ucx_stack_topsize(stack);
   8.130 +    if (len > n) {
   8.131 +        len = n;
   8.132 +    }
   8.133 +    
   8.134 +    memcpy(dest, stack->top, len);
   8.135 +    
   8.136 +    ucx_stack_free(stack, stack->top);
   8.137  }
   8.138  
   8.139 -void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) {
   8.140 +size_t ucx_stack_avail(UcxStack *stack) {
   8.141 +    size_t avail = ((stack->top ? (stack->size
   8.142 +                    - (stack->top - stack->space)
   8.143 +                    - ucx_stack_align(ucx_stack_topsize(stack)))
   8.144 +                    : stack->size));
   8.145 +    
   8.146 +    if (avail > sizeof(struct ucx_stack_metadata)) {
   8.147 +        return avail - sizeof(struct ucx_stack_metadata);
   8.148 +    } else {
   8.149 +        return 0;
   8.150 +    }
   8.151  }
     9.1 --- a/ucx/stack.h	Mon Jul 21 13:18:32 2014 +0200
     9.2 +++ b/ucx/stack.h	Mon Jul 28 14:36:25 2014 +0200
     9.3 @@ -39,7 +39,7 @@
     9.4  #define	UCX_STACK_H
     9.5  
     9.6  #include "ucx.h"
     9.7 -#include <stddef.h>
     9.8 +#include <stdint.h>
     9.9  #include "allocator.h"
    9.10  
    9.11  #ifdef	__cplusplus
    9.12 @@ -65,13 +65,27 @@
    9.13  } UcxStack;
    9.14  
    9.15  /**
    9.16 - * Wraps memory in a new UcxStack structure.
    9.17 + * Metadata for each UCX stack element.
    9.18 + */
    9.19 +struct ucx_stack_metadata {
    9.20 +    /**
    9.21 +     * Location of the previous element (<code>NULL</code> if this is the first)
    9.22 +     */
    9.23 +    char *prev;
    9.24 +    
    9.25 +    /** Size of this element */
    9.26 +    size_t size;
    9.27 +};
    9.28 +
    9.29 +/**
    9.30 + * Initializes UcxStack structure with memory.
    9.31   * 
    9.32 + * @param stack a pointer to an uninitialized stack structure
    9.33   * @param space the memory area that shall be managed
    9.34   * @param size size of the memory area
    9.35   * @return a new UcxStack structure
    9.36   */
    9.37 -UcxStack ucx_stack_new(char* space, size_t size);
    9.38 +void ucx_stack_init(UcxStack *stack, char* space, size_t size);
    9.39  
    9.40  /**
    9.41   * Allocates stack memory.
    9.42 @@ -149,7 +163,8 @@
    9.43   * @param stack a pointer to the stack
    9.44   * @return the size of the top most element
    9.45   */
    9.46 -#define ucx_stack_topsize(stack) (*(((size_t*)stack->top - 1))
    9.47 +#define ucx_stack_topsize(stack) ((stack)->top ? ((struct ucx_stack_metadata*)\
    9.48 +                                  (stack)->top - 1)->size : 0)
    9.49  
    9.50  /**
    9.51   * Removes the top most element from the stack and copies the content to <code>
    9.52 @@ -164,7 +179,7 @@
    9.53   * @see ucx_stack_free
    9.54   * @see ucx_stack_popn
    9.55   */
    9.56 -void ucx_stack_pop(UcxStack *stack, void *dest);
    9.57 +#define ucx_stack_pop(stack, dest) ucx_stack_popn(stack, dest, SIZE_MAX)
    9.58  
    9.59  /**
    9.60   * Removes the top most element from the stack and copies the content to <code>
    9.61 @@ -186,8 +201,28 @@
    9.62   * @param stack a pointer to the stack
    9.63   * @return the remaining available memory
    9.64   */
    9.65 -#define ucx_stack_avail(stack) ((stack->size)  - (s.top - s.space)\
    9.66 -                                - sizeof(size_t))
    9.67 +size_t ucx_stack_avail(UcxStack *stack);
    9.68 +
    9.69 +/**
    9.70 + * Checks, if the stack is empty.
    9.71 + * 
    9.72 + * @param stack a pointer to the stack
    9.73 + * @return nonzero, if the stack is empty, zero otherwise
    9.74 + */
    9.75 +#define ucx_stack_empty(stack) (!(stack)->top)
    9.76 +
    9.77 +/**
    9.78 + * Computes a recommended size for the stack memory area. Note, that
    9.79 + * reallocations have not been taken into account, so you might need to reserve
    9.80 + * twice as much memory to allow many reallocations.
    9.81 + * 
    9.82 + * @param size the approximate payload
    9.83 + * @param elems the approximate count of element allocations
    9.84 + * @return a recommended size for the stack space based on the information
    9.85 + * provided
    9.86 + */
    9.87 +#define ucx_stack_dim(size, elems) (size+sizeof(struct ucx_stack_metadata) * \
    9.88 +                                    (elems + 1))
    9.89  
    9.90  
    9.91  #ifdef	__cplusplus
    10.1 --- a/ucx/string.c	Mon Jul 21 13:18:32 2014 +0200
    10.2 +++ b/ucx/string.c	Mon Jul 28 14:36:25 2014 +0200
    10.3 @@ -74,7 +74,7 @@
    10.4          return str;
    10.5      }
    10.6      
    10.7 -    sstr_t *strings = calloc(count, sizeof(sstr_t));
    10.8 +    sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t));
    10.9      if(!strings) {
   10.10          return str;
   10.11      }
   10.12 @@ -90,7 +90,7 @@
   10.13      }
   10.14      
   10.15      // create new string
   10.16 -    str.ptr = almalloc(a, strlen + 1);
   10.17 +    str.ptr = (char*) almalloc(a, strlen + 1);
   10.18      str.length = strlen;
   10.19      if(!str.ptr) {
   10.20          free(strings);

mercurial