mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin: add string.replace_char and string.normalize_tabs (#15239)
This commit is contained in:
parent
60094d95e2
commit
10f3c9f127
@ -495,6 +495,75 @@ pub fn (s string) replace_each(vals []string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// replace_char replaces all occurences of the character `rep` multiple occurences of the character passed in `with` with respect to `repeat`.
|
||||
// Example: assert '\tHello!'.replace_char(`\t`,` `,8) == ' Hello!'
|
||||
[direct_array_access]
|
||||
pub fn (s string) replace_char(rep u8, with u8, repeat int) string {
|
||||
$if !no_bounds_checking ? {
|
||||
if repeat <= 0 {
|
||||
panic('string.replace_char(): tab length too short')
|
||||
}
|
||||
}
|
||||
if s.len == 0 {
|
||||
return s.clone()
|
||||
}
|
||||
// TODO Allocating ints is expensive. Should be a stack array
|
||||
// - string.replace()
|
||||
mut idxs := []int{cap: s.len}
|
||||
defer {
|
||||
unsafe { idxs.free() }
|
||||
}
|
||||
// No need to do a contains(), it already traverses the entire string
|
||||
for i, ch in s {
|
||||
if ch == rep { // Found char? Mark its location
|
||||
idxs << i
|
||||
}
|
||||
}
|
||||
if idxs.len == 0 {
|
||||
return s.clone()
|
||||
}
|
||||
// Now we know the number of replacements we need to do and we can calc the len of the new string
|
||||
new_len := s.len + idxs.len * (repeat - 1)
|
||||
mut b := unsafe { malloc_noscan(new_len + 1) } // add space for the null byte at the end
|
||||
// Fill the new string
|
||||
mut b_i := 0
|
||||
mut s_idx := 0
|
||||
for rep_pos in idxs {
|
||||
for i in s_idx .. rep_pos { // copy everything up to piece being replaced
|
||||
unsafe {
|
||||
b[b_i] = s[i]
|
||||
}
|
||||
b_i++
|
||||
}
|
||||
s_idx = rep_pos + 1 // move string index past replacement
|
||||
for _ in 0 .. repeat { // copy replacement piece
|
||||
unsafe {
|
||||
b[b_i] = with
|
||||
}
|
||||
b_i++
|
||||
}
|
||||
}
|
||||
if s_idx < s.len { // if any original after last replacement, copy it
|
||||
for i in s_idx .. s.len {
|
||||
unsafe {
|
||||
b[b_i] = s[i]
|
||||
}
|
||||
b_i++
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
b[new_len] = 0
|
||||
return tos(b, new_len)
|
||||
}
|
||||
}
|
||||
|
||||
// normalize_tabs replaces all tab characters with `tab_len` amount of spaces
|
||||
// Example: assert '\t\tpop rax\t; pop rax'.normalize_tabs(2) == ' pop rax ; pop rax'
|
||||
[inline]
|
||||
pub fn (s string) normalize_tabs(tab_len int) string {
|
||||
return s.replace_char(`\t`, ` `, tab_len)
|
||||
}
|
||||
|
||||
// bool returns `true` if the string equals the word "true" it will return `false` otherwise.
|
||||
pub fn (s string) bool() bool {
|
||||
return s == 'true' || s == 't' // TODO t for pg, remove
|
||||
|
@ -380,6 +380,18 @@ fn test_replace_each() {
|
||||
assert s2.replace_each(['hello_world', 'aaa', 'hello', 'bbb']) == 'aaa bbb'
|
||||
}
|
||||
|
||||
fn test_replace_char() {
|
||||
assert 'azert'.replace_char(`z`, `s`, 2) == 'assert'
|
||||
assert '\rHello!\r'.replace_char(`\r`, `\n`, 1) == '\nHello!\n'
|
||||
assert 'Hello!'.replace_char(`l`, `e`, 4) == 'Heeeeeeeeeo!'
|
||||
assert '1141'.replace_char(`1`, `8`, 2) == '8888488'
|
||||
}
|
||||
|
||||
fn test_normalize_tabs() {
|
||||
assert '\t\tHello!'.normalize_tabs(4) == ' Hello!'
|
||||
assert '\t\tHello!\t; greeting'.normalize_tabs(1) == ' Hello! ; greeting'
|
||||
}
|
||||
|
||||
fn test_itoa() {
|
||||
num := 777
|
||||
assert num.str() == '777'
|
||||
|
Loading…
Reference in New Issue
Block a user