adds array utility functions for user defined arrays feature/array

Tue, 24 Sep 2019 20:16:00 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 24 Sep 2019 20:16:00 +0200
branch
feature/array
changeset 355
d315a068235a
parent 354
7fd13b9f8f60
child 356
77efe51c6c9a

adds array utility functions for user defined arrays

src/array.c file | annotate | diff | comparison | revisions
src/ucx/array.h file | annotate | diff | comparison | revisions
test/array_tests.c file | annotate | diff | comparison | revisions
test/array_tests.h file | annotate | diff | comparison | revisions
test/main.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/array.c	Sat Aug 10 11:12:49 2019 +0200
     1.2 +++ b/src/array.c	Tue Sep 24 20:16:00 2019 +0200
     1.3 @@ -35,6 +35,7 @@
     1.4  
     1.5  #include <string.h>
     1.6  #include <stdlib.h>
     1.7 +#include <errno.h>
     1.8  
     1.9  #ifndef UCX_ARRAY_DISABLE_QSORT
    1.10  #ifdef __GLIBC__
    1.11 @@ -67,6 +68,51 @@
    1.12      }
    1.13  }
    1.14  
    1.15 +int ucx_array_util_set_a(UcxAllocator* alloc, void** array, size_t* capacity,
    1.16 +    size_t elmsize, size_t index, ...) {
    1.17 +    
    1.18 +    if(!alloc || !capacity || !array) {
    1.19 +        errno = EINVAL;
    1.20 +        return 1;
    1.21 +    }
    1.22 +    
    1.23 +    size_t newcapacity = *capacity;
    1.24 +    while(index >= newcapacity) {
    1.25 +        if(ucx_szmul(newcapacity, 2, &newcapacity)) {
    1.26 +            errno = EOVERFLOW;
    1.27 +            return 1;
    1.28 +        }        
    1.29 +    }
    1.30 +
    1.31 +    size_t memlen, offset;
    1.32 +    if(ucx_szmul(newcapacity, elmsize, &memlen)) {
    1.33 +        errno = EOVERFLOW;
    1.34 +        return 1;
    1.35 +    }
    1.36 +    /* we don't need to check index*elmsize - it is smaller than memlen */
    1.37 +    
    1.38 +    
    1.39 +    void* newptr = alrealloc(alloc, *array, memlen);
    1.40 +    if(newptr == NULL) {
    1.41 +        errno = ENOMEM; /* we cannot assume that every allocator sets this */
    1.42 +        return 1;
    1.43 +    }
    1.44 +    *array = newptr;
    1.45 +    *capacity = newcapacity;
    1.46 +    
    1.47 +    
    1.48 +    char* dest = *array;
    1.49 +    dest += elmsize*index;
    1.50 +
    1.51 +    va_list ap;
    1.52 +    va_start(ap, index);
    1.53 +    int elem = va_arg(ap, int);    
    1.54 +    memcpy(dest, &elem, elmsize);
    1.55 +    va_end(ap);
    1.56 +    
    1.57 +    return 0;
    1.58 +}
    1.59 +
    1.60  UcxArray ucx_array_new(size_t capacity, size_t elemsize) {
    1.61      return ucx_array_new_a(capacity, elemsize, ucx_default_allocator());
    1.62  }
     2.1 --- a/src/ucx/array.h	Sat Aug 10 11:12:49 2019 +0200
     2.2 +++ b/src/ucx/array.h	Tue Sep 24 20:16:00 2019 +0200
     2.3 @@ -69,6 +69,77 @@
     2.4      UcxAllocator* allocator;
     2.5  } UcxArray;
     2.6  
     2.7 +/**
     2.8 + * Sets an element in an arbitrary user defined array.
     2.9 + * 
    2.10 + * If the capacity is insufficient, the array is automatically reallocated and
    2.11 + * the possibly new pointer is stored in the <code>array</code> argument.
    2.12 + * 
    2.13 + * On reallocation the capacity of the array is doubled until it is sufficient.
    2.14 + * The new capacity is stored back to <code>capacity</code>.
    2.15 + *  
    2.16 + * @param array a pointer to location of the array pointer
    2.17 + * @param capacity a pointer to the capacity
    2.18 + * @param elmsize the size of each element
    2.19 + * @param idx the index of the element to set
    2.20 + * @param data the element data
    2.21 + * @return zero on success or non-zero on error (errno will be set)
    2.22 + */
    2.23 +#define ucx_array_util_set(array, capacity, elmsize, idx, data) \
    2.24 +    ucx_array_util_set_a(ucx_default_allocator(), (void**)(array), capacity, \
    2.25 +                         elmsize, idx, data)
    2.26 +
    2.27 +/**
    2.28 + * Convenience macro for ucx_array_util_set() which automatically computes
    2.29 + * <code>sizeof(data)</code>.
    2.30 + * 
    2.31 + * @param array a pointer to location of the array pointer
    2.32 + * @param capacity a pointer to the capacity
    2.33 + * @param idx the index of the element to set
    2.34 + * @param data the element data
    2.35 + * @return zero on success or non-zero on error (errno will be set)
    2.36 + * @see ucx_array_util_set()
    2.37 + */
    2.38 +#define UCX_ARRAY_UTIL_SET(array, capacity, idx, data) \
    2.39 +    ucx_array_util_set_a(ucx_default_allocator(), (void**)(array), capacity, \
    2.40 +                         sizeof(data), idx, data)
    2.41 +
    2.42 +/**
    2.43 + * Sets an element in an arbitrary user defined array.
    2.44 + * 
    2.45 + * If the capacity is insufficient, the array is automatically reallocated
    2.46 + * using the specified allocator and the possibly new pointer is stored in
    2.47 + * the <code>array</code> argument.
    2.48 + * 
    2.49 + * On reallocation the capacity of the array is doubled until it is sufficient.
    2.50 + * The new capacity is stored back to <code>capacity</code>. 
    2.51 + * 
    2.52 + * @param alloc the allocator that shall be used to reallocate the array
    2.53 + * @param array a pointer to location of the array pointer
    2.54 + * @param capacity a pointer to the capacity
    2.55 + * @param elmsize the size of each element
    2.56 + * @param idx the index of the element to set
    2.57 + * @param ... the element data
    2.58 + * @return zero on success or non-zero on error (errno will be set)
    2.59 + */
    2.60 +int ucx_array_util_set_a(UcxAllocator* alloc, void** array, size_t* capacity,
    2.61 +    size_t elmsize, size_t idx, ...);
    2.62 +
    2.63 +
    2.64 +/**
    2.65 + * Convenience macro for ucx_array_util_set_a() which automatically computes
    2.66 + * <code>sizeof(data)</code>.
    2.67 + * 
    2.68 + * @param alloc the allocator that shall be used to reallocate the array
    2.69 + * @param array a pointer to location of the array pointer
    2.70 + * @param capacity a pointer to the capacity
    2.71 + * @param idx the index of the element to set
    2.72 + * @param data the element data
    2.73 + * @return zero on success or non-zero on error (errno will be set)
    2.74 + * @see ucx_array_util_set_a()
    2.75 + */
    2.76 +#define UCX_ARRAY_UTIL_SET_A(alloc, array, capacity, idx, data) \
    2.77 +    ucx_array_util_set_a(alloc, capacity, sizeof(data), idx, data)
    2.78  
    2.79  /**
    2.80   * Creates a new UCX array with the given capacity and element size.
     3.1 --- a/test/array_tests.c	Sat Aug 10 11:12:49 2019 +0200
     3.2 +++ b/test/array_tests.c	Tue Sep 24 20:16:00 2019 +0200
     3.3 @@ -622,3 +622,26 @@
     3.4      UCX_TEST_END
     3.5      ucx_array_destroy(&array);
     3.6  }
     3.7 +
     3.8 +UCX_TEST(test_ucx_array_util_set) {
     3.9 +    size_t capacity = 16;
    3.10 +    int* array = malloc(sizeof(int)*capacity);
    3.11 +
    3.12 +    UCX_TEST_BEGIN
    3.13 +
    3.14 +    UCX_ARRAY_UTIL_SET(&array, &capacity, 7, 42);
    3.15 +    
    3.16 +    UCX_TEST_ASSERT(array[7] == 42, "failed");
    3.17 +    UCX_TEST_ASSERT(capacity == 16, "capacity changed unnecessarily");
    3.18 +    
    3.19 +    UCX_ARRAY_UTIL_SET(&array, &capacity, 37, 13);
    3.20 +    UCX_ARRAY_UTIL_SET(&array, &capacity, 38, 37);
    3.21 +    
    3.22 +    UCX_TEST_ASSERT(array[37] == 13, "failed");
    3.23 +    UCX_TEST_ASSERT(array[38] == 37, "failed");
    3.24 +    UCX_TEST_ASSERT(capacity == 64, "capacity not grown");
    3.25 +        
    3.26 +    UCX_TEST_END
    3.27 +    
    3.28 +    free(array);
    3.29 +}
     4.1 --- a/test/array_tests.h	Sat Aug 10 11:12:49 2019 +0200
     4.2 +++ b/test/array_tests.h	Tue Sep 24 20:16:00 2019 +0200
     4.3 @@ -56,6 +56,7 @@
     4.4  UCX_TEST(test_ucx_array_shrink);
     4.5  UCX_TEST(test_ucx_array_resize);
     4.6  UCX_TEST(test_ucx_array_reserve);
     4.7 +UCX_TEST(test_ucx_array_util_set);
     4.8  
     4.9  #ifdef	__cplusplus
    4.10  }
     5.1 --- a/test/main.c	Sat Aug 10 11:12:49 2019 +0200
     5.2 +++ b/test/main.c	Tue Sep 24 20:16:00 2019 +0200
     5.3 @@ -163,6 +163,7 @@
     5.4          ucx_test_register(suite, test_ucx_array_shrink);
     5.5          ucx_test_register(suite, test_ucx_array_resize);
     5.6          ucx_test_register(suite, test_ucx_array_reserve);
     5.7 +        ucx_test_register(suite, test_ucx_array_util_set);
     5.8          
     5.9          /* UcxList Tests */
    5.10          ucx_test_register(suite, test_ucx_list_append);

mercurial