diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 8975f3d82a..8b6fa4b92e 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -2617,48 +2617,54 @@ pub fn (s string) camel_to_snake() string { if s.len == 0 { return '' } + lower_first_char := if s[0] >= `A` && s[0] <= `Z` { s[0] + 32 } else { s[0] } + if s.len == 1 { + return lower_first_char.ascii_str() + } + mut b := unsafe { malloc_noscan(2 * s.len + 1) } + second_char := if s[1] >= `A` && s[1] <= `Z` { `_` } else { s[1] } + unsafe { + b[0] = lower_first_char + b[1] = second_char + } + mut prev_char := second_char mut prev_is_upper := false - mut prev_char := ` ` mut lower_c := `_` mut c_is_upper := false - mut b := unsafe { malloc_noscan(2 * s.len + 1) } - mut i := 0 - for c in s { + mut pos := 1 + for i in pos .. s.len { + c := s[i] c_is_upper = c >= `A` && c <= `Z` lower_c = if c_is_upper { c + 32 } else { c } - if i > 0 { - if prev_is_upper == false && c_is_upper { - // aB => a_b, if prev has `_`, then do not add `_` - unsafe { - if b[i - 1] != `_` { - b[i] = `_` - i++ - } + if prev_is_upper == false && c_is_upper { + // aB => a_b, if prev has `_`, then do not add `_` + unsafe { + if b[pos - 1] != `_` { + b[pos] = `_` + pos++ } - } else if prev_is_upper && c_is_upper == false && c != `_` { - // Ba => _ba, if prev has `_`, then do not add `_` - if i > 1 { - unsafe { - if b[i - 2] != `_` { - prev_char = b[i - 1] - b[i - 1] = `_` - b[i] = prev_char - i++ - } - } + } + } else if prev_is_upper && c_is_upper == false && c != `_` { + // Ba => _ba, if prev has `_`, then do not add `_` + unsafe { + if b[pos - 2] != `_` { + prev_char = b[pos - 1] + b[pos - 1] = `_` + b[pos] = prev_char + pos++ } } } unsafe { - b[i] = lower_c + b[pos] = lower_c } prev_is_upper = c_is_upper - i++ + pos++ } unsafe { - b[i] = 0 + b[pos] = 0 } - return unsafe { tos(b, i) } + return unsafe { tos(b, pos) } } // snake_to_camel convert string from snake_case to camelCase diff --git a/vlib/builtin/string_test.v b/vlib/builtin/string_test.v index 09661a69f1..2ab4a6cf73 100644 --- a/vlib/builtin/string_test.v +++ b/vlib/builtin/string_test.v @@ -1525,6 +1525,7 @@ fn test_contains_byte() { fn test_camel_to_snake() { assert 'Abcd'.camel_to_snake() == 'abcd' assert 'aaBB'.camel_to_snake() == 'aa_bb' + assert 'aaBbCcDD'.camel_to_snake() == 'aa_bb_cc_dd' assert 'BBaa'.camel_to_snake() == 'b_baa' assert 'aa_BB'.camel_to_snake() == 'aa_bb' } @@ -1532,6 +1533,7 @@ fn test_camel_to_snake() { fn test_snake_to_camel() { assert 'abcd'.snake_to_camel() == 'Abcd' assert 'ab_cd'.snake_to_camel() == 'AbCd' + assert 'ab_cd_efg'.snake_to_camel() == 'AbCdEfg' assert '_abcd'.snake_to_camel() == 'Abcd' assert '_abcd_'.snake_to_camel() == 'Abcd' }