# HG changeset patch # User Olaf Wintermann # Date 1683453190 -7200 # Node ID 49a284f61e8ceb49ab75d064e01040481ee74bf5 # Parent efbd59642577c827351cba92e4548936bac12297 update ucx diff -r efbd59642577 -r 49a284f61e8c ucx/array_list.c --- a/ucx/array_list.c Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/array_list.c Sun May 07 11:53:10 2023 +0200 @@ -345,21 +345,22 @@ } } -static size_t cx_arl_find( +static ssize_t cx_arl_find( struct cx_list_s const *list, void const *elem ) { assert(list->cmpfunc != NULL); + assert(list->size < SIZE_MAX / 2); char *cur = ((cx_array_list const *) list)->data; - for (size_t i = 0; i < list->size; i++) { + for (ssize_t i = 0; i < (ssize_t) list->size; i++) { if (0 == list->cmpfunc(elem, cur)) { return i; } cur += list->item_size; } - return list->size; + return -1; } static void cx_arl_sort(struct cx_list_s *list) { diff -r efbd59642577 -r 49a284f61e8c ucx/cx/hash_map.h --- a/ucx/cx/hash_map.h Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/cx/hash_map.h Sun May 07 11:53:10 2023 +0200 @@ -90,6 +90,22 @@ ); /** + * Creates a new hash map with a default number of buckets. + * + * If \p item_size is CX_STORE_POINTERS, the created map will be created as if + * cxMapStorePointers() was called immediately after creation. + * + * @note Iterators provided by this hash map implementation provide the remove operation. + * The index value of an iterator is the incremented when the iterator advanced without removal. + * In other words, when the iterator is finished, \c index==size . + * + * @param itemsize the size of one element + * @return a pointer to the new hash map + */ +#define cxHashMapCreateSimple(itemsize) \ + cxHashMapCreate(cxDefaultAllocator, itemsize, 0) + +/** * Increases the number of buckets, if necessary. * * The load threshold is \c 0.75*buckets. If the element count exceeds the load diff -r efbd59642577 -r 49a284f61e8c ucx/cx/iterator.h --- a/ucx/cx/iterator.h Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/cx/iterator.h Sun May 07 11:53:10 2023 +0200 @@ -74,7 +74,7 @@ bool (*flag_removal)(void *); /** - * Indicates whether this iterator is muting. + * Indicates whether this iterator may remove elements. */ bool mutating; diff -r efbd59642577 -r 49a284f61e8c ucx/cx/linked_list.h --- a/ucx/cx/linked_list.h Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/cx/linked_list.h Sun May 07 11:53:10 2023 +0200 @@ -118,9 +118,9 @@ * @param loc_data the location of the \c data pointer within your node struct * @param cmp_func a compare function to compare \p elem against the node data * @param elem a pointer to the element to find - * @return the index of the element or a past-one index if the element could not be found + * @return the index of the element or a negative value if it could not be found */ -size_t cx_linked_list_find( +ssize_t cx_linked_list_find( void const *start, ptrdiff_t loc_advance, ptrdiff_t loc_data, diff -r efbd59642577 -r 49a284f61e8c ucx/cx/list.h --- a/ucx/cx/list.h Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/cx/list.h Sun May 07 11:53:10 2023 +0200 @@ -136,7 +136,7 @@ /** * Member function for finding an element. */ - size_t (*find)( + ssize_t (*find)( struct cx_list_s const *list, void const *elem ); @@ -569,10 +569,11 @@ * * @param list the list * @param elem the element to find - * @return the index of the element or \c (size+1) if the element is not found + * @return the index of the element or a negative + * value when the element is not found */ __attribute__((__nonnull__)) -static inline size_t cxListFind( +static inline ssize_t cxListFind( CxList const *list, void const *elem ) { diff -r efbd59642577 -r 49a284f61e8c ucx/cx/string.h --- a/ucx/cx/string.h Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/cx/string.h Sun May 07 11:53:10 2023 +0200 @@ -296,28 +296,50 @@ ); /** - * Concatenates two or more strings. + * Concatenates strings. * * The resulting string will be allocated by the specified allocator. - * So developers \em must pass the return value to cx_strfree() eventually. - * - * \note It is guaranteed that there is only one allocation. - * It is also guaranteed that the returned string is zero-terminated. + * So developers \em must pass the return value to cx_strfree_a() eventually. + * + * If \p str already contains a string, the memory will be reallocated and + * the other strings are appended. Otherwise, new memory is allocated. + * + * \note It is guaranteed that there is only one allocation. + * It is also guaranteed that the returned string is zero-terminated. * * @param alloc the allocator to use - * @param count the total number of strings to concatenate - * @param ... all strings + * @param str the string the other strings shall be concatenated to + * @param count the number of the other following strings to concatenate + * @param ... all other strings * @return the concatenated string */ __attribute__((__warn_unused_result__, __nonnull__)) -cxmutstr cx_strcat_a( +cxmutstr cx_strcat_ma( CxAllocator const *alloc, + cxmutstr str, size_t count, ... ); /** - * Concatenates two or more strings. + * Concatenates strings and returns a new string. + * + * The resulting string will be allocated by the specified allocator. + * So developers \em must pass the return value to cx_strfree_a() eventually. + * + * \note It is guaranteed that there is only one allocation. + * It is also guaranteed that the returned string is zero-terminated. + * + * @param alloc the allocator to use + * @param count the number of the other following strings to concatenate + * @param ... all other strings + * @return the concatenated string + */ +#define cx_strcat_a(alloc, count, ...) \ +cx_strcat_ma(alloc, cx_mutstrn(NULL, 0), count, __VA_ARGS__) + +/** + * Concatenates strings and returns a new string. * * The resulting string will be allocated by standard \c malloc(). * So developers \em must pass the return value to cx_strfree() eventually. @@ -325,12 +347,32 @@ * \note It is guaranteed that there is only one allocation. * It is also guaranteed that the returned string is zero-terminated. * - * @param count the total number of strings to concatenate - * @param ... all strings + * @param count the number of the other following strings to concatenate + * @param ... all other strings * @return the concatenated string */ #define cx_strcat(count, ...) \ -cx_strcat_a(cxDefaultAllocator, count, __VA_ARGS__) +cx_strcat_ma(cxDefaultAllocator, cx_mutstrn(NULL, 0), count, __VA_ARGS__) + +/** + * Concatenates strings. + * + * The resulting string will be allocated by standard \c malloc(). + * So developers \em must pass the return value to cx_strfree() eventually. + * + * If \p str already contains a string, the memory will be reallocated and + * the other strings are appended. Otherwise, new memory is allocated. + * + * \note It is guaranteed that there is only one allocation. + * It is also guaranteed that the returned string is zero-terminated. + * + * @param str the string the other strings shall be concatenated to + * @param count the number of the other following strings to concatenate + * @param ... all other strings + * @return the concatenated string + */ +#define cx_strcat_m(str, count, ...) \ +cx_strcat_ma(cxDefaultAllocator, str, count, __VA_ARGS__) /** * Returns a substring starting at the specified location. @@ -732,6 +774,35 @@ */ #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string) + +/** + * Creates a duplicate of the specified string. + * + * The new string will contain a copy allocated by \p allocator. + * + * \note The returned string is guaranteed to be zero-terminated. + * + * @param allocator the allocator to use + * @param string the string to duplicate + * @return a duplicate of the string + * @see cx_strdup_m() + */ +#define cx_strdup_ma(allocator, string) cx_strdup_a(allocator, cx_strcast(string)) + +/** + * Creates a duplicate of the specified string. + * + * The new string will contain a copy allocated by standard + * \c malloc(). So developers \em must pass the return value to cx_strfree(). + * + * \note The returned string is guaranteed to be zero-terminated. + * + * @param string the string to duplicate + * @return a duplicate of the string + * @see cx_strdup_ma() + */ +#define cx_strdup_m(string) cx_strdup_a(cxDefaultAllocator, cx_strcast(string)) + /** * Omits leading and trailing spaces. * diff -r efbd59642577 -r 49a284f61e8c ucx/linked_list.c --- a/ucx/linked_list.c Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/linked_list.c Sun May 07 11:53:10 2023 +0200 @@ -56,7 +56,7 @@ return (void *) cur; } -size_t cx_linked_list_find( +ssize_t cx_linked_list_find( void const *start, ptrdiff_t loc_advance, ptrdiff_t loc_data, @@ -69,7 +69,7 @@ assert(cmp_func); void const *node = start; - size_t index = 0; + ssize_t index = 0; do { void *current = ll_data(node); if (cmp_func(current, elem) == 0) { @@ -78,7 +78,7 @@ node = ll_advance(node); index++; } while (node != NULL); - return index; + return -1; } void *cx_linked_list_first( @@ -355,6 +355,9 @@ // set start node ls = *begin; + // early exit when this list is empty + if (ls == NULL) return; + // check how many elements are already sorted lc = ls; size_t ln = 1; @@ -729,7 +732,7 @@ return node == NULL ? NULL : node->payload; } -static size_t cx_ll_find( +static ssize_t cx_ll_find( struct cx_list_s const *list, void const *elem ) { diff -r efbd59642577 -r 49a284f61e8c ucx/list.c --- a/ucx/list.c Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/list.c Sun May 07 11:53:10 2023 +0200 @@ -115,12 +115,12 @@ return ptr == NULL ? NULL : *ptr; } -static size_t cx_pl_find( +static ssize_t cx_pl_find( struct cx_list_s const *list, void const *elem ) { cx_pl_hack_cmpfunc(list); - size_t ret = list->climpl->find(list, &elem); + ssize_t ret = list->climpl->find(list, &elem); cx_pl_unhack_cmpfunc(list); return ret; } diff -r efbd59642577 -r 49a284f61e8c ucx/string.c --- a/ucx/string.c Fri Apr 21 21:25:32 2023 +0200 +++ b/ucx/string.c Sun May 07 11:53:10 2023 +0200 @@ -98,11 +98,14 @@ return size; } -cxmutstr cx_strcat_a( +cxmutstr cx_strcat_ma( CxAllocator const *alloc, + cxmutstr str, size_t count, ... ) { + if (count == 0) return str; + cxstring *strings = calloc(count, sizeof(cxstring)); if (!strings) abort(); @@ -110,34 +113,38 @@ va_start(ap, count); // get all args and overall length - size_t slen = 0; + size_t slen = str.length; cx_for_n(i, count) { cxstring s = va_arg (ap, cxstring); strings[i] = s; slen += s.length; } + va_end(ap); - // create new string - cxmutstr result; - result.ptr = cxMalloc(alloc, slen + 1); - result.length = slen; - if (result.ptr == NULL) abort(); + // reallocate or create new string + if (str.ptr == NULL) { + str.ptr = cxMalloc(alloc, slen + 1); + } else { + str.ptr = cxRealloc(alloc, str.ptr, slen + 1); + } + if (str.ptr == NULL) abort(); // concatenate strings - size_t pos = 0; + size_t pos = str.length; + str.length = slen; cx_for_n(i, count) { cxstring s = strings[i]; - memcpy(result.ptr + pos, s.ptr, s.length); + memcpy(str.ptr + pos, s.ptr, s.length); pos += s.length; } // terminate string - result.ptr[result.length] = '\0'; + str.ptr[str.length] = '\0'; // free temporary array free(strings); - return result; + return str; } cxstring cx_strsubs(