Make all string.index functions return ?int

pull/13693/head
Tarcisio Gruppi 2022-03-08 22:13:17 -03:00
parent 3f1e232c9b
commit f1873908ea
No known key found for this signature in database
GPG Key ID: 36F5005FCAF5C057
15 changed files with 86 additions and 123 deletions

View File

@ -570,16 +570,16 @@ fn get_all_modules() []string {
mut start_token := '<a href="/mod'
end_token := '</a>'
// get the start index of the module entry
mut start_index := s.index_after(start_token, read_len)
mut start_index := s.index_after(start_token, read_len) or { -1 }
if start_index == -1 {
break
}
// get the index of the end of anchor (a) opening tag
// we use the previous start_index to make sure we are getting a module and not just a random 'a' tag
start_token = '">'
start_index = s.index_after(start_token, start_index) + start_token.len
start_index = s.index_after(start_token, start_index) or { -1 } + start_token.len
// get the index of the end of module entry
end_index := s.index_after(end_token, start_index)
end_index := s.index_after(end_token, start_index) or { -1 }
if end_index == -1 {
break
}

View File

@ -4,11 +4,11 @@ fn main() {
html := http.get_text('https://news.ycombinator.com')
mut pos := 0
for {
pos = html.index_after('https://', pos + 1)
pos = html.index_after('https://', pos + 1) or { -1 }
if pos == -1 {
break
}
end := html.index_after('"', pos)
end := html.index_after('"', pos) or { html.len }
println(html[pos..end])
}
}

View File

@ -319,11 +319,11 @@ pub fn (a string) clone() string {
// replace_once replaces the first occurence of `rep` with the string passed in `with`.
pub fn (s string) replace_once(rep string, with string) string {
idx := s.index_(rep)
if idx == -1 {
if idx := s.index(rep) {
return s.substr(0, idx) + with + s.substr(idx + rep.len, s.len)
} else {
return s.clone()
}
return s.substr(0, idx) + with + s.substr(idx + rep.len, s.len)
}
// replace replaces all occurences of `rep` with the string passed in `with`.
@ -343,10 +343,7 @@ pub fn (s string) replace(rep string, with string) string {
}
mut idx := 0
for {
idx = s.index_after(rep, idx)
if idx == -1 {
break
}
idx = s.index_after(rep, idx) or { break }
idxs << idx
idx += rep.len
}
@ -419,7 +416,7 @@ pub fn (s string) replace_each(vals []string) string {
with := vals[rep_i + 1]
for {
idx = s_.index_after(rep, idx)
idx = s_.index_after(rep, idx) or { -1 }
if idx == -1 {
break
}
@ -899,11 +896,11 @@ pub fn (s string) substr_ni(_start int, _end int) string {
}
// index returns the position of the first character of the input string.
// It will return `-1` if the input string can't be found.
// It will return `none` if the input string can't be found.
[direct_array_access]
fn (s string) index_(p string) int {
pub fn (s string) index(p string) ?int {
if p.len > s.len || p.len == 0 {
return -1
return none
}
if p.len > 2 {
return s.index_kmp(p)
@ -919,24 +916,14 @@ fn (s string) index_(p string) int {
}
i++
}
return -1
}
// index returns the position of the first character of the input string.
// It will return `none` if the input string can't be found.
pub fn (s string) index(p string) ?int {
idx := s.index_(p)
if idx == -1 {
return none
}
return idx
return none
}
// index_kmp does KMP search.
[direct_array_access; manualfree]
fn (s string) index_kmp(p string) int {
fn (s string) index_kmp(p string) ?int {
if p.len > s.len {
return -1
return none
}
mut prefix := []int{len: p.len}
defer {
@ -964,11 +951,11 @@ fn (s string) index_kmp(p string) int {
return i - p.len + 1
}
}
return -1
return none
}
// index_any returns the position of any of the characters in the input string - if found.
pub fn (s string) index_any(chars string) int {
pub fn (s string) index_any(chars string) ?int {
for i, ss in s {
for c in chars {
if c == ss {
@ -976,14 +963,14 @@ pub fn (s string) index_any(chars string) int {
}
}
}
return -1
return none
}
// last_index returns the position of the last occurence of the input string.
[direct_array_access]
fn (s string) last_index_(p string) int {
pub fn (s string) last_index(p string) ?int {
if p.len > s.len || p.len == 0 {
return -1
return none
}
mut i := s.len - p.len
for i >= 0 {
@ -996,30 +983,21 @@ fn (s string) last_index_(p string) int {
}
i--
}
return -1
}
// last_index returns the position of the last occurence of the input string.
pub fn (s string) last_index(p string) ?int {
idx := s.last_index_(p)
if idx == -1 {
return none
}
return idx
return none
}
// index_after returns the position of the input string, starting search from `start` position.
[direct_array_access]
pub fn (s string) index_after(p string, start int) int {
pub fn (s string) index_after(p string, start int) ?int {
if p.len > s.len {
return -1
return none
}
mut strt := start
if start < 0 {
strt = 0
}
if start >= s.len {
return -1
return none
}
mut i := strt
for i < s.len {
@ -1034,35 +1012,35 @@ pub fn (s string) index_after(p string, start int) int {
}
i++
}
return -1
return none
}
// index_byte returns the index of byte `c` if found in the string.
// index_byte returns -1 if the byte can not be found.
// index_byte returns `none` if the byte can not be found.
[direct_array_access]
pub fn (s string) index_byte(c byte) int {
pub fn (s string) index_byte(c byte) ?int {
for i in 0 .. s.len {
if unsafe { s.str[i] } == c {
return i
}
}
return -1
return none
}
// last_index_byte returns the index of the last occurence of byte `c` if found in the string.
// last_index_byte returns -1 if the byte is not found.
// last_index_byte returns `none` if the byte is not found.
[direct_array_access]
pub fn (s string) last_index_byte(c byte) int {
pub fn (s string) last_index_byte(c byte) ?int {
for i := s.len - 1; i >= 0; i-- {
if unsafe { s.str[i] == c } {
return i
}
}
return -1
return none
}
// count returns the number of occurrences of `substr` in the string.
// count returns -1 if no `substr` could be found.
// count returns 0 if no `substr` could be found.
[direct_array_access]
pub fn (s string) count(substr string) int {
if s.len == 0 || substr.len == 0 {
@ -1088,10 +1066,7 @@ pub fn (s string) count(substr string) int {
mut i := 0
for {
i = s.index_after(substr, i)
if i == -1 {
return n
}
i = s.index_after(substr, i) or { return n }
i += substr.len
n++
}
@ -1103,10 +1078,11 @@ pub fn (s string) contains(substr string) bool {
if substr.len == 0 {
return true
}
if s.index_(substr) == -1 {
if _ := s.index(substr) {
return true
} else {
return false
}
return true
}
// contains_any returns `true` if the string contains any chars in `chars`.
@ -1294,16 +1270,10 @@ pub fn (s string) is_title() bool {
// find_between returns the string found between `start` string and `end` string.
// Example: assert 'hey [man] how you doin'.find_between('[', ']') == 'man'
pub fn (s string) find_between(start string, end string) string {
start_pos := s.index_(start)
if start_pos == -1 {
return ''
}
start_pos := s.index(start) or { return '' }
// First get everything to the right of 'start'
val := s[start_pos + start.len..]
end_pos := val.index_(end)
if end_pos == -1 {
return val
}
end_pos := val.index(end) or { return val }
return val[..end_pos]
}
@ -1582,11 +1552,11 @@ pub fn (s &string) free() {
// Example: assert 'abcd'.before('.') == 'abcd'
// TODO: deprecate and remove either .before or .all_before
pub fn (s string) before(sub string) string {
pos := s.index_(sub)
if pos == -1 {
if pos := s.index(sub) {
return s[..pos]
} else {
return s.clone()
}
return s[..pos]
}
// all_before returns the contents before `sub` in the string.
@ -1595,11 +1565,11 @@ pub fn (s string) before(sub string) string {
// Example: assert 'abcd'.all_before('.') == 'abcd'
pub fn (s string) all_before(sub string) string {
// TODO remove dup method
pos := s.index_(sub)
if pos == -1 {
if pos := s.index(sub) {
return s[..pos]
} else {
return s.clone()
}
return s[..pos]
}
// all_before_last returns the contents before the last occurence of `sub` in the string.
@ -1607,11 +1577,11 @@ pub fn (s string) all_before(sub string) string {
// Example: assert '23:34:45.234'.all_before_last(':') == '23:34'
// Example: assert 'abcd'.all_before_last('.') == 'abcd'
pub fn (s string) all_before_last(sub string) string {
pos := s.last_index_(sub)
if pos == -1 {
if pos := s.last_index(sub) {
return s[..pos]
} else {
return s.clone()
}
return s[..pos]
}
// all_after returns the contents after `sub` in the string.
@ -1619,11 +1589,11 @@ pub fn (s string) all_before_last(sub string) string {
// Example: assert '23:34:45.234'.all_after('.') == '234'
// Example: assert 'abcd'.all_after('z') == 'abcd'
pub fn (s string) all_after(sub string) string {
pos := s.index_(sub)
if pos == -1 {
if pos := s.index(sub) {
return s[pos + sub.len..]
} else {
return s.clone()
}
return s[pos + sub.len..]
}
// all_after_last returns the contents after the last occurence of `sub` in the string.
@ -1631,11 +1601,11 @@ pub fn (s string) all_after(sub string) string {
// Example: assert '23:34:45.234'.all_after_last(':') == '45.234'
// Example: assert 'abcd'.all_after_last('z') == 'abcd'
pub fn (s string) all_after_last(sub string) string {
pos := s.last_index_(sub)
if pos == -1 {
if pos := s.last_index(sub) {
return s[pos + sub.len..]
} else {
return s.clone()
}
return s[pos + sub.len..]
}
// after returns the contents after the last occurence of `sub` in the string.

View File

@ -961,8 +961,12 @@ fn test_string_to_rune() {
fn test_index_any() {
x := 'abcdefghij'
assert x.index_any('ef') == 4
assert x.index_any('fe') == 4
if idx := x.index_any('ef') {
assert idx == 4
}
if idx := x.index_any('fe') {
assert idx == 4
}
}
fn test_string_f64() {

View File

@ -94,8 +94,7 @@ pub fn decode_int_walpha(input string, alphabet Alphabet) ?int {
mut total := 0 // to hold the results
b58 := input.reverse()
for i, ch in b58 {
ch_i := alphabet.encode.bytestr().index_byte(ch)
if ch_i == -1 {
ch_i := alphabet.encode.bytestr().index_byte(ch) or {
return error(@MOD + '.' + @FN +
': input string contains values not found in the provided alphabet')
}

View File

@ -87,11 +87,11 @@ fn (mut r Reader) read_line() ?string {
return IError(&EndOfFileError{})
}
le := if r.is_mac_pre_osx_le { '\r' } else { '\n' }
mut i := r.data.index_after(le, r.row_pos)
mut i := r.data.index_after(le, r.row_pos) or { -1 }
if i == -1 {
if r.row_pos == 0 {
// check for pre osx mac line endings
i = r.data.index_after('\r', r.row_pos)
i = r.data.index_after('\r', r.row_pos) or { -1 }
if i != -1 {
r.is_mac_pre_osx_le = true
} else {

View File

@ -37,10 +37,7 @@ pub fn (mut w Writer) write(record []string) ?bool {
}
w.sb.write_string('"')
for field.len > 0 {
mut i := field.index_any('"\r\n')
if i < 0 {
i = field.len
}
mut i := field.index_any('"\r\n') or { field.len }
w.sb.write_string(field[..i])
field = field[i..]
if field.len > 0 {
@ -69,7 +66,10 @@ fn (w &Writer) field_needs_quotes(field string) bool {
if field == '' {
return false
}
if field.contains(w.delimiter.ascii_str()) || (field.index_any('"\r\n') != -1) {
if field.contains(w.delimiter.ascii_str()) {
return true
}
if _ := field.index_any('"\r\n') {
return true
}
return false

View File

@ -305,7 +305,8 @@ fn (mut fs FlagParser) parse_bool_value(longhand string, shorthand byte) ?string
fs.args.delete(i)
return val
}
if arg.len > 1 && arg[0] == `-` && arg[1] != `-` && arg.index_byte(shorthand) != -1 {
if arg.len > 1 && arg[0] == `-` && arg[1] != `-`
&& arg.index_byte(shorthand) or { -1 } != -1 {
// -abc is equivalent to -a -b -c
return 'true'
}

View File

@ -68,7 +68,7 @@ pub fn read_cookies(h map[string][]string, filter string) []&Cookie {
mut line := line_.trim_space()
mut part := ''
for line.len > 0 {
if line.index_any(';') > 0 {
if _ := line.index_any(';') {
line_parts := line.split(';')
part = line_parts[0]
line = line_parts[1]

View File

@ -418,10 +418,7 @@ fn get_scheme(rawurl string) ?string {
// sep. If cutc is true then sep is included with the second substring.
// If sep does not occur in s then s and the empty string is returned.
fn split(s string, sep byte, cutc bool) (string, string) {
i := s.index_byte(sep)
if i < 0 {
return s, ''
}
i := s.index_byte(sep) or { return s, '' }
if cutc {
return s[..i], s[i + 1..]
}
@ -746,11 +743,10 @@ pub fn (u URL) str() string {
// it would be mistaken for a scheme name. Such a segment must be
// preceded by a dot-segment (e.g., './this:that') to make a relative-
// path reference.
i := path.index_byte(`:`)
if i > -1 {
if i := path.index_byte(`:`) {
// TODO remove this when autofree handles tmp
// expressions like this
if i > -1 && path[..i].index_byte(`/`) == -1 {
if i > -1 && path[..i].index_byte(`/`) or { -1 } == -1 {
buf.write_string('./')
}
}
@ -800,7 +796,7 @@ fn parse_query_values(mut m Values, query string) ?bool {
mut q := query
for q != '' {
mut key := q
mut i := key.index_any('&;')
mut i := key.index_any('&;') or { -1 }
if i >= 0 {
q = key[i + 1..]
key = key[..i]
@ -1006,8 +1002,7 @@ pub fn (u &URL) port() string {
fn split_host_port(hostport string) (string, string) {
mut host := hostport
mut port := ''
colon := host.last_index_byte(`:`)
if colon != -1 {
if colon := host.last_index_byte(`:`) {
if valid_optional_port(host[colon..]) {
port = host[colon + 1..]
host = host[..colon]

View File

@ -109,8 +109,7 @@ pub fn environ() map[string]string {
break
}
eline := unsafe { cstring_to_vstring(x) }
eq_index := eline.index_byte(`=`)
if eq_index > 0 {
if eq_index := eline.index_byte(`=`) {
res[eline[0..eq_index]] = eline[eq_index + 1..]
}
i++

View File

@ -130,9 +130,7 @@ fn parse_comparator(input string) ?Comparator {
fn parse_xrange(input string) ?Version {
mut raw_ver := parse(input).complete()
for typ in versions {
if raw_ver.raw_ints[typ].index_any(semver.x_range_symbols) == -1 {
continue
}
raw_ver.raw_ints[typ].index_any(semver.x_range_symbols) or { continue }
match typ {
ver_major {
raw_ver.raw_ints[ver_major] = '0'
@ -156,8 +154,9 @@ fn parse_xrange(input string) ?Version {
}
fn can_expand(input string) bool {
return input[0] == `~` || input[0] == `^` || input.contains(semver.hyphen_range_sep)
|| input.index_any(semver.x_range_symbols) > -1
return input[0] == `~` || input[0] == `^` || input.contains(semver.hyphen_range_sep) || input.index_any(semver.x_range_symbols) or {
-1
} > -1
}
fn expand_comparator_set(input string) ?ComparatorSet {

View File

@ -63,7 +63,7 @@ pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string)
if has_next {
break
}
index = flag.index_after(' -', index + 1)
index = flag.index_after(' -', index + 1) or { -1 }
}
if index == -1 {
value = flag.trim_space()

View File

@ -2975,7 +2975,7 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
lit := p.tok.lit
full_lit := if is_neg { '-' + lit } else { lit }
mut node := ast.empty_expr()
if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] {
if lit.index_any('.eE') or { -1 } >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] {
node = ast.FloatLiteral{
val: full_lit
pos: pos

View File

@ -1334,13 +1334,9 @@ fn trim_slash_line_break(s string) string {
mut start := 0
mut ret_str := s
for {
idx := ret_str.index_after('\\\n', start)
if idx != -1 {
ret_str = ret_str[..idx] + ret_str[idx + 2..].trim_left(' \n\t\v\f\r')
start = idx
} else {
break
}
idx := ret_str.index_after('\\\n', start) or { break }
ret_str = ret_str[..idx] + ret_str[idx + 2..].trim_left(' \n\t\v\f\r')
start = idx
}
return ret_str
}