merged sstrcat function

Mon, 14 Jul 2014 16:54:10 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 14 Jul 2014 16:54:10 +0200
changeset 182
998bf7c643b4
parent 181
1e9012ad8215 (current diff)
parent 180
2185f19dcc45 (diff)
child 183
6a694f8f0084

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

mercurial