builtin: improve performance of string.camel_to_snake (#21691)

This commit is contained in:
Turiiya 2024-06-18 08:16:10 +02:00 committed by GitHub
parent fb32951abd
commit 895bb87a32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 27 deletions

View File

@ -2617,48 +2617,54 @@ pub fn (s string) camel_to_snake() string {
if s.len == 0 { if s.len == 0 {
return '' 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_is_upper := false
mut prev_char := ` `
mut lower_c := `_` mut lower_c := `_`
mut c_is_upper := false mut c_is_upper := false
mut b := unsafe { malloc_noscan(2 * s.len + 1) } mut pos := 1
mut i := 0 for i in pos .. s.len {
for c in s { c := s[i]
c_is_upper = c >= `A` && c <= `Z` c_is_upper = c >= `A` && c <= `Z`
lower_c = if c_is_upper { c + 32 } else { c } lower_c = if c_is_upper { c + 32 } else { c }
if i > 0 { if prev_is_upper == false && c_is_upper {
if prev_is_upper == false && c_is_upper { // aB => a_b, if prev has `_`, then do not add `_`
// aB => a_b, if prev has `_`, then do not add `_` unsafe {
unsafe { if b[pos - 1] != `_` {
if b[i - 1] != `_` { b[pos] = `_`
b[i] = `_` pos++
i++
}
} }
} else if prev_is_upper && c_is_upper == false && c != `_` { }
// Ba => _ba, if prev has `_`, then do not add `_` } else if prev_is_upper && c_is_upper == false && c != `_` {
if i > 1 { // Ba => _ba, if prev has `_`, then do not add `_`
unsafe { unsafe {
if b[i - 2] != `_` { if b[pos - 2] != `_` {
prev_char = b[i - 1] prev_char = b[pos - 1]
b[i - 1] = `_` b[pos - 1] = `_`
b[i] = prev_char b[pos] = prev_char
i++ pos++
}
}
} }
} }
} }
unsafe { unsafe {
b[i] = lower_c b[pos] = lower_c
} }
prev_is_upper = c_is_upper prev_is_upper = c_is_upper
i++ pos++
} }
unsafe { 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 // snake_to_camel convert string from snake_case to camelCase

View File

@ -1525,6 +1525,7 @@ fn test_contains_byte() {
fn test_camel_to_snake() { fn test_camel_to_snake() {
assert 'Abcd'.camel_to_snake() == 'abcd' assert 'Abcd'.camel_to_snake() == 'abcd'
assert 'aaBB'.camel_to_snake() == 'aa_bb' assert 'aaBB'.camel_to_snake() == 'aa_bb'
assert 'aaBbCcDD'.camel_to_snake() == 'aa_bb_cc_dd'
assert 'BBaa'.camel_to_snake() == 'b_baa' assert 'BBaa'.camel_to_snake() == 'b_baa'
assert 'aa_BB'.camel_to_snake() == 'aa_bb' assert 'aa_BB'.camel_to_snake() == 'aa_bb'
} }
@ -1532,6 +1533,7 @@ fn test_camel_to_snake() {
fn test_snake_to_camel() { fn test_snake_to_camel() {
assert 'abcd'.snake_to_camel() == 'Abcd' assert 'abcd'.snake_to_camel() == 'Abcd'
assert 'ab_cd'.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'
assert '_abcd_'.snake_to_camel() == 'Abcd' assert '_abcd_'.snake_to_camel() == 'Abcd'
} }