Tue, 24 Sep 2019 20:16:00 +0200
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);