Mon, 22 Dec 2025 15:28:07 +0100
add support for any string to all cx_strreplace() variants
relates to #789
| 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/docs/Writerside/topics/string.h.md Mon Dec 22 00:20:41 2025 +0100 +++ b/docs/Writerside/topics/string.h.md Mon Dec 22 15:28:07 2025 +0100 @@ -196,17 +196,17 @@ ```C #include <cx/string.h> -cxmutstr cx_strreplace(cxstring str, - cxstring search, cxstring replacement); +cxmutstr cx_strreplace(AnyStr str, + AnyStr search, AnyStr replacement); -cxmutstr cx_strreplace_a(const CxAllocator *allocator, cxstring str, - cxstring search, cxstring replacement); +cxmutstr cx_strreplace_a(const CxAllocator *allocator, AnyStr str, + AnyStr search, AnyStr replacement); -cxmutstr cx_strreplacen(cxstring str, - cxstring search, cxstring replacement, size_t replmax); +cxmutstr cx_strreplacen(AnyStr str, + AnyStr search, AnyStr replacement, size_t replmax); -cxmutstr cx_strreplacen_a(const CxAllocator *allocator, cxstring str, - cxstring search, cxstring replacement, size_t replmax); +cxmutstr cx_strreplacen_a(const CxAllocator *allocator, AnyStr str, + AnyStr search, AnyStr replacement, size_t replmax); ``` The function `cx_strreplace()` allocates a new string which will contain a copy of `str`
--- a/src/cx/string.h Mon Dec 22 00:20:41 2025 +0100 +++ b/src/cx/string.h Mon Dec 22 15:28:07 2025 +0100 @@ -1006,6 +1006,27 @@ */ #define cx_strcasesuffix(string, suffix) cx_strcasesuffix_(cx_strcast(string), cx_strcast(suffix)) + +/** + * Replaces a string with another string. + * + * Internal function - do not use. + * + * @param allocator + * @param str + * @param search + * @param replacement + * @param replmax + * @return + * @see cx_strreplace_a() + * @see cx_strreplace() + * @see cx_strreplacen_a() + * @see cx_strreplacen() + */ +cx_attr_nodiscard cx_attr_nonnull +CX_EXPORT cxmutstr cx_strreplace_(const CxAllocator *allocator, + cxstring str, cxstring search, cxstring replacement, size_t replmax); + /** * Replaces a string with another string. * @@ -1017,16 +1038,15 @@ * If allocation fails, or the input string is empty, * the returned string will be empty. * - * @param allocator the allocator to use + * @param allocator (@c CxAllocator*) the allocator to use * @param str the string where replacements should be applied * @param search the string to search for * @param replacement the replacement string - * @param replmax maximum number of replacements - * @return the resulting string after applying the replacements + * @param replmax (@c size_t) maximum number of replacements + * @return (@c cxmutstr) the resulting string after applying the replacements */ -cx_attr_nodiscard cx_attr_nonnull -CX_EXPORT cxmutstr cx_strreplacen_a(const CxAllocator *allocator, - cxstring str, cxstring search, cxstring replacement, size_t replmax); +#define cx_strreplacen_a(allocator, str, search, replacement, replmax) \ + cx_strreplace_(allocator, cx_strcast(str), cx_strcast(search), cx_strcast(replacement), replmax) /** * Replaces a string with another string. @@ -1039,9 +1059,9 @@ * If allocation fails, or the input string is empty, * the returned string will be empty. * - * @param str (@c cxstring) the string where replacements should be applied - * @param search (@c cxstring) the string to search for - * @param replacement (@c cxstring) the replacement string + * @param str the string where replacements should be applied + * @param search the string to search for + * @param replacement the replacement string * @param replmax (@c size_t) maximum number of replacements * @return (@c cxmutstr) the resulting string after applying the replacements */ @@ -1058,9 +1078,9 @@ * the returned string will be empty. * * @param allocator (@c CxAllocator*) the allocator to use - * @param str (@c cxstring) the string where replacements should be applied - * @param search (@c cxstring) the string to search for - * @param replacement (@c cxstring) the replacement string + * @param str the string where replacements should be applied + * @param search the string to search for + * @param replacement the replacement string * @return (@c cxmutstr) the resulting string after applying the replacements */ #define cx_strreplace_a(allocator, str, search, replacement) \ @@ -1075,9 +1095,9 @@ * If allocation fails, or the input string is empty, * the returned string will be empty. * - * @param str (@c cxstring) the string where replacements should be applied - * @param search (@c cxstring) the string to search for - * @param replacement (@c cxstring) the replacement string + * @param str the string where replacements should be applied + * @param search the string to search for + * @param replacement the replacement string * @return (@c cxmutstr) the resulting string after applying the replacements */ #define cx_strreplace(str, search, replacement) \
--- a/src/string.c Mon Dec 22 00:20:41 2025 +0100 +++ b/src/string.c Mon Dec 22 15:28:07 2025 +0100 @@ -568,7 +568,7 @@ #endif } -cxmutstr cx_strreplacen_a( +cxmutstr cx_strreplace_( const CxAllocator *allocator, cxstring str, cxstring search,
--- a/tests/test_string.c Mon Dec 22 00:20:41 2025 +0100 +++ b/tests/test_string.c Mon Dec 22 15:28:07 2025 +0100 @@ -740,57 +740,53 @@ CxAllocator *alloc = &talloc.base; cxstring str = cx_str("test ababab string aba"); - cxstring longstr = cx_str( - "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd"); - cxstring notrail = cx_str("test abab"); - cxstring empty = cx_str(""); cxstring astr = cx_str("aaaaaaaaaa"); cxstring csstr = cx_str("test AB ab TEST xyz"); - cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger")); + cxmutstr repl = cx_strreplace(str, "abab", "muchlonger"); const char *expected = "test muchlongerab string aba"; - cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2); + cxmutstr repln = cx_strreplacen(str, "ab", "c", 2); const char *expectedn = "test ccab string aba"; - cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z")); + cxmutstr longrepl = cx_strreplace("xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd", "a", "z"); const char *longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd"; - cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z")); + cxmutstr replnotrail = cx_strreplace("test abab", "ab", "z"); const char *notrailexpect = "test zz"; - cxmutstr repleq = cx_strreplace(str, str, cx_str("hello")); + cxmutstr repleq = cx_strreplace(str, str, "hello"); const char *eqexpect = "hello"; - cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty - cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty); + cxmutstr replempty1 = cx_strreplace("", "ab", "c"); // expect: empty + cxmutstr replempty2 = cx_strreplace(str, "abab", ""); const char *emptyexpect2 = "test ab string aba"; - cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST ")); + cxmutstr replpre = cx_strreplace(str, "test ", "TEST "); const char *preexpected = "TEST ababab string aba"; - cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1); + cxmutstr replan1 = cx_strreplacen(astr, "a", "x", 1); const char *an1expected = "xaaaaaaaaa"; - cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4); + cxmutstr replan4 = cx_strreplacen(astr, "a", "x", 4); const char *an4expected = "xxxxaaaaaa"; - cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9); + cxmutstr replan9 = cx_strreplacen(astr, "a", "x", 9); const char *an9expected = "xxxxxxxxxa"; - cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10); + cxmutstr replan10 = cx_strreplacen(astr, "a", "x", 10); const char *an10expected = "xxxxxxxxxx"; - cxmutstr norepl = cx_strreplace(cx_strn("hello world", 11), cx_str("worlds"), cx_str("test")); + cxmutstr norepl = cx_strreplace(cx_strn("hello worlds", 11), "worlds", "test"); const char *noreplexpect = "hello world"; + cxmutstr repl1_a = cx_strreplace_a(alloc, csstr, "AB", "*"); + const char *expeced1_a = "test * ab TEST xyz"; + + cxmutstr repl2_a = cx_strreplace_a(alloc, csstr, "test", "TEST"); + const char *expected2_a = "TEST AB ab TEST xyz"; + CX_TEST_DO { - cxmutstr repl1_a = cx_strreplace_a(alloc, csstr, cx_str("AB"), cx_str("*")); - const char *expeced1_a = "test * ab TEST xyz"; - - cxmutstr repl2_a = cx_strreplace_a(alloc, csstr, cx_str("test"), cx_str("TEST")); - const char *expected2_a = "TEST AB ab TEST xyz"; - CX_TEST_ASSERT(repl.ptr != str.ptr); ASSERT_ZERO_TERMINATED(repl); CX_TEST_ASSERT(0 == strcmp(repl.ptr, expected));