From 50b4d7aa3573f3da9b59cddf2f59075d804fbfef Mon Sep 17 00:00:00 2001 From: DragonFriend <211247049+ADragonFriend@users.noreply.github.com> Date: Wed, 14 May 2025 04:00:20 -0500 Subject: [PATCH] Add replace and treplace to String (#2127) * Add replace and treplace functions to String --- lib/std/core/builtin.c3 | 1 - lib/std/core/string.c3 | 33 +++++++++++++++++++++++++++++++++ releasenotes.md | 1 + test/unit/stdlib/core/string.c3 | 24 +++++++++++++++++++++++- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index e7171dc59..d677becf1 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -278,7 +278,6 @@ macro enum_by_name($Type, String enum_name) @builtin *> macro @enum_from_value($Type, #value, value) @builtin { - usz elements = $Type.elements; foreach (e : $Type.values) { if (e.#value == value) return e; diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 8adaa10d5..58e20bc00 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -154,6 +154,39 @@ fn String join(Allocator allocator, String[] s, String joiner) }; } +<* + Replace all instances of one substring with a different string. + + @param [in] self + @param [in] needle : `The string to be replaced` + @param [in] new_str : `The replacement string` + @param [&inout] allocator : `The allocator to use for the String` + @return "The new string with the elements replaced" +*> +fn String String.replace(self, Allocator allocator, String needle, String new_str) @nodiscard +{ + @pool() + { + String[] split = self.tsplit(needle); + return dstring::join(tmem, split, new_str).copy_str(mem); + }; +} + +<* + Replace all instances of one substring with a different string, allocating the new string on the temp allocator. + + @param [in] self + @param [in] needle : `The string to be replaced` + @param [in] new_str : `The replacement string` + @return "The new string with the elements replaced" +*> +fn String String.treplace(self, String needle, String new_str) +{ + String[] split = self.tsplit(needle); + return dstring::join(tmem, split, new_str).str_view(); +} + + <* Remove characters from the front and end of a string. diff --git a/releasenotes.md b/releasenotes.md index 403b0b128..5adc6b83f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -21,6 +21,7 @@ - std::ascii moved into std::core::ascii. Old _m variants are deprecated, as is uint methods. - Add `String.tokenize_all` to replace the now deprecated `String.splitter` - Add `String.count` to count the number of instances of a string. +- Add `String.replace` and `String.treplace` to replace substrings within a string. - Add `Duration * Int` and `Clock - Clock` overload. - Add `DateTime + Duration` overloads. diff --git a/test/unit/stdlib/core/string.c3 b/test/unit/stdlib/core/string.c3 index 9a6bee9ed..245489917 100644 --- a/test/unit/stdlib/core/string.c3 +++ b/test/unit/stdlib/core/string.c3 @@ -195,6 +195,28 @@ fn void test_split_to_buffer() free(strings); } +fn void test_treplace() +{ + String test = "Befriend some dragons?"; + assert(test.treplace("some", "all") == "Befriend all dragons?"); + assert(test.treplace("?", "!") == "Befriend some dragons!"); + assert(test.treplace("Never", "Always") == "Befriend some dragons?"); +} + +fn void test_replace() +{ + String test = "Befriend some dragons?"; + String val = test.replace(mem, "some", "all"); + test::eq(val, "Befriend all dragons?"); + free(val); + val = test.replace(mem, "?", "!"); + test::eq(val, "Befriend some dragons!"); + free(val); + val = test.replace(mem, "Never", "Always"); + test::eq(val, "Befriend some dragons?"); + free(val); +} + fn void test_index_of() { String test = "hello world hello"; @@ -283,4 +305,4 @@ fn void tokenize_all_skip_last() str.append("-"); } test::eq(str.str_view(), "foo--bar-baz-"); -} \ No newline at end of file +}