map: make DenseArray.has_index not assume string keys (#7284)

pull/7300/head
Nick Treleaven 2020-12-13 01:05:56 +00:00 committed by GitHub
parent 4324be9bd8
commit ae460a2208
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 11 deletions

View File

@ -100,7 +100,10 @@ mut:
cap int cap int
len int len int
deletes u32 // count deletes u32 // count
data byteptr // array of interspersed key data and value data // array allocated (with `cap` bytes) on first deletion
// has non-zero element when key deleted
all_deleted &byte
data byteptr // array of interleaved key data and value data
} }
[inline] [inline]
@ -115,6 +118,7 @@ fn new_dense_array(key_bytes int, value_bytes int) DenseArray {
cap: cap cap: cap
len: 0 len: 0
deletes: 0 deletes: 0
all_deleted: 0
data: malloc(cap * slot_bytes) data: malloc(cap * slot_bytes)
} }
} }
@ -132,9 +136,7 @@ fn (d &DenseArray) value(i int) voidptr {
[inline] [inline]
fn (d &DenseArray) has_index(i int) bool { fn (d &DenseArray) has_index(i int) bool {
// assume string keys for now return d.deletes == 0 || unsafe {d.all_deleted[i]} == 0
pkey := unsafe {&string(d.key(i))}
return pkey.str != 0
} }
// Push element to array and return index // Push element to array and return index
@ -145,10 +147,17 @@ fn (mut d DenseArray) push(key voidptr, value voidptr) int {
d.cap += d.cap >> 3 d.cap += d.cap >> 3
unsafe { unsafe {
d.data = v_realloc(d.data, d.slot_bytes * d.cap) d.data = v_realloc(d.data, d.slot_bytes * d.cap)
if d.deletes != 0 {
d.all_deleted = v_realloc(d.all_deleted, d.cap)
C.memset(d.all_deleted + d.len, 0, d.cap - d.len)
}
} }
} }
push_index := d.len push_index := d.len
unsafe { unsafe {
if d.deletes != 0 {
d.all_deleted[push_index] = 0
}
ptr := d.key(push_index) ptr := d.key(push_index)
C.memcpy(ptr, key, d.key_bytes) C.memcpy(ptr, key, d.key_bytes)
C.memcpy(byteptr(ptr) + d.key_bytes, value, d.value_bytes) C.memcpy(byteptr(ptr) + d.key_bytes, value, d.value_bytes)
@ -175,6 +184,8 @@ fn (mut d DenseArray) zeros_to_end() {
} }
free(tmp_buf) free(tmp_buf)
d.deletes = 0 d.deletes = 0
// TODO: reallocate instead as more deletes are likely
free(d.all_deleted)
d.len = count d.len = count
d.cap = if count < 8 { 8 } else { count } d.cap = if count < 8 { 8 } else { count }
unsafe { unsafe {
@ -468,12 +479,14 @@ pub fn (mut m map) delete(key string) {
index += 2 index += 2
} }
m.len-- m.len--
unsafe { if m.key_values.deletes == 0 {
m.metas[index] = 0 m.key_values.all_deleted = C.calloc(1, m.cap) // sets to 0
} }
m.key_values.deletes++ m.key_values.deletes++
// Mark key as deleted
unsafe { unsafe {
m.key_values.all_deleted[kv_index] = 1
m.metas[index] = 0
// Mark key as deleted
(*pkey).free() (*pkey).free()
C.memset(pkey, 0, sizeof(string)) C.memset(pkey, 0, sizeof(string))
} }
@ -484,7 +497,6 @@ pub fn (mut m map) delete(key string) {
if m.key_values.deletes >= (m.key_values.len >> 1) { if m.key_values.deletes >= (m.key_values.len >> 1) {
m.key_values.zeros_to_end() m.key_values.zeros_to_end()
m.rehash() m.rehash()
m.key_values.deletes = 0
} }
return return
} }
@ -525,7 +537,14 @@ pub fn (d DenseArray) clone() DenseArray {
cap: d.cap cap: d.cap
len: d.len len: d.len
deletes: d.deletes deletes: d.deletes
data: unsafe {memdup(d.data, d.cap * d.slot_bytes)} all_deleted: 0
data: 0
}
unsafe {
if d.deletes != 0 {
res.all_deleted = memdup(d.all_deleted, d.cap)
}
res.data = memdup(d.data, d.cap * d.slot_bytes)
} }
// FIXME clone each key // FIXME clone each key
return res return res
@ -568,6 +587,7 @@ pub fn (m &map) free() {
(*pkey).free() (*pkey).free()
} }
} }
unsafe {free(m.key_values.all_deleted)}
} }
unsafe {free(m.key_values.data)} unsafe {free(m.key_values.data)}
} }

View File

@ -5,7 +5,7 @@ const (
) )
fn unique_strings(arr_len int, str_len int) []string { fn unique_strings(arr_len int, str_len int) []string {
mut arr := []string{} mut arr := []string{cap: arr_len}
for arr.len < arr_len { for arr.len < arr_len {
str := rand.string(str_len) str := rand.string(str_len)
if str !in arr { if str !in arr {