Mon, 14 Jul 2014 16:54:10 +0200
merged sstrcat function
ucx/Makefile | 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 |
--- a/test/main.c Mon Jul 14 13:20:03 2014 +0200 +++ b/test/main.c Mon Jul 14 16:54:10 2014 +0200 @@ -121,6 +121,7 @@ ucx_test_register(suite, test_sstr_len); ucx_test_register(suite, test_sstrcmp); ucx_test_register(suite, test_sstrcasecmp); + ucx_test_register(suite, test_sstrcat); ucx_test_register(suite, test_sstrchr_sstrrchr); ucx_test_register(suite, test_sstrsplit); ucx_test_register(suite, test_sstrtrim);
--- a/test/string_tests.c Mon Jul 14 13:20:03 2014 +0200 +++ b/test/string_tests.c Mon Jul 14 16:54:10 2014 +0200 @@ -54,6 +54,7 @@ UCX_TEST_END } + UCX_TEST(test_sstrchr_sstrrchr) { sstr_t str = ST("I will find you - and I will kill you"); UCX_TEST_BEGIN @@ -100,6 +101,37 @@ UCX_TEST_END } + +UCX_TEST(test_sstrcat) { + sstr_t s1 = S("12"); + sstr_t s2 = S("34"); + sstr_t s3 = S("56"); + sstr_t sn = { NULL, 0 }; + + UCX_TEST_BEGIN + + sstr_t t1 = sstrcat(2, s1, s2); + UCX_TEST_ASSERT(!sstrcmp(t1, S("1234")), "t1: wrong content"); + free(t1.ptr); + + sstr_t t2 = sstrcat(3, s1, s2, s3); + UCX_TEST_ASSERT(!sstrcmp(t2, S("123456")), "t2: wrong content"); + free(t2.ptr); + + sstr_t t3 = sstrcat(6, s1, sn, s2, sn, s3, sn); + UCX_TEST_ASSERT(!sstrcmp(t3, S("123456")), "t3: wrong content"); + free(t3.ptr); + + sstr_t t4 = sstrcat(2, sn, sn); + UCX_TEST_ASSERT(t4.ptr, "t4.ptr is NULL"); + UCX_TEST_ASSERT(t4.length == 0, "t4 has wrong length"); + free(t4.ptr); + + + UCX_TEST_END + +} + UCX_TEST(test_sstrsplit) { const char *original = "this,is,a,csv,string";
--- a/test/string_tests.h Mon Jul 14 13:20:03 2014 +0200 +++ b/test/string_tests.h Mon Jul 14 16:54:10 2014 +0200 @@ -40,6 +40,7 @@ UCX_TEST(test_sstr_len); UCX_TEST(test_sstrcmp); UCX_TEST(test_sstrcasecmp); +UCX_TEST(test_sstrcat); UCX_TEST(test_sstrchr_sstrrchr); UCX_TEST(test_sstrsplit); UCX_TEST(test_sstrtrim);
--- a/ucx/Makefile Mon Jul 14 13:20:03 2014 +0200 +++ b/ucx/Makefile Mon Jul 14 16:54:10 2014 +0200 @@ -39,6 +39,7 @@ SRC += allocator.c SRC += logging.c SRC += buffer.c +SRC += stack.c OBJ = $(SRC:%.c=../build/release/ucx/%$(OBJ_EXT)) OBJ_D = $(SRC:%.c=../build/debug/ucx/%$(OBJ_EXT))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ucx/stack.c Mon Jul 14 16:54:10 2014 +0200 @@ -0,0 +1,108 @@ +/* + * 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.h" +#include <string.h> + +UcxStack ucx_stack_new(char* space, size_t size) { + UcxStack stack; + stack.size = size; + stack.space = stack.top = space; + + 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; +} + +void *ucx_stack_malloc(UcxStack *stack, size_t n) { + n += n % sizeof(void*); + + if (stack->top + n + sizeof(size_t) > stack->space + stack->size) { + return NULL; + } else { + void *ptr = stack->top; + + *((size_t*) (stack->top + n)) = n; + stack->top += n + sizeof(size_t); + + return ptr; + } +} + +void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize) { + void *mem = ucx_stack_malloc(stack, nelem*elsize); + memset(mem, 0, nelem*elsize); + return mem; +} + +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; + } else { + size_t* sptr = (size_t*) (((char*) ptr)-sizeof(size_t)); + if (*sptr < n) { + void *nptr = ucx_stack_malloc(stack, n); + if (nptr) { + memcpy(nptr, ptr, *sptr); + ucx_stack_free(stack, ptr); + return nptr; + } else { + return NULL; + } + } else { + *sptr = n; + return ptr; + } + } +} + +void ucx_stack_free(UcxStack *stack, void *ptr) { + if (ptr == stack->top+sizeof(size_t)) { + + } else { + + } +} + +void ucx_stack_pop(UcxStack *stack, void *dest) { +} + +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ucx/stack.h Mon Jul 14 16:54:10 2014 +0200 @@ -0,0 +1,198 @@ +/* + * 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. + */ + +/** + * @file stack.h + * + * Default stack memory allocation implementation. + * + * @author Mike Becker + * @author Olaf Wintermann + */ + +#ifndef UCX_STACK_H +#define UCX_STACK_H + +#include "ucx.h" +#include <stddef.h> +#include "allocator.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * UCX stack structure. + */ +typedef struct { + /** UcxAllocator based on this stack */ + UcxAllocator allocator; + + /** Stack size. */ + size_t size; + + /** Pointer to the bottom of the stack */ + char *space; + + /** Pointer to the top of the stack */ + char *top; +} UcxStack; + +/** + * Wraps memory in a new UcxStack 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); + +/** + * Allocates stack memory. + * + * @param stack a pointer to the stack + * @param n amount of memory to allocate + * @return a pointer to the allocated memory + * @see ucx_allocator_malloc() + */ +void *ucx_stack_malloc(UcxStack *stack, size_t n); + +/** + * Alias for #ucx_stack_malloc(). + * @param stack a pointer to the stack + * @param n amount of memory to allocate + * @return a pointer to the allocated memory + * @see ucx_stack_malloc + */ +#define ucx_stack_push(s, n) ucx_stack_malloc(s, n) + +/** + * Allocates an array of stack memory + * + * The content of the allocated memory is set to zero. + * + * @param stack a pointer to the stack + * @param nelem amount of elements to allocate + * @param elsize amount of memory per element + * @return a pointer to the allocated memory + * @see ucx_allocator_calloc() + */ +void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize); + +/** + * Alias for #ucx_stack_calloc(). + * + * @param stack a pointer to the stack + * @param nelem amount of elements to allocate + * @param elsize amount of memory per element + * @return a pointer to the allocated memory + * @see ucx_stack_calloc + */ +#define ucx_stack_pusharr(st,n,es) ucx_stack_calloc(st,n,es) + +/** + * Reallocates memory on the stack. + * + * Shrinking memory is always safe. Extending memory can be very expensive. + * + * @param stack the stack + * @param ptr a pointer to the memory that shall be reallocated + * @param n the new size of the memory + * @return a pointer to the new location of the memory + * @see ucx_allocator_realloc() + */ +void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n); + +/** + * Frees memory on the stack. + * + * Freeing stack memory behaves in a special way. + * + * If the element, that should be freed, is the top most element of the stack, + * it is removed from the stack. Otherwise it is marked as freed. Marked + * elements are removed, when they become the top most elements of the stack. + * + * @param stack a pointer to the stack + * @param ptr a pointer to the memory that shall be freed + */ +void ucx_stack_free(UcxStack *stack, void *ptr); + + +/** + * Returns the size of the top most element. + * @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)) + +/** + * Removes the top most element from the stack and copies the content to <code> + * dest</code>, if specified. + * + * Use #ucx_stack_topsize()# to get the amount of memory that must be available + * at the location of <code>dest</code>. + * + * @param stack a pointer to the stack + * @param dest the location where the contents shall be written to, or <code> + * NULL</code>, if the element shall only be removed. + * @see ucx_stack_free + * @see ucx_stack_popn + */ +void ucx_stack_pop(UcxStack *stack, void *dest); + +/** + * Removes the top most element from the stack and copies the content to <code> + * dest</code>. + * + * In contrast to #ucx_stack_pop() the <code>dest</code> pointer <code>MUST + * NOT</code> be <code>NULL</code>. + * + * @param stack a pointer to the stack + * @param dest the location where the contents shall be written to + * @param n copies at most n elements to <code>dest</code> + * @see ucx_stack_pop + */ +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n); + +/** + * Returns the remaining available memory on the specified stack. + * + * @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)) + + +#ifdef __cplusplus +} +#endif + +#endif /* UCX_STACK_H */ +
--- a/ucx/string.c Mon Jul 14 13:20:03 2014 +0200 +++ b/ucx/string.c Mon Jul 14 16:54:10 2014 +0200 @@ -61,6 +61,74 @@ return size; } +static sstr_t sstrvcat_a( + UcxAllocator *a, + size_t count, + sstr_t s1, + sstr_t s2, + va_list ap) { + sstr_t str; + str.ptr = NULL; + str.length = 0; + if(count < 2) { + return str; + } + + sstr_t *strings = calloc(count, sizeof(sstr_t)); + if(!strings) { + return str; + } + + // get all args and overall length + strings[0] = s1; + strings[1] = s2; + size_t strlen = s1.length + s2.length; + for (size_t i=2;i<count;i++) { + sstr_t s = va_arg (ap, sstr_t); + strings[i] = s; + strlen += s.length; + } + + // create new string + str.ptr = almalloc(a, strlen + 1); + str.length = strlen; + if(!str.ptr) { + free(strings); + str.length = 0; + return str; + } + + // concatenate strings + size_t pos = 0; + for (size_t i=0;i<count;i++) { + sstr_t s = strings[i]; + memcpy(str.ptr + pos, s.ptr, s.length); + pos += s.length; + } + + str.ptr[str.length] = '\0'; + + free(strings); + + return str; +} + +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { + va_list ap; + va_start(ap, s2); + sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); + va_end(ap); + return s; +} + +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { + va_list ap; + va_start(ap, s2); + sstr_t s = sstrvcat_a(a, count, s1, s2, ap); + va_end(ap); + return s; +} + sstr_t sstrsubs(sstr_t s, size_t start) { return sstrsubsl (s, start, s.length-start); }
--- a/ucx/string.h Mon Jul 14 13:20:03 2014 +0200 +++ b/ucx/string.h Mon Jul 14 16:54:10 2014 +0200 @@ -120,6 +120,17 @@ size_t sstrnlen(size_t count, sstr_t string, ...); /** + * Concatenates strings. + * + * @param count the total number of strings to concatenate + * @param ... all strings + * @return the concatenated string + */ +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...); +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...); + + +/** * Returns a substring starting at the specified location. * * <b>Attention:</b> the new string references the same memory area as the