Skip to content

Commit 3793bf1

Browse files
authored
builtin: optimise the common case of s.contains("x") add s.contains_byte(x) (#17702)
1 parent 14148f3 commit 3793bf1

File tree

2 files changed

+51
-10
lines changed

2 files changed

+51
-10
lines changed

vlib/builtin/string.v

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,12 +1287,12 @@ pub fn (s string) index_after(p string, start int) int {
12871287
return -1
12881288
}
12891289

1290-
// index_byte returns the index of byte `c` if found in the string.
1291-
// index_byte returns -1 if the byte can not be found.
1290+
// index_u8 returns the index of byte `c` if found in the string.
1291+
// index_u8 returns -1 if the byte can not be found.
12921292
[direct_array_access]
12931293
pub fn (s string) index_u8(c u8) int {
1294-
for i in 0 .. s.len {
1295-
if unsafe { s.str[i] } == c {
1294+
for i, b in s {
1295+
if b == c {
12961296
return i
12971297
}
12981298
}
@@ -1348,22 +1348,33 @@ pub fn (s string) count(substr string) int {
13481348
return 0 // TODO can never get here - v doesn't know that
13491349
}
13501350

1351+
// contains_u8 returns `true` if the string contains the byte value `x`.
1352+
// See also: [`string.index_u8`](#string.index_u8) , to get the index of the byte as well.
1353+
pub fn (s string) contains_u8(x u8) bool {
1354+
for c in s {
1355+
if x == c {
1356+
return true
1357+
}
1358+
}
1359+
return false
1360+
}
1361+
13511362
// contains returns `true` if the string contains `substr`.
13521363
// See also: [`string.index`](#string.index)
13531364
pub fn (s string) contains(substr string) bool {
13541365
if substr.len == 0 {
13551366
return true
13561367
}
1357-
if s.index_(substr) == -1 {
1358-
return false
1368+
if substr.len == 1 {
1369+
return s.contains_u8(unsafe { substr.str[0] })
13591370
}
1360-
return true
1371+
return s.index_(substr) != -1
13611372
}
13621373

13631374
// contains_any returns `true` if the string contains any chars in `chars`.
13641375
pub fn (s string) contains_any(chars string) bool {
13651376
for c in chars {
1366-
if s.contains(c.ascii_str()) {
1377+
if s.contains_u8(c) {
13671378
return true
13681379
}
13691380
}

vlib/builtin/string_test.v

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import strings
2-
31
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
42
// Use of this source code is governed by an MIT license
53
// that can be found in the LICENSE file.
@@ -1213,3 +1211,35 @@ fn test_indent_width() {
12131211
assert '\t\tabc'.indent_width() == 2
12141212
assert '\t\t abc'.indent_width() == 3
12151213
}
1214+
1215+
fn test_index_u8() {
1216+
assert 'abcabca'.index_u8(`a`) == 0
1217+
assert 'abcabca'.index_u8(`b`) == 1
1218+
assert 'abcabca'.index_u8(`c`) == 2
1219+
//
1220+
assert 'abc'.index_u8(`d`) == -1
1221+
assert 'abc'.index_u8(`A`) == -1
1222+
assert 'abc'.index_u8(`B`) == -1
1223+
assert 'abc'.index_u8(`C`) == -1
1224+
//
1225+
}
1226+
1227+
fn test_last_index_u8() {
1228+
assert 'abcabca'.last_index_u8(`a`) == 6
1229+
assert 'abcabca'.last_index_u8(`c`) == 5
1230+
assert 'abcabca'.last_index_u8(`b`) == 4
1231+
assert 'Zabcabca'.last_index_u8(`Z`) == 0
1232+
//
1233+
assert 'abc'.index_u8(`d`) == -1
1234+
assert 'abc'.index_u8(`A`) == -1
1235+
assert 'abc'.index_u8(`B`) == -1
1236+
assert 'abc'.index_u8(`C`) == -1
1237+
}
1238+
1239+
fn test_contains_byte() {
1240+
assert 'abc abca'.contains_u8(`a`)
1241+
assert 'abc abca'.contains_u8(`b`)
1242+
assert 'abc abca'.contains_u8(`c`)
1243+
assert 'abc abca'.contains_u8(` `)
1244+
assert !'abc abca'.contains_u8(`A`)
1245+
}

0 commit comments

Comments
 (0)