# HG changeset patch # User Mike Becker # Date 1406550985 -7200 # Node ID a48428642b4e8e7afe087ab363ddee1a96e8fa44 # Parent 5c0990c95f740f290caec7a0d383e428fb83be54 added stack implementation + added g++ config and added some fixes for C++ diff -r 5c0990c95f74 -r a48428642b4e g++.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/g++.mk Mon Jul 28 14:36:25 2014 +0200 @@ -0,0 +1,46 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2014 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +CC = g++ +LD = g++ +AR = ar +RM = rm +MKDIR = mkdir + +CFLAGS = -O2 -fstrict-aliasing -fPIC +CFLAGS_D = -g -fstrict-aliasing -Wall -Wno-variadic-macros -pedantic -fPIC +LDFLAGS = +SOLDFLAGS = -shared +ARFLAGS = -r +RMFLAGS = -f -R +MKDIRFLAGS = -p + +OBJ_EXT = .o +SO_EXT = .so +LIB_EXT = .a +APP_EXT = diff -r 5c0990c95f74 -r a48428642b4e test/Makefile --- a/test/Makefile Mon Jul 21 13:18:32 2014 +0200 +++ b/test/Makefile Mon Jul 28 14:36:25 2014 +0200 @@ -32,6 +32,7 @@ SRC += allocator_tests.c SRC += list_tests.c SRC += mpool_tests.c +SRC += stack_tests.c SRC += map_tests.c SRC += prop_tests.c SRC += string_tests.c diff -r 5c0990c95f74 -r a48428642b4e test/buffer_tests.c --- a/test/buffer_tests.c Mon Jul 21 13:18:32 2014 +0200 +++ b/test/buffer_tests.c Mon Jul 28 14:36:25 2014 +0200 @@ -70,7 +70,7 @@ } UCX_TEST(test_ucx_buffer_eof) { - char *test = "0123456789ABCDEF"; + char *test = (char*)"0123456789ABCDEF"; UcxBuffer *b = ucx_buffer_new(test, 16, UCX_BUFFER_DEFAULT); UCX_TEST_BEGIN b->pos = 9; b->size = 10; diff -r 5c0990c95f74 -r a48428642b4e test/logging_tests.c --- a/test/logging_tests.c Mon Jul 21 13:18:32 2014 +0200 +++ b/test/logging_tests.c Mon Jul 28 14:36:25 2014 +0200 @@ -50,16 +50,16 @@ "incorrect number of registered log levels"); int level = UCX_LOGGER_ERROR; - UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level), + UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level), "[ERROR]") == 0, "invalid error level"); level = UCX_LOGGER_WARN; - UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level), + UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level), "[WARNING]") == 0, "invalid warning level"); level = UCX_LOGGER_INFO; - UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level), + UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level), "[INFO]") == 0, "invalid info level"); level = UCX_LOGGER_TRACE; - UCX_TEST_ASSERT(strcmp(ucx_map_int_get(logger->levels, level), + UCX_TEST_ASSERT(strcmp((char*)ucx_map_int_get(logger->levels, level), "[TRACE]") == 0, "invalid trace level"); UCX_TEST_END @@ -75,7 +75,7 @@ UcxLogger *logger = ucx_logger_new(stream, UCX_LOGGER_INFO, UCX_LOGGER_SOURCE | UCX_LOGGER_LEVEL); - logger->dateformat = "%F:"; + logger->dateformat = (char*) "%F:"; UCX_TEST_BEGIN const uint line1 = __LINE__; ucx_logger_info(logger, "allright"); @@ -92,7 +92,7 @@ size_t r = fread(buffer, 1, 100, stream); const size_t expected_length = 87; - char expected[expected_length+1]; + char expected[88]; snprintf(expected, expected_length+1, "[INFO] logging_tests.c:%u - allright\n" "[ERROR] %slogging_tests.c:%u - error 42!\n", line1, timestr, line2); diff -r 5c0990c95f74 -r a48428642b4e test/main.c --- a/test/main.c Mon Jul 21 13:18:32 2014 +0200 +++ b/test/main.c Mon Jul 28 14:36:25 2014 +0200 @@ -38,6 +38,7 @@ #include "list_tests.h" #include "string_tests.h" #include "mpool_tests.h" +#include "stack_tests.h" #include "map_tests.h" #include "prop_tests.h" #include "buffer_tests.h" @@ -156,6 +157,14 @@ ucx_test_register(suite, test_ucx_mempool_set_destr); ucx_test_register(suite, test_ucx_mempool_reg_destr); ucx_test_register(suite, test_ucx_mempool_realloc); + + /* UcxStack Tests */ + ucx_test_register(suite, test_ucx_stack_init); + ucx_test_register(suite, test_ucx_stack_malloc); + ucx_test_register(suite, test_ucx_stack_calloc); + ucx_test_register(suite, test_ucx_stack_free); + ucx_test_register(suite, test_ucx_stack_realloc); + ucx_test_register(suite, test_ucx_stack_pop); /* UcxMap Tests */ ucx_test_register(suite, test_ucx_map_new); diff -r 5c0990c95f74 -r a48428642b4e test/stack_tests.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/stack_tests.c Mon Jul 28 14:36:25 2014 +0200 @@ -0,0 +1,209 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stack_tests.h" + +#define test_ucx_stack_before \ + char space[100]; \ + UcxStack stack; \ + ucx_stack_init(&stack, space, 100) \ + +UCX_TEST(test_ucx_stack_init) { + + test_ucx_stack_before; + + UCX_TEST_BEGIN + + UCX_TEST_ASSERT( + stack.allocator.malloc == (ucx_allocator_malloc) ucx_stack_malloc && + stack.allocator.calloc == (ucx_allocator_calloc) ucx_stack_calloc && + stack.allocator.realloc == (ucx_allocator_realloc) ucx_stack_realloc && + stack.allocator.free == (ucx_allocator_free) ucx_stack_free && + stack.allocator.pool == &stack, + "allocator not properly set"); + + UCX_TEST_ASSERT(!stack.top && stack.space == space + && stack.size == 100 - 100 % sizeof(void*), + "struct fields not properly set"); + + UCX_TEST_END +} + +UCX_TEST(test_ucx_stack_malloc) { + + test_ucx_stack_before; + + const size_t metasize = sizeof(struct ucx_stack_metadata); + + + char* first = (char*) ucx_stack_malloc(&stack, 30); + char* second = (char*) ucx_stack_malloc(&stack, 30); + char* full = (char*) ucx_stack_malloc(&stack, 30); + + memcpy(first, "012345678901234567890123456789", 30); + memcpy(second, "abcdefghijklmnopqrstuvwxyzABCD", 30); + + UCX_TEST_BEGIN + + UCX_TEST_ASSERT(!memcmp(space + metasize, + "012345678901234567890123456789", 30), "first element corrupted"); + UCX_TEST_ASSERT(!memcmp(space + 32+2*metasize, + "abcdefghijklmnopqrstuvwxyzABCD", 30), "first element corrupted"); + + UCX_TEST_ASSERT(!full, "stack can be overflowed"); + UCX_TEST_ASSERT(stack.top == space + 32 + 2*metasize, "wrong top pointer"); + + if (3*metasize < 32) { + UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 32-3*metasize, + "wrong remaining available memory"); + } else { + UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 0, + "wrong remaining available memory"); + } + + UCX_TEST_END +} + +UCX_TEST(test_ucx_stack_calloc) { + + test_ucx_stack_before; + + char zeros[100]; + memset(zeros, 0, 100); + memset(space, 32, 100); + ucx_stack_calloc(&stack, 4, sizeof(int)); + + UCX_TEST_BEGIN + + UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata), + zeros, 4*sizeof(int)), "memory not nulled"); + UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata) + +4*sizeof(int), " ", 10), "too much memory nulled"); + + UCX_TEST_END +} + +UCX_TEST(test_ucx_stack_free) { + + test_ucx_stack_before; + + void *fst = ucx_stack_malloc(&stack, 10); + void *snd = ucx_stack_malloc(&stack, 10); + void *thrd = ucx_stack_malloc(&stack, 10); + + UCX_TEST_BEGIN + + UCX_TEST_ASSERT(stack.top == thrd, "wrong stack"); + UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == snd, + "wrong thrd prev pointer before free"); + + ucx_stack_free(&stack, snd); + + UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == fst, + "wrong thrd prev pointer after freeing snd"); + UCX_TEST_ASSERT(stack.top == thrd, "wrong top after freeing snd"); + + ucx_stack_free(&stack, thrd); + + UCX_TEST_ASSERT(stack.top == fst, "wrong top after freeing thrd"); + + UCX_TEST_END +} + +UCX_TEST(test_ucx_stack_realloc) { + + test_ucx_stack_before; + + void *fst = ucx_stack_malloc(&stack, 10); + void *snd = ucx_stack_malloc(&stack, 10); + + UCX_TEST_BEGIN + + void *nfst = ucx_stack_realloc(&stack, fst, 16); + UCX_TEST_ASSERT(nfst == fst, "unnecessary move on reallocation"); + UCX_TEST_ASSERT(((struct ucx_stack_metadata*)fst - 1)->size == 16, + "wrong size after reallocation"); + + void *nsnd = ucx_stack_realloc(&stack, snd, 30); + UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top reallocation"); + UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 30, + "wrong size after top reallocation"); + + nsnd = ucx_stack_realloc(&stack, snd, 5); + UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top shrink"); + UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 5, + "wrong size after top shrink"); + UCX_TEST_ASSERT(ucx_stack_avail(&stack) == + 72-3*sizeof(struct ucx_stack_metadata), "wrong size after top shrink"); + + nfst = ucx_stack_realloc(&stack, fst, 24); + UCX_TEST_ASSERT(nfst != fst, "missing move on huge reallocation"); + UCX_TEST_ASSERT(stack.top == nfst, "wrong top after huge reallocation"); + UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 24, + "wrong size after huge reallocation"); + UCX_TEST_ASSERT(!((struct ucx_stack_metadata*)snd - 1)->prev, + "element not freed after huge reallocation"); + + UCX_TEST_END +} + +UCX_TEST(test_ucx_stack_pop) { + + test_ucx_stack_before; + memset(space, 32, 100); + + void *fst = ucx_stack_malloc(&stack, 10); + void *snd = ucx_stack_malloc(&stack, 10); + ucx_stack_malloc(&stack, 10); + + char buf[16]; + + UCX_TEST_BEGIN + + memset(buf, '0', 16); + ucx_stack_pop(&stack, buf); + UCX_TEST_ASSERT(memcmp(buf, " 000000", 16) == 0, + "popped wrong content"); + UCX_TEST_ASSERT(stack.top == snd, "wrong top after pop"); + + memset(buf, '0', 16); + ucx_stack_popn(&stack, buf, 5); + UCX_TEST_ASSERT(memcmp(buf, " 00000000000", 16) == 0, + "n-popped wrong content"); + UCX_TEST_ASSERT(stack.top == fst, "wrong top after pop"); + + ucx_stack_pop(&stack, buf); + UCX_TEST_ASSERT(!stack.top, "top not NULL after last pop"); + + memset(buf, '0', 16); + ucx_stack_pop(&stack, buf); + UCX_TEST_ASSERT(memcmp(buf, "0000000000000000", 16) == 0, + "content not unchanged after empty pop"); + + UCX_TEST_END +} diff -r 5c0990c95f74 -r a48428642b4e test/stack_tests.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/stack_tests.h Mon Jul 28 14:36:25 2014 +0200 @@ -0,0 +1,51 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef STACK_TESTS_H +#define STACK_TESTS_H + +#include "ucx/test.h" +#include "ucx/stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +UCX_TEST(test_ucx_stack_init); +UCX_TEST(test_ucx_stack_malloc); +UCX_TEST(test_ucx_stack_calloc); +UCX_TEST(test_ucx_stack_free); +UCX_TEST(test_ucx_stack_realloc); +UCX_TEST(test_ucx_stack_pop); + +#ifdef __cplusplus +} +#endif + +#endif /* STACK_TESTS_H */ + diff -r 5c0990c95f74 -r a48428642b4e ucx/stack.c --- a/ucx/stack.c Mon Jul 21 13:18:32 2014 +0200 +++ b/ucx/stack.c Mon Jul 28 14:36:25 2014 +0200 @@ -29,35 +29,43 @@ #include "stack.h" #include -UcxStack ucx_stack_new(char* space, size_t size) { - UcxStack stack; - stack.size = size; - stack.space = stack.top = space; +static size_t ucx_stack_align(size_t n) { + int align = n % sizeof(void*); + if (align) { + n += sizeof(void*) - align; + } + return n; +} + +void ucx_stack_init(UcxStack *stack, char* space, size_t size) { + stack->size = size - size % sizeof(void*); + stack->space = space; + stack->top = NULL; - UcxAllocator alloc; - alloc.pool = &stack; - alloc.malloc = (ucx_allocator_malloc) ucx_stack_malloc; - alloc.calloc = (ucx_allocator_calloc) ucx_stack_calloc; - alloc.realloc = (ucx_allocator_realloc) ucx_stack_realloc; - alloc.free = (ucx_allocator_free) ucx_stack_free; - - stack.allocator = alloc; - - return stack; + stack->allocator.pool = stack; + stack->allocator.malloc = (ucx_allocator_malloc) ucx_stack_malloc; + stack->allocator.calloc = (ucx_allocator_calloc) ucx_stack_calloc; + stack->allocator.realloc = (ucx_allocator_realloc) ucx_stack_realloc; + stack->allocator.free = (ucx_allocator_free) ucx_stack_free; } void *ucx_stack_malloc(UcxStack *stack, size_t n) { - n += n % sizeof(void*); - if (stack->top + n + sizeof(size_t) > stack->space + stack->size) { + if (ucx_stack_avail(stack) < ucx_stack_align(n)) { return NULL; } else { - void *ptr = stack->top; + char *prev = stack->top; + if (stack->top) { + stack->top += ucx_stack_align(ucx_stack_topsize(stack)); + } else { + stack->top = stack->space; + } - *((size_t*) (stack->top + n)) = n; - stack->top += n + sizeof(size_t); + ((struct ucx_stack_metadata*)stack->top)->prev = prev; + ((struct ucx_stack_metadata*)stack->top)->size = n; + stack->top += sizeof(struct ucx_stack_metadata); - return ptr; + return stack->top; } } @@ -68,41 +76,68 @@ } void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) { - if (ptr == stack->top - sizeof(size_t) - *((size_t*) stack->top - 1)) { - - stack->top = (char*)ptr + n; - *((size_t*)stack->top) = n; - stack->top += sizeof(size_t); - - return ptr; + if (ptr == stack->top) { + if (stack->size - (stack->top - stack->space) < ucx_stack_align(n)) { + return NULL; + } else { + ((struct ucx_stack_metadata*)stack->top - 1)->size = n; + return ptr; + } } else { - size_t* sptr = (size_t*) (((char*) ptr)-sizeof(size_t)); - if (*sptr < n) { + if (ucx_stack_align(((struct ucx_stack_metadata*)ptr - 1)->size) < + ucx_stack_align(n)) { void *nptr = ucx_stack_malloc(stack, n); if (nptr) { - memcpy(nptr, ptr, *sptr); + memcpy(nptr, ptr, n); ucx_stack_free(stack, ptr); + return nptr; } else { return NULL; } } else { - *sptr = n; + ((struct ucx_stack_metadata*)ptr - 1)->size = n; return ptr; } } } void ucx_stack_free(UcxStack *stack, void *ptr) { - if (ptr == stack->top+sizeof(size_t)) { - + if (ptr == stack->top) { + stack->top = ((struct ucx_stack_metadata*) stack->top - 1)->prev; } else { - + struct ucx_stack_metadata *next = (struct ucx_stack_metadata*)( + (char*)ptr + + ucx_stack_align(((struct ucx_stack_metadata*) ptr - 1)->size) + ); + next->prev = ((struct ucx_stack_metadata*) ptr - 1)->prev; } } -void ucx_stack_pop(UcxStack *stack, void *dest) { +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) { + if (ucx_stack_empty(stack)) { + return; + } + + size_t len = ucx_stack_topsize(stack); + if (len > n) { + len = n; + } + + memcpy(dest, stack->top, len); + + ucx_stack_free(stack, stack->top); } -void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) { +size_t ucx_stack_avail(UcxStack *stack) { + size_t avail = ((stack->top ? (stack->size + - (stack->top - stack->space) + - ucx_stack_align(ucx_stack_topsize(stack))) + : stack->size)); + + if (avail > sizeof(struct ucx_stack_metadata)) { + return avail - sizeof(struct ucx_stack_metadata); + } else { + return 0; + } } diff -r 5c0990c95f74 -r a48428642b4e ucx/stack.h --- a/ucx/stack.h Mon Jul 21 13:18:32 2014 +0200 +++ b/ucx/stack.h Mon Jul 28 14:36:25 2014 +0200 @@ -39,7 +39,7 @@ #define UCX_STACK_H #include "ucx.h" -#include +#include #include "allocator.h" #ifdef __cplusplus @@ -65,13 +65,27 @@ } UcxStack; /** - * Wraps memory in a new UcxStack structure. + * Metadata for each UCX stack element. + */ +struct ucx_stack_metadata { + /** + * Location of the previous element (NULL if this is the first) + */ + char *prev; + + /** Size of this element */ + size_t size; +}; + +/** + * Initializes UcxStack structure with memory. * + * @param stack a pointer to an uninitialized stack structure * @param space the memory area that shall be managed * @param size size of the memory area * @return a new UcxStack structure */ -UcxStack ucx_stack_new(char* space, size_t size); +void ucx_stack_init(UcxStack *stack, char* space, size_t size); /** * Allocates stack memory. @@ -149,7 +163,8 @@ * @param stack a pointer to the stack * @return the size of the top most element */ -#define ucx_stack_topsize(stack) (*(((size_t*)stack->top - 1)) +#define ucx_stack_topsize(stack) ((stack)->top ? ((struct ucx_stack_metadata*)\ + (stack)->top - 1)->size : 0) /** * Removes the top most element from the stack and copies the content to @@ -164,7 +179,7 @@ * @see ucx_stack_free * @see ucx_stack_popn */ -void ucx_stack_pop(UcxStack *stack, void *dest); +#define ucx_stack_pop(stack, dest) ucx_stack_popn(stack, dest, SIZE_MAX) /** * Removes the top most element from the stack and copies the content to @@ -186,8 +201,28 @@ * @param stack a pointer to the stack * @return the remaining available memory */ -#define ucx_stack_avail(stack) ((stack->size) - (s.top - s.space)\ - - sizeof(size_t)) +size_t ucx_stack_avail(UcxStack *stack); + +/** + * Checks, if the stack is empty. + * + * @param stack a pointer to the stack + * @return nonzero, if the stack is empty, zero otherwise + */ +#define ucx_stack_empty(stack) (!(stack)->top) + +/** + * Computes a recommended size for the stack memory area. Note, that + * reallocations have not been taken into account, so you might need to reserve + * twice as much memory to allow many reallocations. + * + * @param size the approximate payload + * @param elems the approximate count of element allocations + * @return a recommended size for the stack space based on the information + * provided + */ +#define ucx_stack_dim(size, elems) (size+sizeof(struct ucx_stack_metadata) * \ + (elems + 1)) #ifdef __cplusplus diff -r 5c0990c95f74 -r a48428642b4e ucx/string.c --- a/ucx/string.c Mon Jul 21 13:18:32 2014 +0200 +++ b/ucx/string.c Mon Jul 28 14:36:25 2014 +0200 @@ -74,7 +74,7 @@ return str; } - sstr_t *strings = calloc(count, sizeof(sstr_t)); + sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t)); if(!strings) { return str; } @@ -90,7 +90,7 @@ } // create new string - str.ptr = almalloc(a, strlen + 1); + str.ptr = (char*) almalloc(a, strlen + 1); str.length = strlen; if(!str.ptr) { free(strings);