map: fix map.clone, refactor, fix map_get_1, map_set_1 non-string keys (#7538)

pull/7606/head
Nick Treleaven 2020-12-27 10:54:12 +00:00 committed by GitHub
parent 9d71a54a61
commit bcdf3ca0cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 22 deletions

View File

@ -139,18 +139,10 @@ fn (d &DenseArray) has_index(i int) bool {
return d.deletes == 0 || unsafe { d.all_deleted[i] } == 0 return d.deletes == 0 || unsafe { d.all_deleted[i] } == 0
} }
[inline] // Make space to append an element to array and return index
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
// The growth-factor is roughly 1.125 `(x + (x >> 3))` // The growth-factor is roughly 1.125 `(x + (x >> 3))`
[inline] [inline]
fn (mut d DenseArray) push(key voidptr, value voidptr) int { fn (mut d DenseArray) push() int {
if d.cap == d.len { if d.cap == d.len {
d.cap += d.cap >> 3 d.cap += d.cap >> 3
unsafe { unsafe {
@ -166,9 +158,6 @@ fn (mut d DenseArray) push(key voidptr, value voidptr) int {
if d.deletes != 0 { if d.deletes != 0 {
d.all_deleted[push_index] = 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++ d.len++
return push_index return push_index
@ -281,6 +270,14 @@ fn (m &map) key_to_index(pkey voidptr) (u32, u32) {
return u32(index), u32(meta) 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) { fn (m &map) free_key(pkey voidptr) {
(*&string(pkey)).free() (*&string(pkey)).free()
} }
@ -369,7 +366,12 @@ fn (mut m map) set_1(key voidptr, value voidptr) {
index += 2 index += 2
meta += probe_inc 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.meta_greater(index, meta, u32(kv_index))
m.len++ m.len++
} }
@ -580,7 +582,7 @@ pub fn (m &map) keys() []string {
} }
unsafe { unsafe {
pkey := m.key_values.key(i) pkey := m.key_values.key(i)
m.key_values.clone_key(item, pkey) m.clone_key(item, pkey)
item += m.key_bytes item += m.key_bytes
} }
} }
@ -595,7 +597,7 @@ pub fn (m &map) keys_1() array {
for i := 0; i < m.key_values.len; i++ { for i := 0; i < m.key_values.len; i++ {
unsafe { unsafe {
pkey := m.key_values.key(i) pkey := m.key_values.key(i)
m.key_values.clone_key(item, pkey) m.clone_key(item, pkey)
item += m.key_bytes item += m.key_bytes
} }
} }
@ -607,13 +609,14 @@ pub fn (m &map) keys_1() array {
} }
unsafe { unsafe {
pkey := m.key_values.key(i) pkey := m.key_values.key(i)
m.key_values.clone_key(item, pkey) m.clone_key(item, pkey)
item += m.key_bytes item += m.key_bytes
} }
} }
return keys return keys
} }
// warning: only copies keys, does not clone
[unsafe] [unsafe]
pub fn (d &DenseArray) clone() DenseArray { pub fn (d &DenseArray) clone() DenseArray {
res := DenseArray{ res := DenseArray{
@ -632,7 +635,6 @@ pub fn (d &DenseArray) clone() DenseArray {
} }
res.data = memdup(d.data, d.cap * d.slot_bytes) res.data = memdup(d.data, d.cap * d.slot_bytes)
} }
// FIXME clone each key
return res return res
} }
@ -651,6 +653,13 @@ pub fn (m &map) clone() map {
len: m.len len: m.len
} }
unsafe { C.memcpy(res.metas, m.metas, metasize) } 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 return res
} }

View File

@ -1726,6 +1726,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.writeln(');') g.writeln(');')
} else if sym.kind == .map { } else if sym.kind == .map {
info := sym.info as table.Map info := sym.info as table.Map
skeytyp := g.typ(info.key_type)
styp := g.typ(info.value_type) styp := g.typ(info.value_type)
zero := g.type_default(info.value_type) zero := g.type_default(info.value_type)
val_typ := g.table.get_type_symbol(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 { } else {
g.expr(left.left) g.expr(left.left)
} }
g.write(', &(string[]){') g.write(', &($skeytyp[]){')
g.expr(left.index) g.expr(left.index)
g.write('}') g.write('}')
if val_typ.kind == .function { if val_typ.kind == .function {
@ -3884,6 +3885,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
} }
} else if sym.kind == .map { } else if sym.kind == .map {
info := sym.info as table.Map info := sym.info as table.Map
key_type_str := g.typ(info.key_type)
elem_type_str := g.typ(info.value_type) elem_type_str := g.typ(info.value_type)
elem_typ := g.table.get_type_symbol(info.value_type) elem_typ := g.table.get_type_symbol(info.value_type)
get_and_set_types := elem_typ.kind in [.struct_, .map] 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('.val')
} }
} }
g.write(', &(string[]){') g.write(', &($key_type_str[]){')
g.expr(node.index) g.expr(node.index)
g.write('}') g.write('}')
if elem_typ.kind == .function { if elem_typ.kind == .function {
@ -3925,7 +3927,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
g.write('&') g.write('&')
} }
g.expr(node.left) g.expr(node.left)
g.write(', &(string[]){') g.write(', &($key_type_str[]){')
g.expr(node.index) g.expr(node.index)
g.write('}, &($elem_type_str[]){ $zero }))') g.write('}, &($elem_type_str[]){ $zero }))')
} else { } else {
@ -3955,7 +3957,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
g.write('.val') g.write('.val')
} }
} }
g.write('), &(string[]){') g.write('), &($key_type_str[]){')
g.expr(node.index) g.expr(node.index)
g.write('}') g.write('}')
if g.is_fn_index_call { if g.is_fn_index_call {