From bcdf3ca0cf7e17876490cdff9900de734f94ed58 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 27 Dec 2020 10:54:12 +0000 Subject: [PATCH] map: fix map.clone, refactor, fix map_get_1, map_set_1 non-string keys (#7538) --- vlib/builtin/map.v | 45 +++++++++++++++++++++++++++------------------ vlib/v/gen/cgen.v | 10 ++++++---- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index db5cd3cb6a..b8511c978e 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -139,18 +139,10 @@ fn (d &DenseArray) has_index(i int) bool { return d.deletes == 0 || unsafe { d.all_deleted[i] } == 0 } -[inline] -fn (d &DenseArray) clone_key(dest voidptr, pkey voidptr) { - unsafe { - s := (*&string(pkey)).clone() - C.memcpy(dest, &s, d.key_bytes) - } -} - -// Push element to array and return index +// Make space to append an element to array and return index // The growth-factor is roughly 1.125 `(x + (x >> 3))` [inline] -fn (mut d DenseArray) push(key voidptr, value voidptr) int { +fn (mut d DenseArray) push() int { if d.cap == d.len { d.cap += d.cap >> 3 unsafe { @@ -166,9 +158,6 @@ fn (mut d DenseArray) push(key voidptr, value voidptr) int { if d.deletes != 0 { d.all_deleted[push_index] = 0 } - ptr := d.key(push_index) - d.clone_key(ptr, key) - C.memcpy(byteptr(ptr) + d.key_bytes, value, d.value_bytes) } d.len++ return push_index @@ -281,6 +270,14 @@ fn (m &map) key_to_index(pkey voidptr) (u32, u32) { return u32(index), u32(meta) } +[inline] +fn (m &map) clone_key(dest voidptr, pkey voidptr) { + unsafe { + s := (*&string(pkey)).clone() + C.memcpy(dest, &s, m.key_bytes) + } +} + fn (m &map) free_key(pkey voidptr) { (*&string(pkey)).free() } @@ -369,7 +366,12 @@ fn (mut m map) set_1(key voidptr, value voidptr) { index += 2 meta += probe_inc } - kv_index := m.key_values.push(key, value) + kv_index := m.key_values.push() + unsafe { + pkey := m.key_values.key(kv_index) + m.clone_key(pkey, key) + C.memcpy(byteptr(pkey) + m.key_bytes, value, m.value_bytes) + } m.meta_greater(index, meta, u32(kv_index)) m.len++ } @@ -580,7 +582,7 @@ pub fn (m &map) keys() []string { } unsafe { pkey := m.key_values.key(i) - m.key_values.clone_key(item, pkey) + m.clone_key(item, pkey) item += m.key_bytes } } @@ -595,7 +597,7 @@ pub fn (m &map) keys_1() array { for i := 0; i < m.key_values.len; i++ { unsafe { pkey := m.key_values.key(i) - m.key_values.clone_key(item, pkey) + m.clone_key(item, pkey) item += m.key_bytes } } @@ -607,13 +609,14 @@ pub fn (m &map) keys_1() array { } unsafe { pkey := m.key_values.key(i) - m.key_values.clone_key(item, pkey) + m.clone_key(item, pkey) item += m.key_bytes } } return keys } +// warning: only copies keys, does not clone [unsafe] pub fn (d &DenseArray) clone() DenseArray { res := DenseArray{ @@ -632,7 +635,6 @@ pub fn (d &DenseArray) clone() DenseArray { } res.data = memdup(d.data, d.cap * d.slot_bytes) } - // FIXME clone each key return res } @@ -651,6 +653,13 @@ pub fn (m &map) clone() map { len: m.len } unsafe { C.memcpy(res.metas, m.metas, metasize) } + // clone keys + for i in 0 .. m.key_values.len { + if !m.key_values.has_index(i) { + continue + } + m.clone_key(res.key_values.key(i), m.key_values.key(i)) + } return res } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c1d7c5d871..cdbd9ca7e5 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1726,6 +1726,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.writeln(');') } else if sym.kind == .map { info := sym.info as table.Map + skeytyp := g.typ(info.key_type) styp := g.typ(info.value_type) zero := g.type_default(info.value_type) val_typ := g.table.get_type_symbol(info.value_type) @@ -1744,7 +1745,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } else { g.expr(left.left) } - g.write(', &(string[]){') + g.write(', &($skeytyp[]){') g.expr(left.index) g.write('}') if val_typ.kind == .function { @@ -3884,6 +3885,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { } } else if sym.kind == .map { info := sym.info as table.Map + key_type_str := g.typ(info.key_type) elem_type_str := g.typ(info.value_type) elem_typ := g.table.get_type_symbol(info.value_type) get_and_set_types := elem_typ.kind in [.struct_, .map] @@ -3905,7 +3907,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('.val') } } - g.write(', &(string[]){') + g.write(', &($key_type_str[]){') g.expr(node.index) g.write('}') if elem_typ.kind == .function { @@ -3925,7 +3927,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('&') } g.expr(node.left) - g.write(', &(string[]){') + g.write(', &($key_type_str[]){') g.expr(node.index) g.write('}, &($elem_type_str[]){ $zero }))') } else { @@ -3955,7 +3957,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('.val') } } - g.write('), &(string[]){') + g.write('), &($key_type_str[]){') g.expr(node.index) g.write('}') if g.is_fn_index_call {