# HG changeset patch # User Mike Becker # Date 1766943025 -3600 # Node ID f889ffd07c8693df4760e7e688f17b83083c8362 # Parent 36c0fb2b60b2a8341c63edad7a68be6d92c0c097 add full generic support for cx_strchr() and cx_strrchr() relates to #792 diff -r 36c0fb2b60b2 -r f889ffd07c86 src/cx/string.h --- a/src/cx/string.h Sun Dec 28 17:31:20 2025 +0100 +++ b/src/cx/string.h Sun Dec 28 18:30:25 2025 +0100 @@ -674,19 +674,59 @@ #define cx_strat(str, index) cx_strat_(cx_strcast(str), index) /** - * Returns a substring starting at the location of the first occurrence of the - * specified character. - * - * If the string does not contain the character, an empty string is returned. - * - * @param string the string where to locate the character - * @param chr the character to locate - * @return a substring starting at the first location of @p chr - * - * @see cx_strchr_m() + * Searches for a character in a string. + * Internal function - do not use. + * @param string + * @param chr + * @return + * @see cx_strchr() + */ +CX_EXTERN CX_NODISCARD +cxstring cx_strchr_(cxstring string, int chr); + +/** + * Searches for a character in a string. + * Internal function - do not use. + * @param string + * @param chr + * @return + * @see cx_strrchr() */ CX_EXTERN CX_NODISCARD -cxstring cx_strchr(cxstring string, int chr); +cxstring cx_strrchr_(cxstring string, int chr); + +#ifdef __cplusplus +CX_CPPDECL cxstring cx_strchr(cxstring string, int chr) { + return cx_strchr_(string, chr); +} +CX_CPPDECL cxmutstr cx_strchr(cxmutstr string, int chr) { + return cx_mutstrcast(cx_strchr_(cx_strcast(string), chr)); +} +CX_CPPDECL cxstring cx_strrchr(cxstring string, int chr) { + return cx_strrchr_(string, chr); +} +CX_CPPDECL cxmutstr cx_strrchr(cxmutstr string, int chr) { + return cx_mutstrcast(cx_strrchr_(cx_strcast(string), chr)); +} +#else +/** + * Internal conversion function - do not use. + * @param string + * @param chr + * @return + */ +CX_INLINE cxmutstr cx_strchr_m_(cxmutstr string, int chr) { + return cx_mutstrcast(cx_strchr_(cx_strcast(string), chr)); +} +/** + * Internal conversion function - do not use. + * @param string + * @param chr + * @return + */ +CX_INLINE cxmutstr cx_strrchr_m_(cxmutstr string, int chr) { + return cx_mutstrcast(cx_strrchr_(cx_strcast(string), chr)); +} /** * Returns a substring starting at the location of the first occurrence of the @@ -697,11 +737,10 @@ * @param string the string where to locate the character * @param chr the character to locate * @return a substring starting at the first location of @p chr - * - * @see cx_strchr() */ -CX_EXTERN CX_NODISCARD -cxmutstr cx_strchr_m(cxmutstr string, int chr); +#define cx_strchr(string, chr) _Generic(cx_strcast_m(string), \ + cxstring: cx_strchr_, \ + cxmutstr: cx_strchr_m_)(cx_strcast_m(string), chr) /** * Returns a substring starting at the location of the last occurrence of the @@ -712,26 +751,11 @@ * @param string the string where to locate the character * @param chr the character to locate * @return a substring starting at the last location of @p chr - * - * @see cx_strrchr_m() */ -CX_EXTERN CX_NODISCARD -cxstring cx_strrchr(cxstring string, int chr); - -/** - * Returns a substring starting at the location of the last occurrence of the - * specified character. - * - * If the string does not contain the character, an empty string is returned. - * - * @param string the string where to locate the character - * @param chr the character to locate - * @return a substring starting at the last location of @p chr - * - * @see cx_strrchr() - */ -CX_EXTERN CX_NODISCARD -cxmutstr cx_strrchr_m(cxmutstr string, int chr); +#define cx_strrchr(string, chr) _Generic(cx_strcast_m(string), \ + cxstring: cx_strrchr_, \ + cxmutstr: cx_strrchr_m_)(cx_strcast_m(string), chr) +#endif /** * Searches for a specific substring. diff -r 36c0fb2b60b2 -r f889ffd07c86 src/string.c --- a/src/string.c Sun Dec 28 17:31:20 2025 +0100 +++ b/src/string.c Sun Dec 28 18:30:25 2025 +0100 @@ -178,7 +178,7 @@ return (cxstring) {string.ptr + start, length}; } -cxstring cx_strchr( +cxstring cx_strchr_( cxstring string, int chr ) { @@ -187,15 +187,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 ) { @@ -216,14 +208,6 @@ #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 diff -r 36c0fb2b60b2 -r f889ffd07c86 tests/test_string.c --- a/tests/test_string.c Sun Dec 28 17:31:20 2025 +0100 +++ b/tests/test_string.c Sun Dec 28 18:30:25 2025 +0100 @@ -373,10 +373,19 @@ cxstring result = cx_strchr(str, 'w'); CX_TEST_ASSERT(result.length == 35); CX_TEST_ASSERT(0 == strcmp(result.ptr, "will find you - and I will kill you")); + } +} - // just for coverage, call the _m variant - cxmutstr m = cx_strchr_m(cx_mutstrn(NULL, 0), 'a'); - CX_TEST_ASSERT(0 == cx_strcmp(m, "")); +CX_TEST(test_strchr_m) { + cxmutstr str = cx_mutstr((char*)"I will find you - and I will kill you"); + + CX_TEST_DO { + cxmutstr notfound = cx_strchr(str, 'x'); + CX_TEST_ASSERT(notfound.length == 0); + + cxmutstr result = cx_strchr(str, 'w'); + CX_TEST_ASSERT(result.length == 35); + CX_TEST_ASSERT(0 == strcmp(result.ptr, "will find you - and I will kill you")); } } @@ -397,10 +406,26 @@ result = cx_strrchr(str, 'X'); CX_TEST_ASSERT(0 == cx_strcmp(result, str)); + } +} - // just for coverage, call the _m variant - cxmutstr m = cx_strrchr_m(cx_mutstrn(NULL, 0), 'a'); - CX_TEST_ASSERT(0 == cx_strcmp(m, "")); +CX_TEST(test_strrchr_m) { + cxmutstr str = cx_mutstr((char*)"X will find you - and I will kill you"); + + CX_TEST_DO { + cxmutstr notfound = cx_strrchr(str, 'x'); + CX_TEST_ASSERT(notfound.length == 0); + + cxmutstr result = cx_strrchr(str, 'w'); + CX_TEST_ASSERT(result.length == 13); + CX_TEST_ASSERT(0 == strcmp(result.ptr, "will kill you")); + + result = cx_strrchr(str, 'u'); + CX_TEST_ASSERT(result.length == 1); + CX_TEST_ASSERT(0 == strcmp(result.ptr, "u")); + + result = cx_strrchr(str, 'X'); + CX_TEST_ASSERT(0 == cx_strcmp(result, str)); } } @@ -1653,7 +1678,9 @@ cx_test_register(suite, test_strsubs_c); cx_test_register(suite, test_strat); cx_test_register(suite, test_strchr); + cx_test_register(suite, test_strchr_m); cx_test_register(suite, test_strrchr); + cx_test_register(suite, test_strrchr_m); cx_test_register(suite, test_strstr); cx_test_register(suite, test_strcmp); cx_test_register(suite, test_strcasecmp);