Delete 16 .js.v files whose functions already exist in generic .v (math abs/bits/cbrt/exp/floor/invtrig/sin/sinh/tan/tanh/unsafe, builtin rune/utf8, strconv f32_str placeholder, strings repeat). Port strings.repeat/repeat_string to pure V in strings.v (keep strings.c.v for the C backend); port utf8_str_len (only defined in utf8.js.v) to builtin/utf8.v so the API is preserved on all backends. wyhash and atof are intentionally untouched (see #31084).
180 lines
5.7 KiB
V
180 lines
5.7 KiB
V
module strings
|
|
|
|
// import rand
|
|
// random returns a random string with `n` characters
|
|
/*
|
|
pub fn random(n int) string {
|
|
buf := vmalloc(n)
|
|
for i in 0..n {
|
|
buf[i] = rand.next()
|
|
}
|
|
return tos(buf)
|
|
}
|
|
*/
|
|
|
|
// find_between_pair_byte returns the string found between the pair of marks defined
|
|
// by `start` and `end`.
|
|
// As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the
|
|
// `string` type, this function can extract content between *nested* marks in `input`.
|
|
// If `start` and `end` marks are nested in `input`, the characters
|
|
// between the *outermost* mark pair is returned. It is expected that `start` and `end`
|
|
// marks are *balanced*, meaning that the amount of `start` marks equal the
|
|
// amount of `end` marks in the `input`. An empty string is returned otherwise.
|
|
// Using two identical marks as `start` and `end` results in undefined output behavior.
|
|
// find_between_pair_byte is the fastest in the find_between_pair_* family of functions.
|
|
// Example: assert strings.find_between_pair_u8('(V) (NOT V)',`(`,`)`) == 'V'
|
|
// Example: assert strings.find_between_pair_u8('s {X{Y}} s',`{`,`}`) == 'X{Y}'
|
|
pub fn find_between_pair_u8(input string, start u8, end u8) string {
|
|
mut marks := 0
|
|
mut start_index := -1
|
|
for i, b in input {
|
|
if b == start {
|
|
if start_index == -1 {
|
|
start_index = i + 1
|
|
}
|
|
marks++
|
|
continue
|
|
}
|
|
if start_index > 0 {
|
|
if b == end {
|
|
marks--
|
|
if marks == 0 {
|
|
return input[start_index..i]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ''
|
|
}
|
|
|
|
// find_between_pair_rune returns the string found between the pair of marks defined by `start` and `end`.
|
|
// As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the
|
|
// `string` type, this function can extract content between *nested* marks in `input`.
|
|
// If `start` and `end` marks are nested in `input`, the characters
|
|
// between the *outermost* mark pair is returned. It is expected that `start` and `end`
|
|
// marks are *balanced*, meaning that the amount of `start` marks equal the
|
|
// amount of `end` marks in the `input`. An empty string is returned otherwise.
|
|
// Using two identical marks as `start` and `end` results in undefined output behavior.
|
|
// find_between_pair_rune is inbetween the fastest and slowest in the find_between_pair_* family of functions.
|
|
// Example: assert strings.find_between_pair_rune('(V) (NOT V)',`(`,`)`) == 'V'
|
|
// Example: assert strings.find_between_pair_rune('s {X{Y}} s',`{`,`}`) == 'X{Y}'
|
|
pub fn find_between_pair_rune(input string, start rune, end rune) string {
|
|
mut marks := 0
|
|
mut start_index := -1
|
|
runes := input.runes()
|
|
for i, r in runes {
|
|
if r == start {
|
|
if start_index == -1 {
|
|
start_index = i + 1
|
|
}
|
|
marks++
|
|
continue
|
|
}
|
|
if start_index > 0 {
|
|
if r == end {
|
|
marks--
|
|
if marks == 0 {
|
|
return runes[start_index..i].string()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ''
|
|
}
|
|
|
|
// find_between_pair_string returns the string found between the pair of marks defined by `start` and `end`.
|
|
// As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the
|
|
// `string` type, this function can extract content between *nested* marks in `input`.
|
|
// If `start` and `end` marks are nested in `input`, the characters
|
|
// between the *outermost* mark pair is returned. It is expected that `start` and `end`
|
|
// marks are *balanced*, meaning that the amount of `start` marks equal the
|
|
// amount of `end` marks in the `input`. An empty string is returned otherwise.
|
|
// Using two identical marks as `start` and `end` results in undefined output behavior.
|
|
// find_between_pair_string is the slowest in the find_between_pair_* function family.
|
|
// Example: assert strings.find_between_pair_string('/*V*/ /*NOT V*/','/*','*/') == 'V'
|
|
// Example: assert strings.find_between_pair_string('s {{X{{Y}}}} s','{{','}}') == 'X{{Y}}'
|
|
pub fn find_between_pair_string(input string, start string, end string) string {
|
|
mut start_index := -1
|
|
mut marks := 0
|
|
start_runes := start.runes()
|
|
end_runes := end.runes()
|
|
runes := input.runes()
|
|
mut i := 0
|
|
for ; i < runes.len; i++ {
|
|
start_slice := runes#[i..i + start_runes.len]
|
|
if start_slice == start_runes {
|
|
i = i + start_runes.len - 1
|
|
if start_index < 0 {
|
|
start_index = i + 1
|
|
}
|
|
marks++
|
|
continue
|
|
}
|
|
if start_index > 0 {
|
|
end_slice := runes#[i..i + end_runes.len]
|
|
if end_slice == end_runes {
|
|
marks--
|
|
if marks == 0 {
|
|
return runes[start_index..i].string()
|
|
}
|
|
i = i + end_runes.len - 1
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
return ''
|
|
}
|
|
|
|
// split_capital returns an array containing the contents of `s` split by capital letters.
|
|
// Example: assert strings.split_capital('XYZ') == ['X', 'Y', 'Z']
|
|
// Example: assert strings.split_capital('XYStar') == ['X', 'Y', 'Star']
|
|
pub fn split_capital(s string) []string {
|
|
mut res := []string{}
|
|
mut word_start := 0
|
|
for idx, c in s {
|
|
if c.is_capital() {
|
|
if word_start != idx {
|
|
res << s#[word_start..idx]
|
|
}
|
|
word_start = idx
|
|
continue
|
|
}
|
|
}
|
|
if word_start != s.len {
|
|
res << s#[word_start..]
|
|
}
|
|
return res
|
|
}
|
|
|
|
// strings.repeat returns a string with `n` repetitions of the character `c`.
|
|
// It returns an empty string if `n` is 0 or negative.
|
|
@[direct_array_access]
|
|
pub fn repeat(c u8, n int) string {
|
|
if n <= 0 {
|
|
return ''
|
|
}
|
|
arr := [c].repeat(n)
|
|
return arr.bytestr()
|
|
}
|
|
|
|
// strings.repeat_string returns a string with `n` repetitions of the substring `s`.
|
|
// It returns an empty string if `n` is 0 or negative, or if `s` is empty.
|
|
// Note: strings.repeat, that repeats a single byte, is faster than
|
|
// strings.repeat_string called for a 1 char string.
|
|
@[direct_array_access]
|
|
pub fn repeat_string(s string, n int) string {
|
|
if n <= 0 || s.len == 0 {
|
|
return ''
|
|
}
|
|
slen := s.len
|
|
blen := slen * n
|
|
mut buf := []u8{len: blen}
|
|
for bi in 0 .. n {
|
|
bislen := bi * slen
|
|
for si in 0 .. slen {
|
|
buf[bislen + si] = s[si]
|
|
}
|
|
}
|
|
return buf.bytestr()
|
|
}
|