From 81d4f66fbba47cf7a4f826d7e95f0c93fc6d05d0 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 30 Nov 2019 13:09:05 +0300 Subject: [PATCH] string: make `index()` return `?int` instead of `int`/-1 --- vlib/builtin/string.v | 61 ++++++++++++++++++---------------- vlib/compiler/cflags.v | 21 +++++++----- vlib/compiler/comptime.v | 20 ++++++------ vlib/compiler/main.v | 3 +- vlib/compiler/parser.v | 19 ++++++----- vlib/compiler/parser2.v | 2 ++ vlib/compiler/table.v | 4 +-- vlib/eventbus/params.v | 4 ++- vlib/net/urllib/urllib.v | 13 ++++---- vlib/time/time.v | 3 +- vlib/vweb/tmpl/tmpl.v | 70 ++++++++++++++++++++-------------------- 11 files changed, 117 insertions(+), 103 deletions(-) diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index d89371512b..07a2c1744b 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -134,11 +134,8 @@ pub fn cstring_to_vstring(cstr byteptr) string { } pub fn (s string) replace_once(rep, with string) string { - index := s.index(rep) - if index != -1 { - return s.substr(0,index) + with + s.substr(index + rep.len, s.len) - } - return s + index := s.index(rep) or { return s } + return s.substr(0,index) + with + s.substr(index + rep.len, s.len) } 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 rstart := 0 for { - mut i := rem.index(rep) - if i < 0 {break} + mut i := rem.index(rep) or { break } idxs << rstart + i i += rep.len rstart += i @@ -428,7 +424,7 @@ fn (s string) substr(start, end int) string { return res } -pub fn (s string) index(p string) int { +pub fn (s string) index_old(p string) int { if p.len > s.len { return -1 } @@ -446,6 +442,24 @@ pub fn (s string) index(p string) int { 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 pub fn (s string) index_kmp(p string) int { if p.len > s.len { @@ -480,10 +494,8 @@ pub fn (s string) index_kmp(p string) int { pub fn (s string) index_any(chars string) int { for c in chars { - index := s.index(c.str()) - if index != -1 { - return index - } + index := s.index(c.str()) or { continue } + return index } return -1 } @@ -573,13 +585,15 @@ pub fn (s string) count(substr string) int { } pub fn (s string) contains(p string) bool { - res := s.index(p) > 0 - 1 - return res + _ = s.index(p) or { + return false + } + return true } pub fn (s string) starts_with(p string) bool { - res := s.index(p) == 0 - return res + idx := s.index(p) or { return false } + return idx == 0 } pub fn (s string) ends_with(p string) bool { @@ -628,16 +642,10 @@ pub fn (s string) title() string { // 'hey [man] how you doin' // find_between('[', ']') == 'man' pub fn (s string) find_between(start, 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.right(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.left(end_pos) } @@ -984,10 +992,7 @@ fn (arr []string) free() { // all_before('23:34:45.234', '.') == '23:34:45' pub fn (s string) all_before(dot string) string { - pos := s.index(dot) - if pos == -1 { - return s - } + pos := s.index(dot) or { return s } return s.left(pos) } diff --git a/vlib/compiler/cflags.v b/vlib/compiler/cflags.v index db1aae1e7d..cc0dae78c7 100644 --- a/vlib/compiler/cflags.v +++ b/vlib/compiler/cflags.v @@ -84,7 +84,7 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool { mut fos := '' mut name := '' 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() 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 index == -1 || (i != -1 && i < index) { + if i := flag.index(' ') { + if index == -1 || i < index { + index = i + } + } + if i := flag.index(',') { + if index == -1 || i < index { index = i } } if index != -1 && flag[index] == ` ` && flag[index+1] == `-` { for f in allowed_flags { - i := index+f.len - if i < flag.len && f == flag[index..i] { - index = i + j := index+f.len + if j < flag.len && f == flag[index..j] { + index = j break } } @@ -149,7 +154,7 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool { fn (cflags []CFlag) c_options_before_target_msvc() string { return '' } fn (cflags []CFlag) c_options_after_target_msvc() string { return '' } -fn (cflags []CFlag) c_options_before_target() string { +fn (cflags []CFlag) c_options_before_target() string { // -I flags, optimization flags and so on mut args:=[]string for flag in cflags { @@ -185,7 +190,7 @@ fn (cflags []CFlag) c_options_without_object_files() string { fn (cflags []CFlag) c_options_only_object_files() string { mut args:=[]string for flag in cflags { - if flag.value.ends_with('.o') || flag.value.ends_with('.obj') { + if flag.value.ends_with('.o') || flag.value.ends_with('.obj') { args << flag.format() } } diff --git a/vlib/compiler/comptime.v b/vlib/compiler/comptime.v index 14a495fa71..323f6cc67c 100644 --- a/vlib/compiler/comptime.v +++ b/vlib/compiler/comptime.v @@ -39,7 +39,7 @@ fn (p mut Parser) comp_time() { for { if p.tok == .key_return { p.returns = true - } + } if p.tok == .lcbr { stack++ } else if p.tok == .rcbr { @@ -114,7 +114,7 @@ fn (p mut Parser) comp_time() { //p.gen('/* returns $p.returns */') } else if p.tok == .key_else { p.error('use `$' + 'else` instead of `else` in comptime if statements') - } + } } else if p.tok == .key_for { p.next() @@ -207,7 +207,7 @@ fn (p mut Parser) chash() { if !p.pref.building_v && !p.fileis('vlib') { p.warn('C #includes will soon be removed from the language' + '\ndefine the C structs and functions in V') - } + } */ if p.file_pcguard.len != 0 { //println('p: $p.file_platform $p.file_pcguard') @@ -220,8 +220,8 @@ fn (p mut Parser) chash() { } // TODO remove after ui_mac.m is removed else if hash.contains('embed') { - pos := hash.index('embed') + 5 - file := hash[pos..] + pos := hash.index('embed') or { return } + file := hash[pos+5..] //if p.pref.build_mode != .default_mode { p.genln('#include $file') //} @@ -262,13 +262,13 @@ fn (p mut Parser) comptime_method_call(typ Type) { mut j := 0 for i, method in typ.methods { if method.typ != 'void' { - + continue } receiver := method.args[0] if !p.expr_var.ptr { p.error('`$p.expr_var.name` needs to be a reference') - } + } amp := if receiver.is_mut && !p.expr_var.ptr { '&' } else { '' } if j > 0 { p.gen(' else ') @@ -290,7 +290,7 @@ fn (p mut Parser) comptime_method_call(typ Type) { fn (p mut Parser) gen_array_str(typ Type) { if typ.has_method('str') { return - } + } p.add_method(typ.name, Fn{ name: 'str' typ: 'string' @@ -381,7 +381,7 @@ fn (p mut Parser) gen_array_filter(str_typ string, method_ph int) { // V a := [1,2,3,4] b := a.filter(it % 2 == 0) - + // C array_int a = ...; array_int tmp2 = new_array(0, 4, 4); @@ -421,7 +421,7 @@ fn (p mut Parser) gen_array_map(str_typ string, method_ph int) string { // V a := [1,2,3,4] b := a.map(it * 2) - + // C array_int a = ...; array_int tmp2 = new_array(0, 4, 4); diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index 634ec0c28e..7b22f3480c 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -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 { key := '$arg ' - mut pos := joined_args.index(key) - if pos == -1 { + mut pos := joined_args.index(key) or { return def } pos += key.len diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index 7e3965c3e6..b2f32b2bf7 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -1068,9 +1068,12 @@ fn (p mut Parser) get_type() string { //} return 'void*' } + /* + TODO this is not needed? if typ.last_index('__') > typ.index('__') { p.error('2 __ in gettype(): typ="$typ"') } + */ return typ } @@ -1410,8 +1413,10 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { { line := p.cgen.cur_line vname := line[..pos].replace('=','') // TODO cgen line hack - p.cgen.resetln(line.replace(line[..line.index('=')+1], '')) - p.gen_handle_option_or_else(expr_type, vname, ph) + if idx := line.index('=') { + p.cgen.resetln(line.replace(line[..idx+1], '')) + p.gen_handle_option_or_else(expr_type, vname, ph) + } } else if expr_type[0]==`[` { // assignment to a fixed_array `mut a:=[3]int a=[1,2,3]!!` @@ -3053,12 +3058,10 @@ fn (p mut Parser) defer_st() { } fn (p mut Parser) check_and_register_used_imported_type(typ_name string) { - us_idx := typ_name.index('__') - if us_idx != -1 { - arg_mod := typ_name[..us_idx] - if p.import_table.known_alias(arg_mod) { - p.import_table.register_used_import(arg_mod) - } + us_idx := typ_name.index('__') or { return } + arg_mod := typ_name[..us_idx] + if p.import_table.known_alias(arg_mod) { + p.import_table.register_used_import(arg_mod) } } diff --git a/vlib/compiler/parser2.v b/vlib/compiler/parser2.v index f1e792c0ce..a331286dcb 100644 --- a/vlib/compiler/parser2.v +++ b/vlib/compiler/parser2.v @@ -157,8 +157,10 @@ fn (p mut Parser) get_type2() Type { typ = 'Option_$typ' p.table.register_type_with_parent(typ, 'Option') } + /* if typ.last_index('__') > typ.index('__') { p.error('2 __ in gettype(): typ="$typ"') } + */ return Type{name: typ, cat: cat} } diff --git a/vlib/compiler/table.v b/vlib/compiler/table.v index 8b97514423..30ec9b7f0a 100644 --- a/vlib/compiler/table.v +++ b/vlib/compiler/table.v @@ -931,8 +931,8 @@ fn (p &Parser) identify_typo(name string) string { // compare just name part, some items are mod prefied fn typo_compare_name_mod(a, b, b_mod string) f32 { if a.len - b.len > 2 || b.len - a.len > 2 { return 0 } - auidx := a.index('__') - buidx := b.index('__') + auidx := a.index('__') or { -1 } + buidx := b.index('__') or { -1 } a_mod := if auidx != -1 { mod_gen_name_rev(a[..auidx]) } else { '' } a_name := if auidx != -1 { a[auidx+2..] } else { a } b_name := if buidx != -1 { b[buidx+2..] } else { b } diff --git a/vlib/eventbus/params.v b/vlib/eventbus/params.v index 47f873945b..235452b183 100644 --- a/vlib/eventbus/params.v +++ b/vlib/eventbus/params.v @@ -115,7 +115,9 @@ pub fn (p mut Params) put_custom(name string, typ string, data voidptr) { //HELPERS 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) return len } diff --git a/vlib/net/urllib/urllib.v b/vlib/net/urllib/urllib.v index 89e0612aaa..652952c12e 100644 --- a/vlib/net/urllib/urllib.v +++ b/vlib/net/urllib/urllib.v @@ -386,7 +386,7 @@ fn (u &Userinfo) string() string { // If so, return [scheme, path]; else return ['', rawurl] fn split_by_scheme(rawurl string) ?[]string { for i := 0; i < rawurl.len; i++ { - c := rawurl[i] + c := rawurl[i] if (`a` <= c && c <= `z`) || (`A` <= c && c <= `Z`) { // do nothing } @@ -516,8 +516,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(':') - slash := rest.index('/') + colon := rest.index(':') or { -1 } + slash := rest.index('/') or { -1 } 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', '')) @@ -615,8 +615,7 @@ 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. - zone := host[..i].index('%25') - if zone >= 0 { + if zone := host[..i].index('%25') { host1 := unescape(host[..zone], .encode_host) or { return err } @@ -863,7 +862,7 @@ fn parse_query_values(m mut Values, query string) ?bool { continue } key = k - + v := query_unescape(value) or { had_error = true continue @@ -1046,7 +1045,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 && valid_optional_port(host[colon..]) { port = host[colon+1..] diff --git a/vlib/time/time.v b/vlib/time/time.v index b4703ffb3b..a30047166f 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -313,8 +313,7 @@ pub fn (t Time) clean12() string { // `parse` parses time in the following format: "2018-01-27 12:48:34" pub fn parse(s string) Time { // println('parse="$s"') - pos := s.index(' ') - if pos <= 0 { + pos := s.index(' ') or { println('bad time format') return now() } diff --git a/vlib/vweb/tmpl/tmpl.v b/vlib/vweb/tmpl/tmpl.v index cd797c2a97..9d5fe72956 100644 --- a/vlib/vweb/tmpl/tmpl.v +++ b/vlib/vweb/tmpl/tmpl.v @@ -2,52 +2,52 @@ // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. -module tmpl +module tmpl -import os -import strings +import os +import strings const ( STR_START = 'sb.write(\'' STR_END = '\' ) ' ) - + pub fn compile_template(path string) string { //lines := os.read_lines(path) mut html := os.read_file(path) or { panic('html failed') - } + } mut header := '' - if os.file_exists('header.html') { + if os.file_exists('header.html') { h := os.read_file('header.html') or { panic('html failed') - } - header = h.replace('\'', '"') - } - lines := html.split_into_lines() - mut s := strings.new_builder(1000) + } + header = h.replace('\'', '"') + } + lines := html.split_into_lines() + mut s := strings.new_builder(1000) base := path.all_after('/').replace('.html', '') - s.writeln(' + s.writeln(' mut sb := strings.new_builder(${lines.len * 30}) -header := \'$header\' -_ = header -//footer := \'footer\' -') +header := \'$header\' +_ = header +//footer := \'footer\' +') s.writeln(STR_START) - mut in_css :=true// false + mut in_css :=true// false for _line in lines { - line := _line.trim_space() + line := _line.trim_space() if line == '' { - //in_css = false - } + //in_css = false + } if line.contains('@if ') { s.writeln(STR_END) - pos := line.index('@if') - s.writeln('if ' + line[pos + 4..] + '{') + pos := line.index('@if') or { continue } + s.writeln('if ' + line[pos+4..] + '{') s.writeln(STR_START) } else if line.contains('@end') { @@ -62,24 +62,24 @@ _ = header } else if line.contains('@for') { s.writeln(STR_END) - pos := line.index('@for') - s.writeln('for ' + line[pos + 4..] + '{') + pos := line.index('@for') or { continue } + s.writeln('for ' + line[pos+4..] + '{') s.writeln(STR_START) } else if !in_css && line.contains('.') && line.ends_with('{') { - class := line.find_between('.', '{') - s.writeln('
') - } + class := line.find_between('.', '{') + s.writeln('
') + } else if !in_css && line == '}' { - s.writeln('
') - } - // HTML, may include `@var` - else { - s.writeln(line.replace('@', '\x24').replace('\'', '"') ) + s.writeln('
') + } + // HTML, may include `@var` + else { + s.writeln(line.replace('@', '\x24').replace('\'', '"') ) } } s.writeln(STR_END) - s.writeln('tmpl_res := sb.str() }') + s.writeln('tmpl_res := sb.str() }') return s.str() }