Correct reflection usage of maps

This commit is contained in:
gingerBill
2022-11-08 11:50:55 +00:00
parent d77269dee2
commit 6dd4d1a924
4 changed files with 36 additions and 82 deletions
+11 -14
View File
@@ -257,21 +257,18 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
opt_write_start(w, opt, '{') or_return opt_write_start(w, opt, '{') or_return
if m != nil { if m != nil {
if info.generated_struct == nil { if info.map_info == nil {
return .Unsupported_Type return .Unsupported_Type
} }
entries := &m.entries map_cap := uintptr(runtime.map_cap(m^))
gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct) ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(m^, info.map_info)
ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array) for bucket_index in 0..<map_cap {
entry_type := ed.elem.variant.(runtime.Type_Info_Struct) if !runtime.map_hash_is_valid(hs[bucket_index]) {
entry_size := ed.elem_size continue
}
for i in 0..<entries.len { key := rawptr(runtime.map_cell_index_dynamic(ks, &info.map_info.ks, bucket_index))
opt_write_iteration(w, opt, i) or_return value := rawptr(runtime.map_cell_index_dynamic(vs, &info.map_info.vs, bucket_index))
data := uintptr(entries.data) + uintptr(i*entry_size)
key := rawptr(data + entry_type.offsets[2])
value := rawptr(data + entry_type.offsets[3])
// check for string type // check for string type
{ {
@@ -281,13 +278,13 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
name: string name: string
#partial switch info in ti.variant { #partial switch info in ti.variant {
case runtime.Type_Info_String: case runtime.Type_Info_String:
switch s in a { switch s in a {
case string: name = s case string: name = s
case cstring: name = string(s) case cstring: name = string(s)
} }
opt_write_key(w, opt, name) or_return opt_write_key(w, opt, name) or_return
case: return .Unsupported_Type case: return .Unsupported_Type
} }
} }
+3 -6
View File
@@ -399,12 +399,10 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
return UNSUPPORTED_TYPE return UNSUPPORTED_TYPE
} }
raw_map := (^mem.Raw_Map)(v.data) raw_map := (^mem.Raw_Map)(v.data)
if raw_map.entries.allocator.procedure == nil { if raw_map.allocator.procedure == nil {
raw_map.entries.allocator = p.allocator raw_map.allocator = p.allocator
} }
header := runtime.__get_map_header_table_runtime(t)
elem_backing := bytes_make(t.value.size, t.value.align, p.allocator) or_return elem_backing := bytes_make(t.value.size, t.value.align, p.allocator) or_return
defer delete(elem_backing, p.allocator) defer delete(elem_backing, p.allocator)
@@ -421,7 +419,6 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
return err return err
} }
key_hash := runtime.default_hasher_string(&key, 0)
key_ptr := rawptr(&key) key_ptr := rawptr(&key)
key_cstr: cstring key_cstr: cstring
@@ -430,7 +427,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
key_ptr = &key_cstr key_ptr = &key_cstr
} }
set_ptr := runtime.__dynamic_map_set(raw_map, header, key_hash, key_ptr, map_backing_value.data) set_ptr := runtime.__dynamic_map_set(raw_map, t.map_info, key_ptr, map_backing_value.data)
if set_ptr == nil { if set_ptr == nil {
delete(key, p.allocator) delete(key, p.allocator)
} }
-36
View File
@@ -1,36 +0,0 @@
package reflect
import "core:runtime"
_ :: runtime
Map_Entry_Info :: struct($Key, $Value: typeid) {
hash: uintptr,
key: Key,
value: Value,
}
map_entry_info_slice :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V), err: runtime.Allocator_Error) #no_bounds_check {
m := m
rm := (^runtime.Raw_Map)(&m)
info := type_info_base(type_info_of(M)).variant.(Type_Info_Map)
if info.map_info != nil {
entries = make(type_of(entries), len(m), allocator) or_return
map_cap := uintptr(cap(m))
ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(rm^, info.map_info)
entry_index := 0
for bucket_index in 0..<map_cap {
if hash := hs[bucket_index]; runtime.map_hash_is_valid(hash) {
key := runtime.map_cell_index_dynamic(ks, &info.map_info.ks, bucket_index)
value := runtime.map_cell_index_dynamic(vs, &info.map_info.vs, bucket_index)
entries[entry_index].hash = hash
entries[entry_index].key = (^K)(key)^
entries[entry_index].value = (^V)(value)^
entry_index += 1
}
}
}
return
}
+22 -26
View File
@@ -6,8 +6,8 @@ import "core:runtime"
_ :: intrinsics _ :: intrinsics
_ :: runtime _ :: runtime
map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K) { map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K, err: runtime.Allocator_Error) {
keys = make(type_of(keys), len(m), allocator) keys = make(type_of(keys), len(m), allocator) or_return
i := 0 i := 0
for key in m { for key in m {
keys[i] = key keys[i] = key
@@ -15,8 +15,8 @@ map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K)
} }
return return
} }
map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (values: []V) { map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (values: []V, err: runtime.Allocator_Error) {
values = make(type_of(values), len(m), allocator) values = make(type_of(values), len(m), allocator) or_return
i := 0 i := 0
for _, value in m { for _, value in m {
values[i] = value values[i] = value
@@ -37,8 +37,8 @@ Map_Entry_Info :: struct($Key, $Value: typeid) {
} }
map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V)) { map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V), err: runtime.Allocator) {
entries = make(type_of(entries), len(m), allocator) entries = make(type_of(entries), len(m), allocator) or_return
i := 0 i := 0
for key, value in m { for key, value in m {
entries[i].key = key entries[i].key = key
@@ -52,28 +52,24 @@ map_entry_infos :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (ent
m := m m := m
rm := (^runtime.Raw_Map)(&m) rm := (^runtime.Raw_Map)(&m)
info := runtime.type_info_base(type_info_of(M)).variant.(runtime.Type_Info_Map) info := type_info_base(type_info_of(M)).variant.(Type_Info_Map)
gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct) if info.map_info != nil {
ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array) entries = make(type_of(entries), len(m), allocator) or_return
entry_type := ed.elem.variant.(runtime.Type_Info_Struct)
key_offset := entry_type.offsets[2]
value_offset := entry_type.offsets[3]
entry_size := uintptr(ed.elem_size)
entries = make(type_of(entries), rm.entries.len) map_cap := uintptr(cap(m))
ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(rm^, info.map_info)
entry_index := 0
for bucket_index in 0..<map_cap {
if hash := hs[bucket_index]; runtime.map_hash_is_valid(hash) {
key := runtime.map_cell_index_dynamic(ks, &info.map_info.ks, bucket_index)
value := runtime.map_cell_index_dynamic(vs, &info.map_info.vs, bucket_index)
entries[entry_index].hash = hash
entries[entry_index].key = (^K)(key)^
entries[entry_index].value = (^V)(value)^
data := uintptr(rm.entries.data) entry_index += 1
for i in 0..<rm.entries.len { }
header := (^runtime.Map_Entry_Header)(data) }
hash := header.hash
key := (^K)(data + key_offset)^
value := (^V)(data + value_offset)^
entries[i] = {hash, key, value}
data += entry_size
} }
return return
} }