Skip to content

Commit 951d304

Browse files
committed
builtin: string.index_after() ?int
1 parent 85973b9 commit 951d304

File tree

12 files changed

+94
-44
lines changed

12 files changed

+94
-44
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,4 @@ bench/vectors/obj
155155

156156
autofuzz.log
157157
.project.gf
158+
.aider*

cmd/tools/changelog_helper.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ fn (l Line) write_at_category(txt string) ?string {
311311
title := category_map[l.category]
312312
title_pos := txt.index(title)?
313313
// Find the position of the ### category title
314-
pos := txt.index_after('\n', title_pos + 1)
314+
pos := txt.index_after('\n', title_pos + 1) or { return none }
315315
first_half := txt[..pos]
316316
second_half := txt[pos..]
317317
if txt.contains(l.text) {

cmd/tools/vpm/common.v

+4-10
Original file line numberDiff line numberDiff line change
@@ -104,24 +104,18 @@ fn get_all_modules() []string {
104104
mut start_token := "<a href='/mod"
105105
end_token := '</a>'
106106
// get the start index of the module entry
107-
mut start_index := s.index_after(start_token, read_len)
107+
mut start_index := s.index_after(start_token, read_len) or { -1 }
108108
if start_index == -1 {
109109
start_token = '<a href="/mod'
110-
start_index = s.index_after(start_token, read_len)
111-
if start_index == -1 {
112-
break
113-
}
110+
start_index = s.index_after(start_token, read_len) or { break }
114111
}
115112
// get the index of the end of anchor (a) opening tag
116113
// we use the previous start_index to make sure we are getting a module and not just a random 'a' tag
117114
start_token = '>'
118-
start_index = s.index_after(start_token, start_index) + start_token.len
115+
start_index = s.index_after(start_token, start_index) or { break } + start_token.len
119116

120117
// get the index of the end of module entry
121-
end_index := s.index_after(end_token, start_index)
122-
if end_index == -1 {
123-
break
124-
}
118+
end_index := s.index_after(end_token, start_index) or { break }
125119
modules << s[start_index..end_index]
126120
read_len = end_index
127121
if read_len >= s.len {

examples/links_scraper.v

+2-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ fn main() {
44
html := http.get_text('https://news.ycombinator.com')
55
mut pos := 0
66
for {
7-
pos = html.index_after('https://', pos + 1)
8-
if pos == -1 {
9-
break
10-
}
11-
end := html.index_after('"', pos)
7+
pos = html.index_after('https://', pos + 1) or { break }
8+
end := html.index_after('"', pos) or { break }
129
println(html[pos..end])
1310
}
1411
}

vlib/builtin/js/string.js.v

+32-2
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ pub fn (s string) replace_each(vals []string) string {
707707
with_ = with_
708708

709709
for {
710-
idx = s_.index_after(rep, idx)
710+
idx = s_.index_after_(rep, idx)
711711
if idx == -1 {
712712
break
713713
}
@@ -817,7 +817,37 @@ pub fn (s string) trim_space() string {
817817
return res
818818
}
819819

820-
pub fn (s string) index_after(p string, start int) int {
820+
pub fn (s string) index_after(p string, start int) ?int {
821+
if p.len > s.len {
822+
return none
823+
}
824+
825+
mut strt := start
826+
if start < 0 {
827+
strt = 0
828+
}
829+
if start >= s.len {
830+
return none
831+
}
832+
mut i := strt
833+
834+
for i < s.len {
835+
mut j := 0
836+
mut ii := i
837+
for j < p.len && s[ii] == p[j] {
838+
j++
839+
ii++
840+
}
841+
842+
if j == p.len {
843+
return i
844+
}
845+
i++
846+
}
847+
return none
848+
}
849+
850+
pub fn (s string) index_after_(p string, start int) int {
821851
if p.len > s.len {
822852
return -1
823853
}

vlib/builtin/string.v

+33-4
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ pub fn (s string) replace(rep string, with string) string {
392392
}
393393
mut idx := 0
394394
for {
395-
idx = s.index_after(rep, idx)
395+
idx = s.index_after_(rep, idx)
396396
if idx == -1 {
397397
break
398398
}
@@ -463,7 +463,7 @@ pub fn (s string) replace_each(vals []string) string {
463463
with := vals[rep_i + 1]
464464

465465
for {
466-
idx = s_.index_after(rep, idx)
466+
idx = s_.index_after_(rep, idx)
467467
if idx == -1 {
468468
break
469469
}
@@ -1352,7 +1352,36 @@ fn (s string) index_last_(p string) int {
13521352

13531353
// index_after returns the position of the input string, starting search from `start` position.
13541354
@[direct_array_access]
1355-
pub fn (s string) index_after(p string, start int) int {
1355+
pub fn (s string) index_after(p string, start int) ?int {
1356+
if p.len > s.len {
1357+
return none
1358+
}
1359+
mut strt := start
1360+
if start < 0 {
1361+
strt = 0
1362+
}
1363+
if start >= s.len {
1364+
return none
1365+
}
1366+
mut i := strt
1367+
for i < s.len {
1368+
mut j := 0
1369+
mut ii := i
1370+
for j < p.len && unsafe { s.str[ii] == p.str[j] } {
1371+
j++
1372+
ii++
1373+
}
1374+
if j == p.len {
1375+
return i
1376+
}
1377+
i++
1378+
}
1379+
return none
1380+
}
1381+
1382+
// index_after_ returns the position of the input string, starting search from `start` position.
1383+
@[direct_array_access]
1384+
pub fn (s string) index_after_(p string, start int) int {
13561385
if p.len > s.len {
13571386
return -1
13581387
}
@@ -1429,7 +1458,7 @@ pub fn (s string) count(substr string) int {
14291458

14301459
mut i := 0
14311460
for {
1432-
i = s.index_after(substr, i)
1461+
i = s.index_after_(substr, i)
14331462
if i == -1 {
14341463
return n
14351464
}

vlib/encoding/csv/reader.v

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ fn (mut r Reader) read_line() !string {
9595
return &EndOfFileError{}
9696
}
9797
le := if r.is_mac_pre_osx_le { '\r' } else { '\n' }
98-
mut i := r.data.index_after(le, r.row_pos)
98+
mut i := r.data.index_after(le, r.row_pos) or { -1 }
9999
if i == -1 {
100100
if r.row_pos == 0 {
101101
// check for pre osx mac line endings
102-
i = r.data.index_after('\r', r.row_pos)
102+
i = r.data.index_after('\r', r.row_pos) or { -1 }
103103
if i != -1 {
104104
r.is_mac_pre_osx_le = true
105105
} else {

vlib/net/http/util.v

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ module http
88
// "GET / HTTP/1.1" => ["GET" "/" "HTTP/1.1"]
99
fn fast_request_words(line string) (int, int) {
1010
space1 := line.index(' ') or { return 0, 0 }
11-
space2 := line.index_after(' ', space1 + 1)
12-
if space2 == -1 {
13-
return 0, 0
14-
}
11+
space2 := line.index_after(' ', space1 + 1) or { return 0, 0 }
1512
return space1, space2
1613
}

vlib/v/ast/cflags.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string)
6464
if has_next {
6565
break
6666
}
67-
index = flag.index_after(' -', index + 1)
67+
index = flag.index_after(' -', index + 1) or { -1 }
6868
}
6969
if index == -1 {
7070
value = flag.trim_space()

vlib/v/checker/checker.v

+11-9
Original file line numberDiff line numberDiff line change
@@ -3367,15 +3367,17 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
33673367
}
33683368
c.check_any_type(to_type, to_sym, node.pos)
33693369

3370-
if (to_sym.is_number() && from_sym.name == 'JS.Number')
3371-
|| (to_sym.is_number() && from_sym.name == 'JS.BigInt')
3372-
|| (to_sym.is_string() && from_sym.name == 'JS.String')
3373-
|| (to_type.is_bool() && from_sym.name == 'JS.Boolean')
3374-
|| (from_type.is_bool() && to_sym.name == 'JS.Boolean')
3375-
|| (from_sym.is_number() && to_sym.name == 'JS.Number')
3376-
|| (from_sym.is_number() && to_sym.name == 'JS.BigInt')
3377-
|| (from_sym.is_string() && to_sym.name == 'JS.String') {
3378-
return to_type
3370+
if c.pref.backend.is_js() {
3371+
if (to_sym.is_number() && from_sym.name == 'JS.Number')
3372+
|| (to_sym.is_number() && from_sym.name == 'JS.BigInt')
3373+
|| (to_sym.is_string() && from_sym.name == 'JS.String')
3374+
|| (to_type.is_bool() && from_sym.name == 'JS.Boolean')
3375+
|| (from_type.is_bool() && to_sym.name == 'JS.Boolean')
3376+
|| (from_sym.is_number() && to_sym.name == 'JS.Number')
3377+
|| (from_sym.is_number() && to_sym.name == 'JS.BigInt')
3378+
|| (from_sym.is_string() && to_sym.name == 'JS.String') {
3379+
return to_type
3380+
}
33793381
}
33803382

33813383
if !c.expected_type.has_flag(.generic) && to_sym.name.len == 1

vlib/v/eval/expr.c.v

+5-2
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,15 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
579579
}
580580
e.error('unhandled index expression ${left}[ ${index} ]')
581581
}
582+
ast.OrExpr {
583+
e.error('unhandled expression ${typeof(expr).name}')
584+
}
582585
ast.AnonFn, ast.ArrayDecompose, ast.AsCast, ast.Assoc, ast.AtExpr, ast.CTempVar,
583586
ast.ChanInit, ast.Comment, ast.ComptimeCall, ast.ComptimeSelector, ast.ComptimeType,
584587
ast.ConcatExpr, ast.DumpExpr, ast.EmptyExpr, ast.EnumVal, ast.GoExpr, ast.SpawnExpr,
585588
ast.IfGuardExpr, ast.IsRefType, ast.Likely, ast.LockExpr, ast.MapInit, ast.MatchExpr,
586-
ast.Nil, ast.None, ast.OffsetOf, ast.OrExpr, ast.RangeExpr, ast.SelectExpr, ast.SqlExpr,
587-
ast.TypeNode, ast.TypeOf, ast.LambdaExpr {
589+
ast.Nil, ast.None, ast.OffsetOf, ast.RangeExpr, ast.SelectExpr, ast.SqlExpr, ast.TypeNode,
590+
ast.TypeOf, ast.LambdaExpr {
588591
e.error('unhandled expression ${typeof(expr).name}')
589592
}
590593
}

vlib/v/scanner/scanner.v

+1-4
Original file line numberDiff line numberDiff line change
@@ -1506,10 +1506,7 @@ fn trim_slash_line_break(s string) string {
15061506
mut ret_str := s
15071507
for {
15081508
// find the position of the first `\` followed by a newline, after `start`:
1509-
idx := ret_str.index_after('\\\n', start)
1510-
if idx == -1 {
1511-
break
1512-
}
1509+
idx := ret_str.index_after('\\\n', start) or { break }
15131510
start = idx
15141511
// Here, ret_str[idx] is \, and ret_str[idx+1] is newline.
15151512
// Depending on the number of backslashes before the newline, we should either

0 commit comments

Comments
 (0)