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.
|
// bool returns `true` if the string equals the word "true" it will return `false` otherwise.
|
||||||
pub fn (s string) bool() bool {
|
pub fn (s string) bool() bool {
|
||||||
return s == 'true' || s == 't' // TODO t for pg, remove
|
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'
|
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() {
|
fn test_itoa() {
|
||||||
num := 777
|
num := 777
|
||||||
assert num.str() == '777'
|
assert num.str() == '777'
|
||||||
|
Loading…
Reference in New Issue
Block a user