diff --git a/lib/std/core/dstring.c3 b/lib/std/core/dstring.c3 index 406014ef8..9d5c78646 100644 --- a/lib/std/core/dstring.c3 +++ b/lib/std/core/dstring.c3 @@ -48,6 +48,56 @@ fn DString new(String c = "", Allocator allocator = allocator::heap()) fn DString temp_new(String s = "") => new(s, allocator::temp()) @inline; + +fn void DString.replace_char(self, char ch, char replacement) +{ + StringData* data = self.data(); + foreach (&c : data.chars[:data.len]) + { + if (*c == ch) *c = replacement; + } +} + +fn void DString.replace(&self, String needle, String replacement) +{ + StringData* data = self.data(); + usz needle_len = needle.len; + if (!data || data.len < needle_len) return; + usz replace_len = replacement.len; + if (needle_len == 1 && replace_len == 1) + { + self.replace_char(needle[0], replacement[0]); + return; + } + @pool(data.allocator) { + String str = self.tcopy_str(); + self.clear(); + usz len = str.len; + usz match = 0; + foreach (i, c : str) + { + if (c == needle[match]) + { + match++; + if (match == needle_len) + { + self.append_chars(replacement); + match = 0; + continue; + } + continue; + } + if (match > 0) + { + self.append_chars(str[i - match:match]); + match = 0; + } + self.append_char(c); + } + if (match > 0) self.append_chars(str[^match:match]); + }; +} + fn DString DString.new_concat(self, DString b, Allocator allocator = allocator::heap()) { DString string; diff --git a/releasenotes.md b/releasenotes.md index 9b02691f3..3f9ed21b7 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -78,6 +78,7 @@ - Deprecated `path.append`, `path.tappend`, `getcwd`, `tgetcwd`, `path.absolute`, `ls`. - Deprecated `env::get_config_dir`, replaced by `env::new_get_config_dir`. - Added `path.has_extension`, `path.new_append`, `path.temp_append`, `new_cwd`, `temp_cwd`, `path.new_absolute`, `new_ls`, `temp_ls`. +- Added `dstring.replace` ## 0.6.1 Change list diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index 31c1f976a..34d479e6d 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -205,7 +205,7 @@ static bool exec_arg_append_to_scratch(Expr *arg) case CONST_TYPEID: if (!arg->const_expr.typeid->name) { - RETURN_PRINT_ERROR_AT(NULL, arg, "The type '%s' has no trivial name.", + RETURN_PRINT_ERROR_AT(false, arg, "The type '%s' has no trivial name.", type_quoted_error_string(arg->const_expr.typeid)); } scratch_buffer_append(arg->const_expr.typeid->name); diff --git a/src/utils/find_msvc.c b/src/utils/find_msvc.c index 3eaea34f2..667528f1c 100644 --- a/src/utils/find_msvc.c +++ b/src/utils/find_msvc.c @@ -39,7 +39,7 @@ static char *find_visual_studio(void) const char *install_path = NULL; // Call vswhere.exe - if (!execute_cmd_failable(scratch_buffer_to_string(), &install_path)) + if (!execute_cmd_failable(scratch_buffer_to_string(), &install_path, NULL)) { error_exit("Failed to find vswhere.exe to detect MSVC."); } diff --git a/test/unit/stdlib/core/dstring.c3 b/test/unit/stdlib/core/dstring.c3 index 94c40a0bd..d0b79ecd5 100644 --- a/test/unit/stdlib/core/dstring.c3 +++ b/test/unit/stdlib/core/dstring.c3 @@ -2,6 +2,14 @@ module std::core::dstring2 @test; const TEST_STRING = "hello world"; +fn void test_replace() +{ + DString hello = dstring::new("Hello world where are you? Are you here too?"); + defer hello.free(); + hello.replace("u", "ooo"); + assert(hello.str_view() == "Hello world where are yoooo? Are yoooo here too?"); +} + fn void test_delete() { {