--- a/ucx/string.c Wed Dec 31 12:37:09 2025 +0100 +++ b/ucx/string.c Wed Dec 31 16:40:12 2025 +0100 @@ -26,8 +26,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -// for memrchr in glibc +#ifdef WITH_MEMRCHR #define _GNU_SOURCE +#endif #include "cx/string.h" @@ -40,7 +41,12 @@ #include <ctype.h> #ifdef _WIN32 -#define cx_strcasecmp_impl _strnicmp +static int cx_fixed_strnicmp(const char* s1, const char* s2, size_t count) { + // Microsoft's implementation crashes when count == 0 and either string is NULL + if (count == 0) return 0; + return _strnicmp(s1, s2, count); +} +#define cx_strcasecmp_impl cx_fixed_strnicmp #else #include <strings.h> #define cx_strcasecmp_impl strncasecmp @@ -63,7 +69,7 @@ str->length = 0; } -int cx_strcpy_a( +int cx_strcpy_a_( const CxAllocator *alloc, cxmutstr *dest, cxstring src @@ -98,13 +104,19 @@ return size; } -cxmutstr cx_strcat_ma( +cxmutstr cx_strcat_a( const CxAllocator *alloc, cxmutstr str, size_t count, ... ) { - if (count == 0) return str; + if (count == 0) { + if (cxReallocate(alloc, &str.ptr, str.length + 1)) { + return CX_NULLSTR; // LCOV_EXCL_LINE + } + str.ptr[str.length] = '\0'; + return str; + } va_list ap; va_start(ap, count); va_list ap2; @@ -124,21 +136,16 @@ if (overflow) { va_end(ap2); errno = EOVERFLOW; - return (cxmutstr) { NULL, 0 }; + return CX_NULLSTR; } - // reallocate or create new string - char *newstr; - if (str.ptr == NULL) { - newstr = cxMalloc(alloc, slen + 1); - } else { - newstr = cxRealloc(alloc, str.ptr, slen + 1); + // reallocate or create a new string + if (cxReallocate(alloc, &str.ptr, slen + 1)) { + // LCOV_EXCL_START + va_end(ap2); + return CX_NULLSTR; + // LCOV_EXCL_STOP } - if (newstr == NULL) { // LCOV_EXCL_START - va_end(ap2); - return (cxmutstr) {NULL, 0}; - } // LCOV_EXCL_STOP - str.ptr = newstr; // concatenate strings size_t pos = str.length; @@ -156,21 +163,14 @@ return str; } -cxstring cx_strsubs( +cxstring cx_strsubs_( cxstring string, size_t start ) { - return cx_strsubsl(string, start, string.length - start); + return cx_strsubsl_(string, start, string.length); } -cxmutstr cx_strsubs_m( - cxmutstr string, - size_t start -) { - return cx_strsubsl_m(string, start, string.length - start); -} - -cxstring cx_strsubsl( +cxstring cx_strsubsl_( cxstring string, size_t start, size_t length @@ -187,16 +187,7 @@ return (cxstring) {string.ptr + start, length}; } -cxmutstr cx_strsubsl_m( - cxmutstr string, - size_t start, - size_t length -) { - cxstring result = cx_strsubsl(cx_strcast(string), start, length); - return (cxmutstr) {(char *) result.ptr, result.length}; -} - -cxstring cx_strchr( +cxstring cx_strchr_( cxstring string, int chr ) { @@ -205,15 +196,7 @@ return (cxstring) {ret, string.length - (ret - string.ptr)}; } -cxmutstr cx_strchr_m( - cxmutstr string, - int chr -) { - cxstring result = cx_strchr(cx_strcast(string), chr); - return (cxmutstr) {(char *) result.ptr, result.length}; -} - -cxstring cx_strrchr( +cxstring cx_strrchr_( cxstring string, int chr ) { @@ -234,23 +217,12 @@ #endif } -cxmutstr cx_strrchr_m( - cxmutstr string, - int chr -) { - cxstring result = cx_strrchr(cx_strcast(string), chr); - return (cxmutstr) {(char *) result.ptr, result.length}; -} +#ifndef CX_STRSTR_SBO_SIZE +#define CX_STRSTR_SBO_SIZE 128 +#endif +const unsigned cx_strstr_sbo_size = CX_STRSTR_SBO_SIZE; -#ifndef cx_strSTR_SBO_SIZE -#define cx_strSTR_SBO_SIZE 128 -#endif -const unsigned cx_strstr_sbo_size = cx_strSTR_SBO_SIZE; - -cxstring cx_strstr( - cxstring haystack, - cxstring needle -) { +cxstring cx_strstr_(cxstring haystack, cxstring needle) { if (needle.length == 0) { return haystack; } @@ -269,11 +241,11 @@ */ // local prefix table - size_t s_prefix_table[cx_strSTR_SBO_SIZE]; + size_t s_prefix_table[CX_STRSTR_SBO_SIZE]; // check needle length and use appropriate prefix table // if the pattern exceeds static prefix table, allocate on the heap - const bool useheap = needle.length >= cx_strSTR_SBO_SIZE; + const bool useheap = needle.length >= CX_STRSTR_SBO_SIZE; register size_t *ptable = useheap ? cxCallocDefault(needle.length + 1, sizeof(size_t)) : s_prefix_table; @@ -320,15 +292,7 @@ return result; } -cxmutstr cx_strstr_m( - cxmutstr haystack, - cxstring needle -) { - cxstring result = cx_strstr(cx_strcast(haystack), needle); - return (cxmutstr) {(char *) result.ptr, result.length}; -} - -size_t cx_strsplit( +size_t cx_strsplit_( cxstring string, cxstring delim, size_t limit, @@ -386,7 +350,7 @@ return n; } -size_t cx_strsplit_a( +size_t cx_strsplit_a_( const CxAllocator *allocator, cxstring string, cxstring delim, @@ -415,27 +379,27 @@ } } *output = cxCalloc(allocator, n, sizeof(cxstring)); - return cx_strsplit(string, delim, n, *output); + return cx_strsplit_(string, delim, n, *output); } -size_t cx_strsplit_m( +size_t cx_strsplit_m_( cxmutstr string, cxstring delim, size_t limit, cxmutstr *output ) { - return cx_strsplit(cx_strcast(string), + return cx_strsplit_(cx_strcast(string), delim, limit, (cxstring *) output); } -size_t cx_strsplit_ma( +size_t cx_strsplit_ma_( const CxAllocator *allocator, cxmutstr string, cxstring delim, size_t limit, cxmutstr **output ) { - return cx_strsplit_a(allocator, cx_strcast(string), + return cx_strsplit_a_(allocator, cx_strcast(string), delim, limit, (cxstring **) output); } @@ -510,23 +474,18 @@ return result; } -cxstring cx_strtrim(cxstring string) { +cxstring cx_strtrim_(cxstring string) { cxstring result = string; - while (result.length > 0 && isspace((unsigned char)(result.ptr[0]))) { + while (isspace((unsigned char)cx_strat(result, 0))) { result.ptr++; result.length--; } - while (result.length > 0 && isspace((unsigned char)result.ptr[result.length - 1])) { + while (isspace((unsigned char)cx_strat(result, -1))) { result.length--; } return result; } -cxmutstr cx_strtrim_m(cxmutstr string) { - cxstring result = cx_strtrim(cx_strcast(string)); - return (cxmutstr) {(char *) result.ptr, result.length}; -} - bool cx_strprefix_( cxstring string, cxstring prefix @@ -570,7 +529,7 @@ #endif } -cxmutstr cx_strreplacen_a( +cxmutstr cx_strreplace_( const CxAllocator *allocator, cxstring str, cxstring search, @@ -651,7 +610,7 @@ return ctx; } -bool cx_strtok_next( +bool cx_strtok_next_( CxStrtokCtx *ctx, cxstring *token ) { @@ -694,13 +653,6 @@ return true; } -bool cx_strtok_next_m( - CxStrtokCtx *ctx, - cxmutstr *token -) { - return cx_strtok_next(ctx, (cxstring *) token); -} - void cx_strtok_delim( CxStrtokCtx *ctx, const cxstring *delim,