Mon, 28 Jul 2014 14:36:25 +0200
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);