diff --git a/cmd/tools/fast/fast.v b/cmd/tools/fast/fast.v
index d771111334..aa6bc07a9a 100644
--- a/cmd/tools/fast/fast.v
+++ b/cmd/tools/fast/fast.v
@@ -188,8 +188,8 @@ fn measure_steps(vdir string) (int, int, int, int, int) {
} else {
// Fetch number of V lines
if line[0].contains('V') && line[0].contains('source') && line[0].contains('size') {
- start := line[0].index(':') or { 0 }
- end := line[0].index('lines,') or { 0 }
+ start := line[0].index_opt(':') or { 0 }
+ end := line[0].index_opt('lines,') or { 0 }
s := line[0][start + 1..end]
vlines = s.trim_space().int()
}
diff --git a/cmd/tools/vcheck-md.v b/cmd/tools/vcheck-md.v
index 1f65a310b8..67fcb116aa 100644
--- a/cmd/tools/vcheck-md.v
+++ b/cmd/tools/vcheck-md.v
@@ -291,7 +291,7 @@ fn (mut ad AnchorData) add_links(line_number int, line string) {
fn (mut ad AnchorData) add_link_targets(line_number int, line string) {
if line.trim_space().starts_with('#') {
- if headline_start_pos := line.index(' ') {
+ if headline_start_pos := line.index_opt(' ') {
headline := line.substr(headline_start_pos + 1, line.len)
link := create_ref_link(headline)
ad.anchors[link] << Headline{
diff --git a/cmd/tools/vpm.v b/cmd/tools/vpm.v
index bdc4645519..a3fe50e9d3 100644
--- a/cmd/tools/vpm.v
+++ b/cmd/tools/vpm.v
@@ -247,7 +247,7 @@ fn vpm_install_from_vcs(module_names []string, vcs_key string) {
for n in module_names {
url := n.trim_space()
- first_cut_pos := url.last_index('/') or {
+ first_cut_pos := url.last_index_opt('/') or {
errors++
println('Errors while retrieving name for module "$url" :')
println(err)
@@ -256,7 +256,7 @@ fn vpm_install_from_vcs(module_names []string, vcs_key string) {
mod_name := url.substr(first_cut_pos + 1, url.len)
- second_cut_pos := url.substr(0, first_cut_pos).last_index('/') or {
+ second_cut_pos := url.substr(0, first_cut_pos).last_index_opt('/') or {
errors++
println('Errors while retrieving name for module "$url" :')
println(err)
diff --git a/cmd/tools/vrepl.v b/cmd/tools/vrepl.v
index f6c25b12f9..f3a5571138 100644
--- a/cmd/tools/vrepl.v
+++ b/cmd/tools/vrepl.v
@@ -445,7 +445,7 @@ fn convert_output(os_result os.Result) string {
if line.contains('.vrepl_temp.v:') {
// Hide the temporary file name
sline := line.all_after('.vrepl_temp.v:')
- idx := sline.index(' ') or {
+ idx := sline.index_opt(' ') or {
content += endline_if_missed(sline)
return content
}
@@ -453,7 +453,7 @@ fn convert_output(os_result os.Result) string {
} else if line.contains('.vrepl.v:') {
// Ensure that .vrepl.v: is at the start, ignore the path
// This is needed to have stable .repl tests.
- idx := line.index('.vrepl.v:') or { panic(err) }
+ idx := line.index_opt('.vrepl.v:') or { panic(err) }
content += endline_if_missed(line[idx..])
} else {
content += endline_if_missed(line)
diff --git a/cmd/tools/vvet/vvet.v b/cmd/tools/vvet/vvet.v
index 42bc430d07..9f8fa0a49a 100644
--- a/cmd/tools/vvet/vvet.v
+++ b/cmd/tools/vvet/vvet.v
@@ -122,14 +122,14 @@ fn (mut vt Vet) vet_line(lines []string, line string, lnumber int) {
return cleaned.split(',')
}
ident_fn_name := fn (line string) string {
- mut fn_idx := line.index(' fn ') or { return '' }
+ mut fn_idx := line.index_opt(' fn ') or { return '' }
if line.len < fn_idx + 5 {
return ''
}
mut tokens := line[fn_idx + 4..].split(' ')
// Skip struct identifier
if tokens.first().starts_with('(') {
- fn_idx = line.index(')') or { return '' }
+ fn_idx = line.index_opt(')') or { return '' }
tokens = line[fn_idx..].split(' ')
if tokens.len > 1 {
tokens = [tokens[1]]
diff --git a/vlib/builtin/js/string.js.v b/vlib/builtin/js/string.js.v
index 09b740cffa..557b3f78f6 100644
--- a/vlib/builtin/js/string.js.v
+++ b/vlib/builtin/js/string.js.v
@@ -719,7 +719,7 @@ pub fn (s string) replace_each(vals []string) string {
}
// last_index returns the position of the last occurence of the input string.
-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
}
@@ -737,9 +737,9 @@ fn (s string) last_index_(p string) int {
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)
+// lsat_index_opt is a wrapper around `last_index` that returns `none` if the input string can't be found.
+pub fn (s string) last_index_opt(p string) ?int {
+ idx := s.last_index(p)
if idx == -1 {
return none
}
@@ -783,6 +783,15 @@ pub fn (s string) index_after(p string, start int) int {
return -1
}
+// index_after_opt is a wrapper around `index_after` that returns `none` if the input string can't be found.
+pub fn (s string) index_after_opt(p string, start int) ?int {
+ idx := s.index_after(p, start)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
pub fn (s string) split_into_lines() []string {
mut res := []string{}
if s.len == 0 {
@@ -827,6 +836,15 @@ pub fn (s string) index_any(chars string) int {
return -1
}
+// index_any_opt is a wrapper around `index_any` that returns `none` if the input string can't be found.
+pub fn (s string) index_any_opt(chars string) ?int {
+ idx := s.index_any(chars)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
// limit returns a portion of the string, starting at `0` and extending for a given number of characters afterward.
// 'hello'.limit(2) => 'he'
// 'hi'.limit(10) => 'hi'
@@ -948,14 +966,21 @@ pub fn (s []string) join(sep string) string {
// There's no better way to find length of JS String in bytes.
#Object.defineProperty(string.prototype,"len", { get: function() {return new int(new TextEncoder().encode(this.str).length);}, set: function(l) {/* ignore */ } });
// 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(search string) ?int {
+// It will return `-1` if the input string can't be found.
+pub fn (s string) index(search string) int {
res := 0
#res.val = s.str.indexOf(search)
- if res == -1 {
+
+ return res
+}
+
+// index_opt is a wrapper around `index` that returns `none` if the input string can't be found.
+pub fn (s string) index_opt(search string) ?int {
+ idx := s.index(search)
+ if idx == -1 {
return none
}
- return res
+ return idx
}
pub fn (_rune string) utf32_code() int {
diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v
index 293b48bcca..04b65f93af 100644
--- a/vlib/builtin/string.v
+++ b/vlib/builtin/string.v
@@ -319,7 +319,7 @@ 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)
+ idx := s.index(rep)
if idx == -1 {
return s.clone()
}
@@ -901,7 +901,7 @@ 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.
[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
}
@@ -922,10 +922,9 @@ fn (s string) index_(p string) int {
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)
+// index_opt is a wrapper around `index` that returns `none` if the input string can't be found.
+pub fn (s string) index_opt(p string) ?int {
+ idx := s.index(p)
if idx == -1 {
return none
}
@@ -967,6 +966,15 @@ fn (s string) index_kmp(p string) int {
return -1
}
+// index_kmp_opt is a wrapper around `index_kmp` that returns `none` if the input string can't be found.
+pub fn (s string) index_kmp_opt(p string) ?int {
+ idx := s.index_kmp(p)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
// 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 {
for i, ss in s {
@@ -979,9 +987,18 @@ pub fn (s string) index_any(chars string) int {
return -1
}
+// index_any_opt is a wrapper around `index_any` that returns `none` if the input string can't be found.
+pub fn (s string) index_any_opt(chars string) ?int {
+ idx := s.index_any(chars)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
// 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
}
@@ -999,9 +1016,9 @@ fn (s string) last_index_(p string) int {
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)
+// last_index_opt is a wrapper around `last_index` that returns `none` if the input string can't be found.
+pub fn (s string) last_index_opt(p string) ?int {
+ idx := s.last_index(p)
if idx == -1 {
return none
}
@@ -1037,6 +1054,15 @@ pub fn (s string) index_after(p string, start int) int {
return -1
}
+// index_after_opt is a wrapper around `index_after` that returns `none` if the input string can't be found.
+pub fn (s string) index_after_opt(p string, start int) ?int {
+ idx := s.index_after(p, start)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
// index_byte returns the index of byte `c` if found in the string.
// index_byte returns -1 if the byte can not be found.
[direct_array_access]
@@ -1049,6 +1075,15 @@ pub fn (s string) index_byte(c byte) int {
return -1
}
+// index_byte_opt is a wrapper around `index_byte` that returns `none` if the input string can't be found.
+pub fn (s string) index_byte_opt(c byte) ?int {
+ idx := s.index_byte(c)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
// 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.
[direct_array_access]
@@ -1061,8 +1096,16 @@ pub fn (s string) last_index_byte(c byte) int {
return -1
}
+// last_index_byte_opt is a wrapper around `last_index_byte` that returns `none` if the input string can't be found.
+pub fn (s string) last_index_byte_opt(c byte) ?int {
+ idx := s.last_index_byte(c)
+ if idx == -1 {
+ return none
+ }
+ return idx
+}
+
// count returns the number of occurrences of `substr` in the string.
-// count returns -1 if no `substr` could be found.
[direct_array_access]
pub fn (s string) count(substr string) int {
if s.len == 0 || substr.len == 0 {
@@ -1103,7 +1146,7 @@ pub fn (s string) contains(substr string) bool {
if substr.len == 0 {
return true
}
- if s.index_(substr) == -1 {
+ if s.index(substr) == -1 {
return false
}
return true
@@ -1294,13 +1337,13 @@ 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)
+ start_pos := s.index(start)
if start_pos == -1 {
return ''
}
// First get everything to the right of 'start'
val := s[start_pos + start.len..]
- end_pos := val.index_(end)
+ end_pos := val.index(end)
if end_pos == -1 {
return val
}
@@ -1582,7 +1625,7 @@ 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)
+ pos := s.index(sub)
if pos == -1 {
return s.clone()
}
@@ -1595,7 +1638,7 @@ 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)
+ pos := s.index(sub)
if pos == -1 {
return s.clone()
}
@@ -1607,7 +1650,7 @@ 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)
+ pos := s.last_index(sub)
if pos == -1 {
return s.clone()
}
@@ -1619,7 +1662,7 @@ 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)
+ pos := s.index(sub)
if pos == -1 {
return s.clone()
}
@@ -1631,7 +1674,7 @@ 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)
+ pos := s.last_index(sub)
if pos == -1 {
return s.clone()
}
diff --git a/vlib/builtin/string_interpolation.v b/vlib/builtin/string_interpolation.v
index ccba92f25d..b71e380c2f 100644
--- a/vlib/builtin/string_interpolation.v
+++ b/vlib/builtin/string_interpolation.v
@@ -708,7 +708,7 @@ pub fn str_intp_g64(in_str string) string {
// replace %% with the in_str
[manualfree]
pub fn str_intp_sub(base_str string, in_str string) string {
- index := base_str.index('%%') or {
+ index := base_str.index_opt('%%') or {
eprintln('No strin interpolation %% parameteres')
exit(1)
}
diff --git a/vlib/encoding/csv/reader.v b/vlib/encoding/csv/reader.v
index 55bf5b8d8e..0c292c23c0 100644
--- a/vlib/encoding/csv/reader.v
+++ b/vlib/encoding/csv/reader.v
@@ -147,7 +147,7 @@ fn (mut r Reader) read_record() ?[]string {
keep_raw = false
}
if line.len == 0 || line[0] != `"` { // not quoted
- j := line.index(r.delimiter.ascii_str()) or {
+ j := line.index_opt(r.delimiter.ascii_str()) or {
// last
fields << line[..line.len]
break
diff --git a/vlib/io/util/util.v b/vlib/io/util/util.v
index 895a1c06bf..1fa45c528c 100644
--- a/vlib/io/util/util.v
+++ b/vlib/io/util/util.v
@@ -84,7 +84,7 @@ fn prefix_and_suffix(pattern string) ?(string, string) {
if pat.contains(os.path_separator) {
return error('pattern cannot contain path separators ($os.path_separator).')
}
- pos := pat.last_index('*') or { -1 }
+ pos := pat.last_index('*')
mut prefix := ''
mut suffix := ''
if pos != -1 {
diff --git a/vlib/net/http/response.v b/vlib/net/http/response.v
index e1fbfd76c3..a7987307ab 100644
--- a/vlib/net/http/response.v
+++ b/vlib/net/http/response.v
@@ -136,7 +136,7 @@ pub fn new_response(conf ResponseConfig) Response {
// helper function expects the first line in `data` to be the HTTP status line
// (HTTP/1.1 200 OK).
fn find_headers_range(data string) ?(int, int) {
- start_idx := data.index('\n') or { return error('no start index found') } + 1
+ start_idx := data.index_opt('\n') or { return error('no start index found') } + 1
mut count := 0
for i := start_idx; i < data.len; i++ {
if data[i] == `\n` {
diff --git a/vlib/net/urllib/urllib.v b/vlib/net/urllib/urllib.v
index dc632f254f..23b14624d9 100644
--- a/vlib/net/urllib/urllib.v
+++ b/vlib/net/urllib/urllib.v
@@ -505,8 +505,8 @@ fn parse_url(rawurl string, via_request bool) ?URL {
// RFC 3986, ยง3.3:
// In addition, a URI reference (Section 4.1) may be a relative-path reference,
// in which case the first path segment cannot contain a colon (':') character.
- colon := rest.index(':') or { return error('there should be a : in the URL') }
- slash := rest.index('/') or { return error('there should be a / in the URL') }
+ colon := rest.index_opt(':') or { return error('there should be a : in the URL') }
+ slash := rest.index_opt('/') or { return error('there should be a / in the URL') }
if colon >= 0 && (slash < 0 || colon < slash) {
// First path segment has colon. Not allowed in relative URL.
return error(error_msg('parse_url: first path segment in URL cannot contain colon',
@@ -534,7 +534,7 @@ struct ParseAuthorityRes {
}
fn parse_authority(authority string) ?ParseAuthorityRes {
- i := authority.last_index('@') or { -1 }
+ i := authority.last_index('@')
mut host := ''
mut zuser := user('')
if i < 0 {
@@ -578,7 +578,7 @@ fn parse_host(host string) ?string {
if host.starts_with('[') {
// parse an IP-Literal in RFC 3986 and RFC 6874.
// E.g., '[fe80::1]', '[fe80::1%25en0]', '[fe80::1]:80'.
- mut i := host.last_index(']') or {
+ mut i := host.last_index_opt(']') or {
return error(error_msg("parse_host: missing ']' in host", ''))
}
mut colon_port := host[i + 1..]
@@ -592,13 +592,13 @@ fn parse_host(host string) ?string {
// can only %-encode non-ASCII bytes.
// We do impose some restrictions on the zone, to avoid stupidity
// like newlines.
- if zone := host[..i].index('%25') {
+ if zone := host[..i].index_opt('%25') {
host1 := unescape(host[..zone], .encode_host) or { return err.msg() }
host2 := unescape(host[zone..i], .encode_zone) or { return err.msg() }
host3 := unescape(host[i..], .encode_host) or { return err.msg() }
return host1 + host2 + host3
}
- if idx := host.last_index(':') {
+ if idx := host.last_index_opt(':') {
colon_port = host[idx..]
if !valid_optional_port(colon_port) {
return error(error_msg('parse_host: invalid port $colon_port after host ',
@@ -811,7 +811,7 @@ fn parse_query_values(mut m Values, query string) ?bool {
continue
}
mut value := ''
- if idx := key.index('=') {
+ if idx := key.index_opt('=') {
i = idx
value = key[i + 1..]
key = key[..i]
@@ -872,7 +872,7 @@ fn resolve_path(base string, ref string) string {
if ref == '' {
full = base
} else if ref[0] != `/` {
- i := base.last_index('/') or { -1 }
+ i := base.last_index('/')
full = base[..i + 1] + ref
} else {
full = ref
diff --git a/vlib/os/os.v b/vlib/os/os.v
index a0a8397249..eba12a51b1 100644
--- a/vlib/os/os.v
+++ b/vlib/os/os.v
@@ -173,7 +173,7 @@ pub fn is_dir_empty(path string) bool {
// file_ext will return the part after the last occurence of `.` in `path`.
// The `.` is included.
pub fn file_ext(path string) string {
- pos := path.last_index('.') or { return '' }
+ pos := path.last_index_opt('.') or { return '' }
return path[pos..]
}
@@ -187,7 +187,7 @@ pub fn dir(opath string) string {
return '.'
}
path := opath.replace_each(['/', path_separator, r'\', path_separator])
- pos := path.last_index(path_separator) or { return '.' }
+ pos := path.last_index_opt(path_separator) or { return '.' }
if pos == 0 && path_separator == '/' {
return '/'
}
@@ -208,10 +208,10 @@ pub fn base(opath string) string {
}
if path.ends_with(path_separator) {
path2 := path[..path.len - 1]
- pos := path2.last_index(path_separator) or { return path2.clone() }
+ pos := path2.last_index_opt(path_separator) or { return path2.clone() }
return path2[pos + 1..]
}
- pos := path.last_index(path_separator) or { return path.clone() }
+ pos := path.last_index_opt(path_separator) or { return path.clone() }
return path[pos + 1..]
}
diff --git a/vlib/rand/random_numbers_test.v b/vlib/rand/random_numbers_test.v
index 0f32adc7c2..f5f1d61697 100644
--- a/vlib/rand/random_numbers_test.v
+++ b/vlib/rand/random_numbers_test.v
@@ -208,7 +208,7 @@ fn test_rand_string_from_set() {
str := rand.string_from_set(charset, len)
assert str.len == len
for character in str {
- position := charset.index(character.ascii_str()) or { -1 }
+ position := charset.index(character.ascii_str())
assert position > -1
}
}
diff --git a/vlib/semver/parse.v b/vlib/semver/parse.v
index 3443f59993..b2ed89aefa 100644
--- a/vlib/semver/parse.v
+++ b/vlib/semver/parse.v
@@ -21,12 +21,12 @@ fn parse(input string) RawVersion {
mut raw_version := input
mut prerelease := ''
mut metadata := ''
- plus_idx := raw_version.last_index('+') or { -1 }
+ plus_idx := raw_version.last_index('+')
if plus_idx > 0 {
metadata = raw_version[(plus_idx + 1)..]
raw_version = raw_version[0..plus_idx]
}
- hyphen_idx := raw_version.index('-') or { -1 }
+ hyphen_idx := raw_version.index('-')
if hyphen_idx > 0 {
prerelease = raw_version[(hyphen_idx + 1)..]
raw_version = raw_version[0..hyphen_idx]
diff --git a/vlib/time/parse.c.v b/vlib/time/parse.c.v
index 2554a22617..bbbf9f3502 100644
--- a/vlib/time/parse.c.v
+++ b/vlib/time/parse.c.v
@@ -18,7 +18,7 @@ pub fn parse_rfc3339(s string) ?Time {
return t
}
- t_i := sn.index('T') or { -1 }
+ t_i := sn.index('T')
parts := if t_i != -1 { [sn[..t_i], sn[t_i + 1..]] } else { sn.split(' ') }
// Check if sn is date only
@@ -62,7 +62,7 @@ pub fn parse(s string) ?Time {
if s == '' {
return error_invalid_time(0)
}
- pos := s.index(' ') or { return error_invalid_time(1) }
+ pos := s.index_opt(' ') or { return error_invalid_time(1) }
symd := s[..pos]
ymd := symd.split('-')
if ymd.len != 3 {
@@ -119,7 +119,7 @@ pub fn parse_iso8601(s string) ?Time {
if s == '' {
return error_invalid_time(0)
}
- t_i := s.index('T') or { -1 }
+ t_i := s.index('T')
parts := if t_i != -1 { [s[..t_i], s[t_i + 1..]] } else { s.split(' ') }
if !(parts.len == 1 || parts.len == 2) {
return error_invalid_time(12)
@@ -160,7 +160,7 @@ pub fn parse_rfc2822(s string) ?Time {
if fields.len < 5 {
return error_invalid_time(1)
}
- pos := months_string.index(fields[2]) or { return error_invalid_time(2) }
+ pos := months_string.index_opt(fields[2]) or { return error_invalid_time(2) }
mm := pos / 3 + 1
unsafe {
tmstr := malloc_noscan(s.len * 2)
diff --git a/vlib/toml/checker/checker.v b/vlib/toml/checker/checker.v
index 1bdf5ca1a1..7c25c12ec7 100644
--- a/vlib/toml/checker/checker.v
+++ b/vlib/toml/checker/checker.v
@@ -103,7 +103,7 @@ fn (c Checker) check_number(num ast.Number) ? {
mut is_bin, mut is_oct, mut is_hex := false, false, false
is_float := lit_lower_case.all_before('e').contains('.')
has_exponent_notation := lit_lower_case.contains('e')
- float_decimal_index := lit.index('.') or { -1 }
+ float_decimal_index := lit.index('.')
// mut is_first_digit := byte(lit[0]).is_digit()
mut ascii := byte(lit[0]).ascii_str()
is_sign_prefixed := lit[0] in [`+`, `-`]
diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v
index 3963072860..b0a97f7b6a 100644
--- a/vlib/v/ast/ast.v
+++ b/vlib/v/ast/ast.v
@@ -2083,7 +2083,7 @@ pub fn all_registers(mut t Table, arch pref.Arch) map[string]ScopeObject {
for bit_size, array in ast.x86_with_number_register_list {
for name, max_num in array {
for i in 0 .. max_num {
- hash_index := name.index('#') or {
+ hash_index := name.index_opt('#') or {
panic('all_registers: no hashtag found')
}
assembled_name := '${name[..hash_index]}$i${name[hash_index + 1..]}'
@@ -2144,7 +2144,7 @@ fn gen_all_registers(mut t Table, without_numbers []string, with_numbers map[str
}
for name, max_num in with_numbers {
for i in 0 .. max_num {
- hash_index := name.index('#') or { panic('all_registers: no hashtag found') }
+ hash_index := name.index_opt('#') or { panic('all_registers: no hashtag found') }
assembled_name := '${name[..hash_index]}$i${name[hash_index + 1..]}'
res[assembled_name] = AsmRegister{
name: assembled_name
diff --git a/vlib/v/ast/cflags.v b/vlib/v/ast/cflags.v
index 12fedd9815..555952782d 100644
--- a/vlib/v/ast/cflags.v
+++ b/vlib/v/ast/cflags.v
@@ -31,7 +31,7 @@ pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string)
if !flag.starts_with(os_override) {
continue
}
- pos := flag.index(' ') or { return none }
+ pos := flag.index_opt(' ') or { return none }
fos = flag[..pos].trim_space()
flag = flag[pos..].trim_space()
}
@@ -48,7 +48,7 @@ pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string)
}
}
}
- mut index := flag.index(' -') or { -1 }
+ mut index := flag.index(' -')
for index > -1 {
mut has_next := false
for f in allowed_flags {
diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v
index ccbb01337f..1d0d4fcded 100644
--- a/vlib/v/checker/checker.v
+++ b/vlib/v/checker/checker.v
@@ -413,7 +413,7 @@ fn (mut c Checker) check_valid_snake_case(name string, identifier string, pos to
}
fn stripped_name(name string) string {
- idx := name.last_index('.') or { -1 }
+ idx := name.last_index('.')
return name[(idx + 1)..]
}
diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v
index 70eb53434c..acd2f69c36 100644
--- a/vlib/v/checker/struct.v
+++ b/vlib/v/checker/struct.v
@@ -189,7 +189,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
// but `x := T{}` is ok.
if !c.is_builtin_mod && !c.inside_unsafe && type_sym.language == .v
&& c.table.cur_concrete_types.len == 0 {
- pos := type_sym.name.last_index('.') or { -1 }
+ pos := type_sym.name.last_index('.')
first_letter := type_sym.name[pos + 1]
if !first_letter.is_capital() {
c.error('cannot initialize builtin type `$type_sym.name`', node.pos)
diff --git a/vlib/v/checker/tests/type_cast_optional_err.out b/vlib/v/checker/tests/type_cast_optional_err.out
index bb52bad666..3eef0160a2 100644
--- a/vlib/v/checker/tests/type_cast_optional_err.out
+++ b/vlib/v/checker/tests/type_cast_optional_err.out
@@ -1,5 +1,5 @@
vlib/v/checker/tests/type_cast_optional_err.vv:2:13: error: cannot type cast an optional
1 | fn main() {
- 2 | println(int('hi'.last_index('i')))
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ 2 | println(int('hi'.last_index_opt('i')))
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 | }
diff --git a/vlib/v/checker/tests/type_cast_optional_err.vv b/vlib/v/checker/tests/type_cast_optional_err.vv
index 982559cbda..237b7d92ae 100644
--- a/vlib/v/checker/tests/type_cast_optional_err.vv
+++ b/vlib/v/checker/tests/type_cast_optional_err.vv
@@ -1,3 +1,3 @@
fn main() {
- println(int('hi'.last_index('i')))
+ println(int('hi'.last_index_opt('i')))
}
diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v
index 33dc2d3e6b..ffa6cf97f0 100644
--- a/vlib/v/gen/js/js.v
+++ b/vlib/v/gen/js/js.v
@@ -308,7 +308,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
// calculate final generated location in output based on position
current_segment := g.out.substr(int(sm_pos), int(sourcemap_ns_entry.ns_pos))
current_line += u32(current_segment.count('\n'))
- current_column := if last_nl_pos := current_segment.last_index('\n') {
+ current_column := if last_nl_pos := current_segment.last_index_opt('\n') {
u32(current_segment.len - last_nl_pos - 1)
} else {
u32(0)
@@ -547,7 +547,7 @@ pub fn (mut g JsGen) new_tmp_var() string {
// 'fn' => ''
[inline]
fn get_ns(s string) string {
- idx := s.last_index('.') or { return '' }
+ idx := s.last_index_opt('.') or { return '' }
return s.substr(0, idx)
}
@@ -3394,7 +3394,7 @@ fn (mut g JsGen) gen_struct_init(it ast.StructInit) {
type_sym := g.table.sym(it.typ)
mut name := type_sym.name
if name.contains('<') {
- name = name[0..name.index('<') or { name.len }]
+ name = name[0..name.index_opt('<') or { name.len }]
}
if it.fields.len == 0 && type_sym.kind != .interface_ {
if type_sym.kind == .struct_ && type_sym.language == .js {
diff --git a/vlib/v/parser/tmpl.v b/vlib/v/parser/tmpl.v
index e0aa85eebd..5d91e79026 100644
--- a/vlib/v/parser/tmpl.v
+++ b/vlib/v/parser/tmpl.v
@@ -129,7 +129,7 @@ fn vweb_tmpl_${fn_name}() string {
eprintln('>>> tfile: $template_file, spos: ${start_of_line_pos:6}, epos:${end_of_line_pos:6}, fi: ${tline_number:5}, i: ${i:5}, state: ${state:10}, line: $line')
}
if line.contains('@header') {
- position := line.index('@header') or { 0 }
+ position := line.index_opt('@header') or { 0 }
p.error_with_error(errors.Error{
message: "Please use @include 'header' instead of @header (deprecated)"
file_path: template_file
@@ -144,7 +144,7 @@ fn vweb_tmpl_${fn_name}() string {
continue
}
if line.contains('@footer') {
- position := line.index('@footer') or { 0 }
+ position := line.index_opt('@footer') or { 0 }
p.error_with_error(errors.Error{
message: "Please use @include 'footer' instead of @footer (deprecated)"
file_path: template_file
@@ -177,7 +177,7 @@ fn vweb_tmpl_${fn_name}() string {
eprintln('>>> basepath: "$basepath" , template_file: "$template_file" , fn_name: "$fn_name" , @include line: "$line" , file_name: "$file_name" , file_ext: "$file_ext" , templates_folder: "$templates_folder" , file_path: "$file_path"')
}
file_content := os.read_file(file_path) or {
- position := line.index('@include ') or { 0 } + '@include '.len
+ position := line.index_opt('@include ') or { 0 } + '@include '.len
p.error_with_error(errors.Error{
message: 'Reading file $file_name from path: $file_path failed'
details: "Failed to @include '$file_name'"
@@ -202,7 +202,7 @@ fn vweb_tmpl_${fn_name}() string {
}
if line.contains('@if ') {
source.writeln(parser.tmpl_str_end)
- pos := line.index('@if') or { continue }
+ pos := line.index_opt('@if') or { continue }
source.writeln('if ' + line[pos + 4..] + '{')
source.writeln(tmpl_str_start)
continue
@@ -225,7 +225,7 @@ fn vweb_tmpl_${fn_name}() string {
}
if line.contains('@for') {
source.writeln(parser.tmpl_str_end)
- pos := line.index('@for') or { continue }
+ pos := line.index_opt('@for') or { continue }
source.writeln('for ' + line[pos + 4..] + '{')
source.writeln(tmpl_str_start)
continue
@@ -239,14 +239,14 @@ fn vweb_tmpl_${fn_name}() string {
if state != .simple {
if line.contains('@js ') {
- pos := line.index('@js') or { continue }
+ pos := line.index_opt('@js') or { continue }
source.write_string('')
continue
}
if line.contains('@css ') {
- pos := line.index('@css') or { continue }
+ pos := line.index_opt('@css') or { continue }
source.write_string('')
diff --git a/vlib/v/pkgconfig/pkgconfig.v b/vlib/v/pkgconfig/pkgconfig.v
index 3eec069825..04a023b64d 100644
--- a/vlib/v/pkgconfig/pkgconfig.v
+++ b/vlib/v/pkgconfig/pkgconfig.v
@@ -72,8 +72,8 @@ fn (mut pc PkgConfig) parse_list(s string) []string {
fn (mut pc PkgConfig) parse_line(s string) string {
mut r := s.trim_space()
for r.contains('\${') {
- tok0 := r.index('\${') or { break }
- mut tok1 := r[tok0..].index('}') or { break }
+ tok0 := r.index_opt('\${') or { break }
+ mut tok1 := r[tok0..].index_opt('}') or { break }
tok1 += tok0
v := r[tok0 + 2..tok1]
r = r.replace('\${$v}', pc.vars[v])
diff --git a/vlib/v/tests/option_default_values_test.v b/vlib/v/tests/option_default_values_test.v
index 2abd546fa9..4da886df3b 100644
--- a/vlib/v/tests/option_default_values_test.v
+++ b/vlib/v/tests/option_default_values_test.v
@@ -127,7 +127,7 @@ fn test_nested_optional_with_opt_fn_call_as_last_value() {
fn remove_suffix1(s string) string {
n := s.len
- i := s.last_index('.') or { n }
+ i := s.last_index_opt('.') or { n }
return s[0..i]
}
diff --git a/vlib/v/util/util.v b/vlib/v/util/util.v
index 3e077928d6..b3affaf60d 100644
--- a/vlib/v/util/util.v
+++ b/vlib/v/util/util.v
@@ -69,7 +69,7 @@ pub fn resolve_vmodroot(str string, dir string) ?string {
// in `str` with the value of the env variable `$ENV_VAR_NAME`.
pub fn resolve_env_value(str string, check_for_presence bool) ?string {
env_ident := "\$env('"
- at := str.index(env_ident) or {
+ at := str.index_opt(env_ident) or {
return error('no "$env_ident' + '...\')" could be found in "$str".')
}
mut ch := byte(`.`)