string: make `index()` return `?int` instead of `int`/-1

pull/2940/head
Alexander Medvednikov 2019-11-30 13:09:05 +03:00
parent cc2bd0bb68
commit 81d4f66fbb
11 changed files with 117 additions and 103 deletions

View File

@ -134,11 +134,8 @@ pub fn cstring_to_vstring(cstr byteptr) string {
} }
pub fn (s string) replace_once(rep, with string) string { pub fn (s string) replace_once(rep, with string) string {
index := s.index(rep) index := s.index(rep) or { return s }
if index != -1 {
return s.substr(0,index) + with + s.substr(index + rep.len, s.len) return s.substr(0,index) + with + s.substr(index + rep.len, s.len)
}
return s
} }
pub fn (s string) replace(rep, with string) string { pub fn (s string) replace(rep, with string) string {
@ -151,8 +148,7 @@ pub fn (s string) replace(rep, with string) string {
mut rem := s mut rem := s
mut rstart := 0 mut rstart := 0
for { for {
mut i := rem.index(rep) mut i := rem.index(rep) or { break }
if i < 0 {break}
idxs << rstart + i idxs << rstart + i
i += rep.len i += rep.len
rstart += i rstart += i
@ -428,7 +424,7 @@ fn (s string) substr(start, end int) string {
return res return res
} }
pub fn (s string) index(p string) int { pub fn (s string) index_old(p string) int {
if p.len > s.len { if p.len > s.len {
return -1 return -1
} }
@ -446,6 +442,24 @@ pub fn (s string) index(p string) int {
return -1 return -1
} }
pub fn (s string) index(p string) ?int {
if p.len > s.len {
return none
}
mut i := 0
for i < s.len {
mut j := 0
for j < p.len && s[i + j] == p[j] {
j++
}
if j == p.len {
return i
}
i++
}
return none
}
// KMP search // KMP search
pub fn (s string) index_kmp(p string) int { pub fn (s string) index_kmp(p string) int {
if p.len > s.len { if p.len > s.len {
@ -480,11 +494,9 @@ pub fn (s string) index_kmp(p string) int {
pub fn (s string) index_any(chars string) int { pub fn (s string) index_any(chars string) int {
for c in chars { for c in chars {
index := s.index(c.str()) index := s.index(c.str()) or { continue }
if index != -1 {
return index return index
} }
}
return -1 return -1
} }
@ -573,13 +585,15 @@ pub fn (s string) count(substr string) int {
} }
pub fn (s string) contains(p string) bool { pub fn (s string) contains(p string) bool {
res := s.index(p) > 0 - 1 _ = s.index(p) or {
return res return false
}
return true
} }
pub fn (s string) starts_with(p string) bool { pub fn (s string) starts_with(p string) bool {
res := s.index(p) == 0 idx := s.index(p) or { return false }
return res return idx == 0
} }
pub fn (s string) ends_with(p string) bool { pub fn (s string) ends_with(p string) bool {
@ -628,16 +642,10 @@ pub fn (s string) title() string {
// 'hey [man] how you doin' // 'hey [man] how you doin'
// find_between('[', ']') == 'man' // find_between('[', ']') == 'man'
pub fn (s string) find_between(start, end string) string { pub fn (s string) find_between(start, end string) string {
start_pos := s.index(start) start_pos := s.index(start) or { return '' }
if start_pos == -1 {
return ''
}
// First get everything to the right of 'start' // First get everything to the right of 'start'
val := s.right(start_pos + start.len) val := s.right(start_pos + start.len)
end_pos := val.index(end) end_pos := val.index(end) or { return val }
if end_pos == -1 {
return val
}
return val.left(end_pos) return val.left(end_pos)
} }
@ -984,10 +992,7 @@ fn (arr []string) free() {
// all_before('23:34:45.234', '.') == '23:34:45' // all_before('23:34:45.234', '.') == '23:34:45'
pub fn (s string) all_before(dot string) string { pub fn (s string) all_before(dot string) string {
pos := s.index(dot) pos := s.index(dot) or { return s }
if pos == -1 {
return s
}
return s.left(pos) return s.left(pos)
} }

View File

@ -84,7 +84,7 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
mut fos := '' mut fos := ''
mut name := '' mut name := ''
if flag.starts_with('linux') || flag.starts_with('darwin') || flag.starts_with('freebsd') || flag.starts_with('windows') { if flag.starts_with('linux') || flag.starts_with('darwin') || flag.starts_with('freebsd') || flag.starts_with('windows') {
pos := flag.index(' ') pos := flag.index(' ') or { return none }
fos = flag[..pos].trim_space() fos = flag[..pos].trim_space()
flag = flag[pos..].trim_space() flag = flag[pos..].trim_space()
} }
@ -101,16 +101,21 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
} }
} }
} }
for i in [flag.index(' '), flag.index(',')] { if i := flag.index(' ') {
if index == -1 || (i != -1 && i < index) { if index == -1 || i < index {
index = i
}
}
if i := flag.index(',') {
if index == -1 || i < index {
index = i index = i
} }
} }
if index != -1 && flag[index] == ` ` && flag[index+1] == `-` { if index != -1 && flag[index] == ` ` && flag[index+1] == `-` {
for f in allowed_flags { for f in allowed_flags {
i := index+f.len j := index+f.len
if i < flag.len && f == flag[index..i] { if j < flag.len && f == flag[index..j] {
index = i index = j
break break
} }
} }

View File

@ -220,8 +220,8 @@ fn (p mut Parser) chash() {
} }
// TODO remove after ui_mac.m is removed // TODO remove after ui_mac.m is removed
else if hash.contains('embed') { else if hash.contains('embed') {
pos := hash.index('embed') + 5 pos := hash.index('embed') or { return }
file := hash[pos..] file := hash[pos+5..]
//if p.pref.build_mode != .default_mode { //if p.pref.build_mode != .default_mode {
p.genln('#include $file') p.genln('#include $file')
//} //}

View File

@ -799,8 +799,7 @@ pub fn get_arg(joined_args, arg, def string) string {
pub fn get_param_after(joined_args, arg, def string) string { pub fn get_param_after(joined_args, arg, def string) string {
key := '$arg ' key := '$arg '
mut pos := joined_args.index(key) mut pos := joined_args.index(key) or {
if pos == -1 {
return def return def
} }
pos += key.len pos += key.len

View File

@ -1068,9 +1068,12 @@ fn (p mut Parser) get_type() string {
//} //}
return 'void*' return 'void*'
} }
/*
TODO this is not needed?
if typ.last_index('__') > typ.index('__') { if typ.last_index('__') > typ.index('__') {
p.error('2 __ in gettype(): typ="$typ"') p.error('2 __ in gettype(): typ="$typ"')
} }
*/
return typ return typ
} }
@ -1410,9 +1413,11 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) {
{ {
line := p.cgen.cur_line line := p.cgen.cur_line
vname := line[..pos].replace('=','') // TODO cgen line hack vname := line[..pos].replace('=','') // TODO cgen line hack
p.cgen.resetln(line.replace(line[..line.index('=')+1], '')) if idx := line.index('=') {
p.cgen.resetln(line.replace(line[..idx+1], ''))
p.gen_handle_option_or_else(expr_type, vname, ph) p.gen_handle_option_or_else(expr_type, vname, ph)
} }
}
else if expr_type[0]==`[` { else if expr_type[0]==`[` {
// assignment to a fixed_array `mut a:=[3]int a=[1,2,3]!!` // assignment to a fixed_array `mut a:=[3]int a=[1,2,3]!!`
expr := p.cgen.cur_line[pos..].all_after('{').all_before('}') // TODO cgen line hack expr := p.cgen.cur_line[pos..].all_after('{').all_before('}') // TODO cgen line hack
@ -3053,13 +3058,11 @@ fn (p mut Parser) defer_st() {
} }
fn (p mut Parser) check_and_register_used_imported_type(typ_name string) { fn (p mut Parser) check_and_register_used_imported_type(typ_name string) {
us_idx := typ_name.index('__') us_idx := typ_name.index('__') or { return }
if us_idx != -1 {
arg_mod := typ_name[..us_idx] arg_mod := typ_name[..us_idx]
if p.import_table.known_alias(arg_mod) { if p.import_table.known_alias(arg_mod) {
p.import_table.register_used_import(arg_mod) p.import_table.register_used_import(arg_mod)
} }
}
} }
fn (p mut Parser) check_unused_imports() { fn (p mut Parser) check_unused_imports() {

View File

@ -157,8 +157,10 @@ fn (p mut Parser) get_type2() Type {
typ = 'Option_$typ' typ = 'Option_$typ'
p.table.register_type_with_parent(typ, 'Option') p.table.register_type_with_parent(typ, 'Option')
} }
/*
if typ.last_index('__') > typ.index('__') { if typ.last_index('__') > typ.index('__') {
p.error('2 __ in gettype(): typ="$typ"') p.error('2 __ in gettype(): typ="$typ"')
} }
*/
return Type{name: typ, cat: cat} return Type{name: typ, cat: cat}
} }

View File

@ -931,8 +931,8 @@ fn (p &Parser) identify_typo(name string) string {
// compare just name part, some items are mod prefied // compare just name part, some items are mod prefied
fn typo_compare_name_mod(a, b, b_mod string) f32 { fn typo_compare_name_mod(a, b, b_mod string) f32 {
if a.len - b.len > 2 || b.len - a.len > 2 { return 0 } if a.len - b.len > 2 || b.len - a.len > 2 { return 0 }
auidx := a.index('__') auidx := a.index('__') or { -1 }
buidx := b.index('__') buidx := b.index('__') or { -1 }
a_mod := if auidx != -1 { mod_gen_name_rev(a[..auidx]) } else { '' } a_mod := if auidx != -1 { mod_gen_name_rev(a[..auidx]) } else { '' }
a_name := if auidx != -1 { a[auidx+2..] } else { a } a_name := if auidx != -1 { a[auidx+2..] } else { a }
b_name := if buidx != -1 { b[buidx+2..] } else { b } b_name := if buidx != -1 { b[buidx+2..] } else { b }

View File

@ -115,7 +115,9 @@ pub fn (p mut Params) put_custom(name string, typ string, data voidptr) {
//HELPERS //HELPERS
fn parse_len(typ, s_tok, e_tok string) int { fn parse_len(typ, s_tok, e_tok string) int {
len := typ[typ.index(s_tok) + 1 .. typ.index(e_tok)].int() start_index := typ.index(s_tok) or { return 0 }
end_index := typ.index(e_tok) or { return 0 }
len := typ[start_index+1..end_index].int()
//t := typ.substr(typ.index(e_tok) + 1, typ.len) //t := typ.substr(typ.index(e_tok) + 1, typ.len)
return len return len
} }

View File

@ -516,8 +516,8 @@ fn parse_url(rawurl string, via_request bool) ?URL {
// RFC 3986, §3.3: // RFC 3986, §3.3:
// In addition, a URI reference (Section 4.1) may be a relative-path reference, // 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. // in which case the first path segment cannot contain a colon (':') character.
colon := rest.index(':') colon := rest.index(':') or { -1 }
slash := rest.index('/') slash := rest.index('/') or { -1 }
if colon >= 0 && (slash < 0 || colon < slash) { if colon >= 0 && (slash < 0 || colon < slash) {
// First path segment has colon. Not allowed in relative URL. // First path segment has colon. Not allowed in relative URL.
return error(error_msg('parse_url: first path segment in URL cannot contain colon', '')) return error(error_msg('parse_url: first path segment in URL cannot contain colon', ''))
@ -615,8 +615,7 @@ fn parse_host(host string) ?string {
// can only %-encode non-ASCII bytes. // can only %-encode non-ASCII bytes.
// We do impose some restrictions on the zone, to avoid stupidity // We do impose some restrictions on the zone, to avoid stupidity
// like newlines. // like newlines.
zone := host[..i].index('%25') if zone := host[..i].index('%25') {
if zone >= 0 {
host1 := unescape(host[..zone], .encode_host) or { host1 := unescape(host[..zone], .encode_host) or {
return err return err
} }

View File

@ -313,8 +313,7 @@ pub fn (t Time) clean12() string {
// `parse` parses time in the following format: "2018-01-27 12:48:34" // `parse` parses time in the following format: "2018-01-27 12:48:34"
pub fn parse(s string) Time { pub fn parse(s string) Time {
// println('parse="$s"') // println('parse="$s"')
pos := s.index(' ') pos := s.index(' ') or {
if pos <= 0 {
println('bad time format') println('bad time format')
return now() return now()
} }

View File

@ -46,8 +46,8 @@ _ = header
} }
if line.contains('@if ') { if line.contains('@if ') {
s.writeln(STR_END) s.writeln(STR_END)
pos := line.index('@if') pos := line.index('@if') or { continue }
s.writeln('if ' + line[pos + 4..] + '{') s.writeln('if ' + line[pos+4..] + '{')
s.writeln(STR_START) s.writeln(STR_START)
} }
else if line.contains('@end') { else if line.contains('@end') {
@ -62,8 +62,8 @@ _ = header
} }
else if line.contains('@for') { else if line.contains('@for') {
s.writeln(STR_END) s.writeln(STR_END)
pos := line.index('@for') pos := line.index('@for') or { continue }
s.writeln('for ' + line[pos + 4..] + '{') s.writeln('for ' + line[pos+4..] + '{')
s.writeln(STR_START) s.writeln(STR_START)
} }
else if !in_css && line.contains('.') && line.ends_with('{') { else if !in_css && line.contains('.') && line.ends_with('{') {