mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
strings: replace_each([]); orm: update
This commit is contained in:
parent
4e69c40e12
commit
cdfbb2978d
@ -190,6 +190,101 @@ pub fn (s string) replace(rep, with string) string {
|
||||
return tos(b, new_len)
|
||||
}
|
||||
|
||||
struct RepIndex {
|
||||
idx int
|
||||
val_idx int
|
||||
}
|
||||
|
||||
fn (a mut []RepIndex) sort() {
|
||||
a.sort_with_compare(compare_rep_index)
|
||||
}
|
||||
|
||||
|
||||
// TODO
|
||||
/*
|
||||
fn (a RepIndex) < (b RepIndex) bool {
|
||||
return a.idx < b.idx
|
||||
}
|
||||
*/
|
||||
|
||||
fn compare_rep_index(a, b &RepIndex) int {
|
||||
if a.idx < b.idx {
|
||||
return -1
|
||||
}
|
||||
if a.idx > b.idx {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
pub fn (s string) replace_each(vals []string) string {
|
||||
if s.len == 0 || vals.len == 0 {
|
||||
return s
|
||||
}
|
||||
if vals.len % 2 != 0 {
|
||||
println('string.replace_many(): odd number of strings')
|
||||
return s
|
||||
}
|
||||
// `rep` - string to replace
|
||||
// `with` - string to replace with
|
||||
// Remember positions of all rep strings, and calculate the length
|
||||
// of the new string to do just one allocation.
|
||||
mut new_len := s.len
|
||||
mut idxs := []RepIndex
|
||||
mut idx := 0
|
||||
for rep_i := 0; rep_i < vals.len; rep_i+=2 {
|
||||
// vals: ['rep1, 'with1', 'rep2', 'with2']
|
||||
rep := vals[rep_i]
|
||||
with := vals[rep_i+1]
|
||||
for {
|
||||
idx = s.index_after(rep, idx)
|
||||
if idx == -1 {
|
||||
break
|
||||
}
|
||||
// We need to remember both the position in the string,
|
||||
// and which rep/with pair it refers to.
|
||||
idxs << RepIndex{idx, rep_i}
|
||||
idx++
|
||||
new_len += with.len - rep.len
|
||||
}
|
||||
}
|
||||
// Dont change the string if there's nothing to replace
|
||||
if idxs.len == 0 {
|
||||
return s
|
||||
}
|
||||
idxs.sort()
|
||||
mut b := malloc(new_len + 1)// add a \0 just in case
|
||||
// Fill the new string
|
||||
mut idx_pos := 0
|
||||
mut cur_idx := idxs[idx_pos]
|
||||
mut b_i := 0
|
||||
for i := 0; i < s.len; i++ {
|
||||
// Reached the location of rep, replace it with "with"
|
||||
if i == cur_idx.idx {
|
||||
rep := vals[cur_idx.val_idx]
|
||||
with := vals[cur_idx.val_idx+1]
|
||||
for j := 0; j < with.len; j++ {
|
||||
b[b_i] = with[j]
|
||||
b_i++
|
||||
}
|
||||
// Skip the length of rep, since we just replaced it with "with"
|
||||
i += rep.len - 1
|
||||
// Go to the next index
|
||||
idx_pos++
|
||||
if idx_pos < idxs.len {
|
||||
cur_idx = idxs[idx_pos]
|
||||
}
|
||||
}
|
||||
// Rep doesnt start here, just copy
|
||||
else {
|
||||
b[b_i] = s[i]
|
||||
b_i++
|
||||
}
|
||||
}
|
||||
b[new_len] = `\0`
|
||||
return tos(b, new_len)
|
||||
}
|
||||
|
||||
pub fn (s string) bool() bool {
|
||||
return s == 'true' || s == 't' // TODO t for pg, remove
|
||||
}
|
||||
|
@ -219,6 +219,22 @@ fn test_replace() {
|
||||
assert c.replace('','-') == c
|
||||
}
|
||||
|
||||
fn test_replace_each() {
|
||||
s := 'hello man man :)'
|
||||
q := s.replace_each([
|
||||
'man', 'dude',
|
||||
'hello', 'hey'
|
||||
])
|
||||
assert q == 'hey dude dude :)'
|
||||
bb := '[b]bold[/b] [code]code[/code]'
|
||||
assert bb.replace_each([
|
||||
'[b]', '<b>',
|
||||
'[/b]', '</b>',
|
||||
'[code]', '<code>',
|
||||
'[/code]', '</code>'
|
||||
]) == '<b>bold</b> <code>code</code>'
|
||||
}
|
||||
|
||||
fn test_itoa() {
|
||||
num := 777
|
||||
assert num.str() == '777'
|
||||
|
@ -1764,7 +1764,11 @@ fn (p mut Parser) var_expr(v Var) string {
|
||||
name := p.tokens[p.token_idx].lit
|
||||
if !name.contains('exec') && !name.starts_with('q_') {
|
||||
p.next()
|
||||
p.insert_query(fn_ph)
|
||||
if name == 'insert' {
|
||||
p.insert_query(fn_ph)
|
||||
} else if name == 'update' {
|
||||
p.update_query(fn_ph)
|
||||
}
|
||||
return 'void'
|
||||
}
|
||||
}
|
||||
|
@ -245,3 +245,63 @@ fn (p mut Parser) insert_query(fn_ph int) {
|
||||
0, params, 0, 0, 0)')
|
||||
}
|
||||
|
||||
// `db.update User set nr_orders=nr_orders+1`
|
||||
fn (p mut Parser) update_query(fn_ph int) {
|
||||
println('update query')
|
||||
p.check_name()
|
||||
table_name := p.check_name()
|
||||
typ := p.table.find_type(table_name)
|
||||
if typ.name == '' {
|
||||
p.error('unknown type `$table_name`')
|
||||
}
|
||||
set := p.check_name()
|
||||
if set != 'set' {
|
||||
p.error('expected `set`')
|
||||
}
|
||||
if typ.fields.len == 0 {
|
||||
p.error('V orm: update: empty fields in `$typ.name`')
|
||||
}
|
||||
if typ.fields[0].name != 'id' {
|
||||
p.error('V orm: `id int` must be the first field in `$typ.name`')
|
||||
}
|
||||
field := p.check_name()
|
||||
p.check(.assign)
|
||||
for f in typ.fields {
|
||||
if !(f.typ in ['string', 'int', 'bool']) {
|
||||
println('orm: skipping $f.name')
|
||||
continue
|
||||
}
|
||||
p.register_var({ f | is_mut: true, is_used:true, is_changed:true })
|
||||
}
|
||||
mut q := 'update ${typ.name}s set $field='
|
||||
p.is_sql = true
|
||||
set_typ, expr := p.tmp_expr()
|
||||
p.is_sql = false
|
||||
// TODO this hack should not be necessary
|
||||
if set_typ == 'bool' {
|
||||
if expr.trim_space() == '1' {
|
||||
q += 'true'
|
||||
}
|
||||
else {
|
||||
q += 'false'
|
||||
}
|
||||
} else {
|
||||
q += expr
|
||||
}
|
||||
// where
|
||||
if p.tok == .name && p.lit == 'where' {
|
||||
p.next()
|
||||
p.is_sql = true
|
||||
_, wexpr := p.tmp_expr()
|
||||
p.is_sql = false
|
||||
q += ' where ' + wexpr
|
||||
}
|
||||
|
||||
|
||||
nr_vals := 0
|
||||
p.cgen.insert_before('char* params[$nr_vals];')// + params)
|
||||
p.cgen.set_placeholder(fn_ph, 'PQexecParams( ')
|
||||
println('update q="$q"')
|
||||
p.genln('.conn, "$q", $nr_vals, 0, params, 0, 0, 0)')
|
||||
}
|
||||
|
||||
|
@ -196,6 +196,7 @@ pub fn run<T>(app mut T, port int) {
|
||||
// }
|
||||
|
||||
// Call the right action
|
||||
println('action=$action')
|
||||
app.$action() or {
|
||||
conn.write(HTTP_404) or {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user