Sun, 21 Dec 2025 23:58:30 +0100
add support for any string to cx_strstr() and cx_strstr_m()
relates to #789
| CHANGELOG | file | annotate | diff | comparison | revisions | |
| docs/Writerside/topics/about.md | file | annotate | diff | comparison | revisions | |
| docs/Writerside/topics/string.h.md | file | annotate | diff | comparison | revisions | |
| src/cx/string.h | file | annotate | diff | comparison | revisions | |
| src/string.c | file | annotate | diff | comparison | revisions | |
| tests/test_string.c | file | annotate | diff | comparison | revisions |
--- a/CHANGELOG Sun Dec 21 11:09:46 2025 +0100 +++ b/CHANGELOG Sun Dec 21 23:58:30 2025 +0100 @@ -18,7 +18,7 @@ * changes cxBufferTerminate() to automatically shrink the buffer * changes cxBufferTerminate() so that position and size are equal after a successful operation * changes cxBufferPutString() to accept any kind of string that cx_strcast() supports - * changes multiple string.h functions automatically apply cx_strcast() where possible + * changes that multiple string.h functions now also automatically apply cx_strcast() where possible * changes the names of cxDefineDestructor() and cxDefineAdvancedDestructor() to cxSetDestructor() and cxSetdvancedDestructor() * changes the name of cxCollectionCompareFunc() to cxSetCompareFunc()
--- a/docs/Writerside/topics/about.md Sun Dec 21 11:09:46 2025 +0100 +++ b/docs/Writerside/topics/about.md Sun Dec 21 23:58:30 2025 +0100 @@ -45,7 +45,7 @@ * changes cxBufferTerminate() to automatically shrink the buffer * changes cxBufferTerminate() so that position and size are equal after a successful operation * changes cxBufferPutString() to accept any kind of string that cx_strcast() supports -* changes multiple string.h functions automatically apply cx_strcast() where possible +* changes that multiple string.h functions now also automatically apply cx_strcast() where possible * changes the names of cxDefineDestructor() and cxDefineAdvancedDestructor() to cxSetDestructor() and cxSetdvancedDestructor() * changes the name of cxCollectionCompareFunc() to cxSetCompareFunc()
--- a/docs/Writerside/topics/string.h.md Sun Dec 21 11:09:46 2025 +0100 +++ b/docs/Writerside/topics/string.h.md Sun Dec 21 23:58:30 2025 +0100 @@ -157,7 +157,7 @@ cxstring cx_strrchr(cxstring string, int chr); -cxstring cx_strstr(cxstring string, cxstring search); +cxstring cx_strstr(cxstring string, AnyStr search); cxstring cx_strsubs(cxstring string, size_t start); @@ -169,7 +169,7 @@ cxmutstr cx_strrchr_m(cxmutstr string, int chr); -cxmutstr cx_strstr_m(cxmutstr string, cxstring search); +cxmutstr cx_strstr_m(cxmutstr string, AnyStr search); cxmutstr cx_strsubs_m(cxmutstr string, size_t start);
--- a/src/cx/string.h Sun Dec 21 11:09:46 2025 +0100 +++ b/src/cx/string.h Sun Dec 21 23:58:30 2025 +0100 @@ -639,23 +639,18 @@ CX_EXPORT cxmutstr cx_strrchr_m(cxmutstr string, int chr); /** - * Returns a substring starting at the location of the first occurrence of the - * specified string. + * Searches for a specific substring. * - * If @p haystack does not contain @p needle, an empty string is returned. - * - * If @p needle is an empty string, the complete @p haystack is - * returned. + * Internal function - do not use. * * @param haystack the string to be scanned - * @param needle string containing the sequence of characters to match - * @return a substring starting at the first occurrence of - * @p needle, or an empty string, if the sequence is not - * contained - * @see cx_strstr_m() + * @param needle string containing the sequence of characters to match + * @return a substring starting at the first occurrence of @p needle, + * or an empty string, if the sequence is not contained + * @see cx_strstr() */ cx_attr_nodiscard -CX_EXPORT cxstring cx_strstr(cxstring haystack, cxstring needle); +CX_EXPORT cxstring cx_strstr_(cxstring haystack, cxstring needle); /** * Returns a substring starting at the location of the first occurrence of the @@ -666,15 +661,44 @@ * If @p needle is an empty string, the complete @p haystack is * returned. * + * @param haystack (@c cxstring) the string to be scanned + * @param needle string containing the sequence of characters to match + * @return (@c cxstring) a substring starting at the first occurrence of + * @p needle, or an empty string, if the sequence is not contained + * @see cx_strstr_m() + */ +#define cx_strstr(haystack, needle) cx_strstr_(haystack, cx_strcast(needle)) + +/** + * Searches for a specific substring. + * + * Internal function - do not use. + * * @param haystack the string to be scanned - * @param needle string containing the sequence of characters to match - * @return a substring starting at the first occurrence of - * @p needle, or an empty string, if the sequence is not - * contained + * @param needle string containing the sequence of characters to match + * @return a substring starting at the first occurrence of @p needle, + * or an empty string, if the sequence is not contained + * @see cx_strstr_m() + */ +cx_attr_nodiscard +CX_EXPORT cxmutstr cx_strstr_m_(cxmutstr haystack, cxstring needle); + +/** + * Returns a substring starting at the location of the first occurrence of the + * specified string. + * + * If @p haystack does not contain @p needle, an empty string is returned. + * + * If @p needle is an empty string, the complete @p haystack is + * returned. + * + * @param haystack (@c cxmutstr) the string to be scanned + * @param needle string containing the sequence of characters to match + * @return (@c cxmutstr) a substring starting at the first occurrence of + * @p needle, or an empty string, if the sequence is not contained * @see cx_strstr() */ -cx_attr_nodiscard -CX_EXPORT cxmutstr cx_strstr_m(cxmutstr haystack, cxstring needle); +#define cx_strstr_m(haystack, needle) cx_strstr_m_(haystack, cx_strcast(needle)) /** * Splits a given string using a delimiter string.
--- a/src/string.c Sun Dec 21 11:09:46 2025 +0100 +++ b/src/string.c Sun Dec 21 23:58:30 2025 +0100 @@ -248,10 +248,7 @@ #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; } @@ -321,7 +318,7 @@ return result; } -cxmutstr cx_strstr_m( +cxmutstr cx_strstr_m_( cxmutstr haystack, cxstring needle ) {
--- a/tests/test_string.c Sun Dec 21 11:09:46 2025 +0100 +++ b/tests/test_string.c Sun Dec 21 23:58:30 2025 +0100 @@ -162,6 +162,12 @@ CX_TEST_ASSERT(0 == cx_strcmp(dup, "test str")); ASSERT_ZERO_TERMINATED(dup); cx_strfree_a(alloc, &dup); + + // copy a plain C-string + CX_TEST_ASSERT(0 == cx_strcpy_a(alloc, &dup, "a c-string test")); + CX_TEST_ASSERT(0 == cx_strcmp(dup, "a c-string test")); + ASSERT_ZERO_TERMINATED(dup); + cx_strfree_a(alloc, &dup); } cx_testing_allocator_destroy(&talloc); } @@ -293,14 +299,14 @@ cxmutstr longstrresult = cx_mutstrn(longstrc+256, longstrlen-256); CX_TEST_DO { - cxstring notfound = cx_strstr(str, cx_str("no match")); + cxstring notfound = cx_strstr(str, "no match"); CX_TEST_ASSERT(notfound.length == 0); - cxstring result = cx_strstr(str, cx_str("match")); + cxstring result = cx_strstr(str, "match"); CX_TEST_ASSERT(result.length == 20); CX_TEST_ASSERT(0 == strcmp(result.ptr, "match in this string")); - result = cx_strstr(str, cx_str("")); + result = cx_strstr(str, ""); CX_TEST_ASSERT(result.length == str.length); CX_TEST_ASSERT(0 == strcmp(result.ptr, str.ptr));