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 |
1.1 --- a/test/main.c Mon Jul 14 13:20:03 2014 +0200 1.2 +++ b/test/main.c Mon Jul 14 16:54:10 2014 +0200 1.3 @@ -121,6 +121,7 @@ 1.4 ucx_test_register(suite, test_sstr_len); 1.5 ucx_test_register(suite, test_sstrcmp); 1.6 ucx_test_register(suite, test_sstrcasecmp); 1.7 + ucx_test_register(suite, test_sstrcat); 1.8 ucx_test_register(suite, test_sstrchr_sstrrchr); 1.9 ucx_test_register(suite, test_sstrsplit); 1.10 ucx_test_register(suite, test_sstrtrim);
2.1 --- a/test/string_tests.c Mon Jul 14 13:20:03 2014 +0200 2.2 +++ b/test/string_tests.c Mon Jul 14 16:54:10 2014 +0200 2.3 @@ -54,6 +54,7 @@ 2.4 UCX_TEST_END 2.5 } 2.6 2.7 + 2.8 UCX_TEST(test_sstrchr_sstrrchr) { 2.9 sstr_t str = ST("I will find you - and I will kill you"); 2.10 UCX_TEST_BEGIN 2.11 @@ -100,6 +101,37 @@ 2.12 UCX_TEST_END 2.13 } 2.14 2.15 + 2.16 +UCX_TEST(test_sstrcat) { 2.17 + sstr_t s1 = S("12"); 2.18 + sstr_t s2 = S("34"); 2.19 + sstr_t s3 = S("56"); 2.20 + sstr_t sn = { NULL, 0 }; 2.21 + 2.22 + UCX_TEST_BEGIN 2.23 + 2.24 + sstr_t t1 = sstrcat(2, s1, s2); 2.25 + UCX_TEST_ASSERT(!sstrcmp(t1, S("1234")), "t1: wrong content"); 2.26 + free(t1.ptr); 2.27 + 2.28 + sstr_t t2 = sstrcat(3, s1, s2, s3); 2.29 + UCX_TEST_ASSERT(!sstrcmp(t2, S("123456")), "t2: wrong content"); 2.30 + free(t2.ptr); 2.31 + 2.32 + sstr_t t3 = sstrcat(6, s1, sn, s2, sn, s3, sn); 2.33 + UCX_TEST_ASSERT(!sstrcmp(t3, S("123456")), "t3: wrong content"); 2.34 + free(t3.ptr); 2.35 + 2.36 + sstr_t t4 = sstrcat(2, sn, sn); 2.37 + UCX_TEST_ASSERT(t4.ptr, "t4.ptr is NULL"); 2.38 + UCX_TEST_ASSERT(t4.length == 0, "t4 has wrong length"); 2.39 + free(t4.ptr); 2.40 + 2.41 + 2.42 + UCX_TEST_END 2.43 + 2.44 +} 2.45 + 2.46 UCX_TEST(test_sstrsplit) { 2.47 2.48 const char *original = "this,is,a,csv,string";
3.1 --- a/test/string_tests.h Mon Jul 14 13:20:03 2014 +0200 3.2 +++ b/test/string_tests.h Mon Jul 14 16:54:10 2014 +0200 3.3 @@ -40,6 +40,7 @@ 3.4 UCX_TEST(test_sstr_len); 3.5 UCX_TEST(test_sstrcmp); 3.6 UCX_TEST(test_sstrcasecmp); 3.7 +UCX_TEST(test_sstrcat); 3.8 UCX_TEST(test_sstrchr_sstrrchr); 3.9 UCX_TEST(test_sstrsplit); 3.10 UCX_TEST(test_sstrtrim);
4.1 --- a/ucx/Makefile Mon Jul 14 13:20:03 2014 +0200 4.2 +++ b/ucx/Makefile Mon Jul 14 16:54:10 2014 +0200 4.3 @@ -39,6 +39,7 @@ 4.4 SRC += allocator.c 4.5 SRC += logging.c 4.6 SRC += buffer.c 4.7 +SRC += stack.c 4.8 4.9 OBJ = $(SRC:%.c=../build/release/ucx/%$(OBJ_EXT)) 4.10 OBJ_D = $(SRC:%.c=../build/debug/ucx/%$(OBJ_EXT))
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/ucx/stack.c Mon Jul 14 16:54:10 2014 +0200 5.3 @@ -0,0 +1,108 @@ 5.4 +/* 5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 5.6 + * 5.7 + * Copyright 2014 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 "stack.h" 5.33 +#include <string.h> 5.34 + 5.35 +UcxStack ucx_stack_new(char* space, size_t size) { 5.36 + UcxStack stack; 5.37 + stack.size = size; 5.38 + stack.space = stack.top = space; 5.39 + 5.40 + UcxAllocator alloc; 5.41 + alloc.pool = &stack; 5.42 + alloc.malloc = (ucx_allocator_malloc) ucx_stack_malloc; 5.43 + alloc.calloc = (ucx_allocator_calloc) ucx_stack_calloc; 5.44 + alloc.realloc = (ucx_allocator_realloc) ucx_stack_realloc; 5.45 + alloc.free = (ucx_allocator_free) ucx_stack_free; 5.46 + 5.47 + stack.allocator = alloc; 5.48 + 5.49 + return stack; 5.50 +} 5.51 + 5.52 +void *ucx_stack_malloc(UcxStack *stack, size_t n) { 5.53 + n += n % sizeof(void*); 5.54 + 5.55 + if (stack->top + n + sizeof(size_t) > stack->space + stack->size) { 5.56 + return NULL; 5.57 + } else { 5.58 + void *ptr = stack->top; 5.59 + 5.60 + *((size_t*) (stack->top + n)) = n; 5.61 + stack->top += n + sizeof(size_t); 5.62 + 5.63 + return ptr; 5.64 + } 5.65 +} 5.66 + 5.67 +void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize) { 5.68 + void *mem = ucx_stack_malloc(stack, nelem*elsize); 5.69 + memset(mem, 0, nelem*elsize); 5.70 + return mem; 5.71 +} 5.72 + 5.73 +void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) { 5.74 + if (ptr == stack->top - sizeof(size_t) - *((size_t*) stack->top - 1)) { 5.75 + 5.76 + stack->top = (char*)ptr + n; 5.77 + *((size_t*)stack->top) = n; 5.78 + stack->top += sizeof(size_t); 5.79 + 5.80 + return ptr; 5.81 + } else { 5.82 + size_t* sptr = (size_t*) (((char*) ptr)-sizeof(size_t)); 5.83 + if (*sptr < n) { 5.84 + void *nptr = ucx_stack_malloc(stack, n); 5.85 + if (nptr) { 5.86 + memcpy(nptr, ptr, *sptr); 5.87 + ucx_stack_free(stack, ptr); 5.88 + return nptr; 5.89 + } else { 5.90 + return NULL; 5.91 + } 5.92 + } else { 5.93 + *sptr = n; 5.94 + return ptr; 5.95 + } 5.96 + } 5.97 +} 5.98 + 5.99 +void ucx_stack_free(UcxStack *stack, void *ptr) { 5.100 + if (ptr == stack->top+sizeof(size_t)) { 5.101 + 5.102 + } else { 5.103 + 5.104 + } 5.105 +} 5.106 + 5.107 +void ucx_stack_pop(UcxStack *stack, void *dest) { 5.108 +} 5.109 + 5.110 +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) { 5.111 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/ucx/stack.h Mon Jul 14 16:54:10 2014 +0200 6.3 @@ -0,0 +1,198 @@ 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 +/** 6.33 + * @file stack.h 6.34 + * 6.35 + * Default stack memory allocation implementation. 6.36 + * 6.37 + * @author Mike Becker 6.38 + * @author Olaf Wintermann 6.39 + */ 6.40 + 6.41 +#ifndef UCX_STACK_H 6.42 +#define UCX_STACK_H 6.43 + 6.44 +#include "ucx.h" 6.45 +#include <stddef.h> 6.46 +#include "allocator.h" 6.47 + 6.48 +#ifdef __cplusplus 6.49 +extern "C" { 6.50 +#endif 6.51 + 6.52 + 6.53 +/** 6.54 + * UCX stack structure. 6.55 + */ 6.56 +typedef struct { 6.57 + /** UcxAllocator based on this stack */ 6.58 + UcxAllocator allocator; 6.59 + 6.60 + /** Stack size. */ 6.61 + size_t size; 6.62 + 6.63 + /** Pointer to the bottom of the stack */ 6.64 + char *space; 6.65 + 6.66 + /** Pointer to the top of the stack */ 6.67 + char *top; 6.68 +} UcxStack; 6.69 + 6.70 +/** 6.71 + * Wraps memory in a new UcxStack structure. 6.72 + * 6.73 + * @param space the memory area that shall be managed 6.74 + * @param size size of the memory area 6.75 + * @return a new UcxStack structure 6.76 + */ 6.77 +UcxStack ucx_stack_new(char* space, size_t size); 6.78 + 6.79 +/** 6.80 + * Allocates stack memory. 6.81 + * 6.82 + * @param stack a pointer to the stack 6.83 + * @param n amount of memory to allocate 6.84 + * @return a pointer to the allocated memory 6.85 + * @see ucx_allocator_malloc() 6.86 + */ 6.87 +void *ucx_stack_malloc(UcxStack *stack, size_t n); 6.88 + 6.89 +/** 6.90 + * Alias for #ucx_stack_malloc(). 6.91 + * @param stack a pointer to the stack 6.92 + * @param n amount of memory to allocate 6.93 + * @return a pointer to the allocated memory 6.94 + * @see ucx_stack_malloc 6.95 + */ 6.96 +#define ucx_stack_push(s, n) ucx_stack_malloc(s, n) 6.97 + 6.98 +/** 6.99 + * Allocates an array of stack memory 6.100 + * 6.101 + * The content of the allocated memory is set to zero. 6.102 + * 6.103 + * @param stack a pointer to the stack 6.104 + * @param nelem amount of elements to allocate 6.105 + * @param elsize amount of memory per element 6.106 + * @return a pointer to the allocated memory 6.107 + * @see ucx_allocator_calloc() 6.108 + */ 6.109 +void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize); 6.110 + 6.111 +/** 6.112 + * Alias for #ucx_stack_calloc(). 6.113 + * 6.114 + * @param stack a pointer to the stack 6.115 + * @param nelem amount of elements to allocate 6.116 + * @param elsize amount of memory per element 6.117 + * @return a pointer to the allocated memory 6.118 + * @see ucx_stack_calloc 6.119 + */ 6.120 +#define ucx_stack_pusharr(st,n,es) ucx_stack_calloc(st,n,es) 6.121 + 6.122 +/** 6.123 + * Reallocates memory on the stack. 6.124 + * 6.125 + * Shrinking memory is always safe. Extending memory can be very expensive. 6.126 + * 6.127 + * @param stack the stack 6.128 + * @param ptr a pointer to the memory that shall be reallocated 6.129 + * @param n the new size of the memory 6.130 + * @return a pointer to the new location of the memory 6.131 + * @see ucx_allocator_realloc() 6.132 + */ 6.133 +void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n); 6.134 + 6.135 +/** 6.136 + * Frees memory on the stack. 6.137 + * 6.138 + * Freeing stack memory behaves in a special way. 6.139 + * 6.140 + * If the element, that should be freed, is the top most element of the stack, 6.141 + * it is removed from the stack. Otherwise it is marked as freed. Marked 6.142 + * elements are removed, when they become the top most elements of the stack. 6.143 + * 6.144 + * @param stack a pointer to the stack 6.145 + * @param ptr a pointer to the memory that shall be freed 6.146 + */ 6.147 +void ucx_stack_free(UcxStack *stack, void *ptr); 6.148 + 6.149 + 6.150 +/** 6.151 + * Returns the size of the top most element. 6.152 + * @param stack a pointer to the stack 6.153 + * @return the size of the top most element 6.154 + */ 6.155 +#define ucx_stack_topsize(stack) (*(((size_t*)stack->top - 1)) 6.156 + 6.157 +/** 6.158 + * Removes the top most element from the stack and copies the content to <code> 6.159 + * dest</code>, if specified. 6.160 + * 6.161 + * Use #ucx_stack_topsize()# to get the amount of memory that must be available 6.162 + * at the location of <code>dest</code>. 6.163 + * 6.164 + * @param stack a pointer to the stack 6.165 + * @param dest the location where the contents shall be written to, or <code> 6.166 + * NULL</code>, if the element shall only be removed. 6.167 + * @see ucx_stack_free 6.168 + * @see ucx_stack_popn 6.169 + */ 6.170 +void ucx_stack_pop(UcxStack *stack, void *dest); 6.171 + 6.172 +/** 6.173 + * Removes the top most element from the stack and copies the content to <code> 6.174 + * dest</code>. 6.175 + * 6.176 + * In contrast to #ucx_stack_pop() the <code>dest</code> pointer <code>MUST 6.177 + * NOT</code> be <code>NULL</code>. 6.178 + * 6.179 + * @param stack a pointer to the stack 6.180 + * @param dest the location where the contents shall be written to 6.181 + * @param n copies at most n elements to <code>dest</code> 6.182 + * @see ucx_stack_pop 6.183 + */ 6.184 +void ucx_stack_popn(UcxStack *stack, void *dest, size_t n); 6.185 + 6.186 +/** 6.187 + * Returns the remaining available memory on the specified stack. 6.188 + * 6.189 + * @param stack a pointer to the stack 6.190 + * @return the remaining available memory 6.191 + */ 6.192 +#define ucx_stack_avail(stack) ((stack->size) - (s.top - s.space)\ 6.193 + - sizeof(size_t)) 6.194 + 6.195 + 6.196 +#ifdef __cplusplus 6.197 +} 6.198 +#endif 6.199 + 6.200 +#endif /* UCX_STACK_H */ 6.201 +
7.1 --- a/ucx/string.c Mon Jul 14 13:20:03 2014 +0200 7.2 +++ b/ucx/string.c Mon Jul 14 16:54:10 2014 +0200 7.3 @@ -61,6 +61,74 @@ 7.4 return size; 7.5 } 7.6 7.7 +static sstr_t sstrvcat_a( 7.8 + UcxAllocator *a, 7.9 + size_t count, 7.10 + sstr_t s1, 7.11 + sstr_t s2, 7.12 + va_list ap) { 7.13 + sstr_t str; 7.14 + str.ptr = NULL; 7.15 + str.length = 0; 7.16 + if(count < 2) { 7.17 + return str; 7.18 + } 7.19 + 7.20 + sstr_t *strings = calloc(count, sizeof(sstr_t)); 7.21 + if(!strings) { 7.22 + return str; 7.23 + } 7.24 + 7.25 + // get all args and overall length 7.26 + strings[0] = s1; 7.27 + strings[1] = s2; 7.28 + size_t strlen = s1.length + s2.length; 7.29 + for (size_t i=2;i<count;i++) { 7.30 + sstr_t s = va_arg (ap, sstr_t); 7.31 + strings[i] = s; 7.32 + strlen += s.length; 7.33 + } 7.34 + 7.35 + // create new string 7.36 + str.ptr = almalloc(a, strlen + 1); 7.37 + str.length = strlen; 7.38 + if(!str.ptr) { 7.39 + free(strings); 7.40 + str.length = 0; 7.41 + return str; 7.42 + } 7.43 + 7.44 + // concatenate strings 7.45 + size_t pos = 0; 7.46 + for (size_t i=0;i<count;i++) { 7.47 + sstr_t s = strings[i]; 7.48 + memcpy(str.ptr + pos, s.ptr, s.length); 7.49 + pos += s.length; 7.50 + } 7.51 + 7.52 + str.ptr[str.length] = '\0'; 7.53 + 7.54 + free(strings); 7.55 + 7.56 + return str; 7.57 +} 7.58 + 7.59 +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) { 7.60 + va_list ap; 7.61 + va_start(ap, s2); 7.62 + sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap); 7.63 + va_end(ap); 7.64 + return s; 7.65 +} 7.66 + 7.67 +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) { 7.68 + va_list ap; 7.69 + va_start(ap, s2); 7.70 + sstr_t s = sstrvcat_a(a, count, s1, s2, ap); 7.71 + va_end(ap); 7.72 + return s; 7.73 +} 7.74 + 7.75 sstr_t sstrsubs(sstr_t s, size_t start) { 7.76 return sstrsubsl (s, start, s.length-start); 7.77 }
8.1 --- a/ucx/string.h Mon Jul 14 13:20:03 2014 +0200 8.2 +++ b/ucx/string.h Mon Jul 14 16:54:10 2014 +0200 8.3 @@ -120,6 +120,17 @@ 8.4 size_t sstrnlen(size_t count, sstr_t string, ...); 8.5 8.6 /** 8.7 + * Concatenates strings. 8.8 + * 8.9 + * @param count the total number of strings to concatenate 8.10 + * @param ... all strings 8.11 + * @return the concatenated string 8.12 + */ 8.13 +sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...); 8.14 +sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...); 8.15 + 8.16 + 8.17 +/** 8.18 * Returns a substring starting at the specified location. 8.19 * 8.20 * <b>Attention:</b> the new string references the same memory area as the