From d6ce544dbff0897f932b842605521cc392117bfc Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 12 Sep 2024 23:16:51 +0800 Subject: [PATCH] builtin: fix string.trim() --- vlib/builtin/string.v | 45 ++++++++++++++++++++++++++++++++------ vlib/builtin/string_test.v | 11 +--------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 7a16bc01d4eb42..daf98f5f277672 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -1720,14 +1720,15 @@ pub fn (s string) trim(cutset string) string { if s == '' || cutset == '' { return s.clone() } - left, right := s.trim_indexes(cutset) - return s.substr(left, right) + if cutset.len_utf8() == cutset.len { + return s.trim_chars(cutset) + } else { + return s.trim_runes(cutset) + } } -// trim_indexes gets the new start and end indices of a string when any of the characters given in `cutset` were stripped from the start and end of the string. Should be used as an input to `substr()`. If the string contains only the characters in `cutset`, both values returned are zero. -// Example: left, right := '-hi-'.trim_indexes('-') @[direct_array_access] -pub fn (s string) trim_indexes(cutset string) (int, int) { +pub fn (s string) trim_chars(cutset string) string { mut pos_left := 0 mut pos_right := s.len - 1 mut cs_match := true @@ -1748,10 +1749,40 @@ pub fn (s string) trim_indexes(cutset string) (int, int) { } } if pos_left > pos_right { - return 0, 0 + return '' + } + } + return s.substr(pos_left, pos_right + 1) +} + +@[direct_array_access] +pub fn (s string) trim_runes(cutset string) string { + s_runes := s.runes() + c_runes := cutset.runes() + mut pos_left := 0 + mut pos_right := s_runes.len - 1 + mut cs_match := true + for pos_left <= s_runes.len && pos_right >= -1 && cs_match { + cs_match = false + for cs in c_runes { + if s_runes[pos_left] == cs { + pos_left++ + cs_match = true + break + } + } + for cs in c_runes { + if s_runes[pos_right] == cs { + pos_right-- + cs_match = true + break + } + } + if pos_left > pos_right { + return '' } } - return pos_left, pos_right + 1 + return s_runes[pos_left..pos_right + 1].string() } // trim_left strips any of the characters given in `cutset` from the left of the string. diff --git a/vlib/builtin/string_test.v b/vlib/builtin/string_test.v index 0fdc976d3ad556..d7512179fbfd5a 100644 --- a/vlib/builtin/string_test.v +++ b/vlib/builtin/string_test.v @@ -921,16 +921,7 @@ fn test_trim() { assert 'banana'.trim('bna') == '' assert 'abc'.trim('ac') == 'b' assert 'aaabccc'.trim('ac') == 'b' -} - -fn test_trim_indexes() { - mut left, mut right := 0, 0 - left, right = '- -- - '.trim_indexes(' -') - assert left == 0 && right == 0 - left, right = '- hello-world!\t'.trim_indexes(' -\t') - assert left == 2 && right == 14 - left, right = 'abc'.trim_indexes('ac') - assert left == 1 && right == 2 + assert 'あいうえお'.trim('あい') == 'うえお' } fn test_trim_left() {