mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Basic get and set support for new map
This commit is contained in:
@@ -290,6 +290,12 @@ map_kvh_data_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Inf
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map_kvh_data_values_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info) -> (vs: uintptr) {
|
||||||
|
capacity := uintptr(1) << map_log2_cap(m)
|
||||||
|
return map_cell_index_dynamic(map_data(m), &info.ks, capacity) // Skip past ks to get start of vs
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// The only procedure which needs access to the context is the one which allocates the map.
|
// The only procedure which needs access to the context is the one which allocates the map.
|
||||||
map_alloc_dynamic :: proc(info: ^Map_Info, log2_capacity: uintptr, allocator := context.allocator) -> (result: Raw_Map, err: Allocator_Error) {
|
map_alloc_dynamic :: proc(info: ^Map_Info, log2_capacity: uintptr, allocator := context.allocator) -> (result: Raw_Map, err: Allocator_Error) {
|
||||||
@@ -490,12 +496,14 @@ map_add_hash_dynamic :: proc(m: Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash,
|
|||||||
@(optimization_mode="size")
|
@(optimization_mode="size")
|
||||||
map_grow_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Allocator_Error {
|
map_grow_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Allocator_Error {
|
||||||
allocator := m.allocator
|
allocator := m.allocator
|
||||||
|
if allocator.procedure == nil {
|
||||||
|
allocator = context.allocator
|
||||||
|
}
|
||||||
|
|
||||||
log2_capacity := map_log2_cap(m^)
|
log2_capacity := map_log2_cap(m^)
|
||||||
|
|
||||||
if m.data == 0 {
|
if m.data == 0 {
|
||||||
n := map_alloc_dynamic(info, MAP_MIN_LOG2_CAPACITY, allocator) or_return
|
m^ = map_alloc_dynamic(info, MAP_MIN_LOG2_CAPACITY, allocator) or_return
|
||||||
m.data = n.data
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,15 +520,21 @@ map_grow_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Al
|
|||||||
n := map_len(m^)
|
n := map_len(m^)
|
||||||
for i := uintptr(0); i < capacity; i += 1 {
|
for i := uintptr(0); i < capacity; i += 1 {
|
||||||
hash := hs[i]
|
hash := hs[i]
|
||||||
if map_hash_is_empty(hash) do continue
|
if map_hash_is_empty(hash) {
|
||||||
if map_hash_is_deleted(hash) do continue
|
continue
|
||||||
|
}
|
||||||
|
if map_hash_is_deleted(hash) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
k := map_cell_index_dynamic(ks, info_ks, i)
|
k := map_cell_index_dynamic(ks, info_ks, i)
|
||||||
v := map_cell_index_dynamic(vs, info_vs, i)
|
v := map_cell_index_dynamic(vs, info_vs, i)
|
||||||
map_insert_hash_dynamic(resized, info, hash, k, v)
|
map_insert_hash_dynamic(resized, info, hash, k, v)
|
||||||
// Only need to do this comparison on each actually added pair, so do not
|
// Only need to do this comparison on each actually added pair, so do not
|
||||||
// fold it into the for loop comparator as a micro-optimization.
|
// fold it into the for loop comparator as a micro-optimization.
|
||||||
n -= 1
|
n -= 1
|
||||||
if n == 0 do break
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_free(rawptr(ks), allocator)
|
mem_free(rawptr(ks), allocator)
|
||||||
@@ -534,6 +548,9 @@ map_grow_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Al
|
|||||||
@(optimization_mode="size")
|
@(optimization_mode="size")
|
||||||
map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uintptr) -> Allocator_Error {
|
map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uintptr) -> Allocator_Error {
|
||||||
allocator := m.allocator
|
allocator := m.allocator
|
||||||
|
if allocator.procedure == nil {
|
||||||
|
allocator = context.allocator
|
||||||
|
}
|
||||||
|
|
||||||
log2_capacity := map_log2_cap(m^)
|
log2_capacity := map_log2_cap(m^)
|
||||||
capacity := uintptr(1) << log2_capacity
|
capacity := uintptr(1) << log2_capacity
|
||||||
@@ -545,8 +562,7 @@ map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, ne
|
|||||||
log2_new_capacity := size_of(uintptr) - intrinsics.count_leading_zeros(new_capacity-1)
|
log2_new_capacity := size_of(uintptr) - intrinsics.count_leading_zeros(new_capacity-1)
|
||||||
|
|
||||||
if m.data == 0 {
|
if m.data == 0 {
|
||||||
n := map_alloc_dynamic(info, MAP_MIN_LOG2_CAPACITY, allocator) or_return
|
m^ = map_alloc_dynamic(info, MAP_MIN_LOG2_CAPACITY, allocator) or_return
|
||||||
m.data = n.data
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,15 +578,21 @@ map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, ne
|
|||||||
n := map_len(m^)
|
n := map_len(m^)
|
||||||
for i := uintptr(0); i < capacity; i += 1 {
|
for i := uintptr(0); i < capacity; i += 1 {
|
||||||
hash := hs[i]
|
hash := hs[i]
|
||||||
if map_hash_is_empty(hash) do continue
|
if map_hash_is_empty(hash) {
|
||||||
if map_hash_is_deleted(hash) do continue
|
continue
|
||||||
|
}
|
||||||
|
if map_hash_is_deleted(hash) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
k := map_cell_index_dynamic(ks, info_ks, i)
|
k := map_cell_index_dynamic(ks, info_ks, i)
|
||||||
v := map_cell_index_dynamic(vs, info_vs, i)
|
v := map_cell_index_dynamic(vs, info_vs, i)
|
||||||
map_insert_hash_dynamic(resized, info, hash, k, v)
|
map_insert_hash_dynamic(resized, info, hash, k, v)
|
||||||
// Only need to do this comparison on each actually added pair, so do not
|
// Only need to do this comparison on each actually added pair, so do not
|
||||||
// fold it into the for loop comparator as a micro-optimization.
|
// fold it into the for loop comparator as a micro-optimization.
|
||||||
n -= 1
|
n -= 1
|
||||||
if n == 0 do break
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_free(rawptr(ks), allocator)
|
mem_free(rawptr(ks), allocator)
|
||||||
@@ -584,12 +606,18 @@ map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, ne
|
|||||||
@(optimization_mode="size")
|
@(optimization_mode="size")
|
||||||
map_shrink_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Allocator_Error {
|
map_shrink_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) -> Allocator_Error {
|
||||||
allocator := m.allocator
|
allocator := m.allocator
|
||||||
|
if allocator.procedure == nil {
|
||||||
|
// TODO(bill): is this correct behaviour?
|
||||||
|
allocator = context.allocator
|
||||||
|
}
|
||||||
|
|
||||||
// Cannot shrink the capacity if the number of items in the map would exceed
|
// Cannot shrink the capacity if the number of items in the map would exceed
|
||||||
// one minus the current log2 capacity's resize threshold. That is the shrunk
|
// one minus the current log2 capacity's resize threshold. That is the shrunk
|
||||||
// map needs to be within the max load factor.
|
// map needs to be within the max load factor.
|
||||||
log2_capacity := map_log2_cap(m^)
|
log2_capacity := map_log2_cap(m^)
|
||||||
if m.len >= map_load_factor(log2_capacity - 1) do return nil
|
if m.len >= map_load_factor(log2_capacity - 1) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
shrinked := map_alloc_dynamic(info, log2_capacity - 1, allocator) or_return
|
shrinked := map_alloc_dynamic(info, log2_capacity - 1, allocator) or_return
|
||||||
|
|
||||||
@@ -603,8 +631,12 @@ map_shrink_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) ->
|
|||||||
n := map_len(m^)
|
n := map_len(m^)
|
||||||
for i := uintptr(0); i < capacity; i += 1 {
|
for i := uintptr(0); i < capacity; i += 1 {
|
||||||
hash := hs[i]
|
hash := hs[i]
|
||||||
if map_hash_is_empty(hash) do continue
|
if map_hash_is_empty(hash) {
|
||||||
if map_hash_is_deleted(hash) do continue
|
continue
|
||||||
|
}
|
||||||
|
if map_hash_is_deleted(hash) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
k := map_cell_index_dynamic(ks, info_ks, i)
|
k := map_cell_index_dynamic(ks, info_ks, i)
|
||||||
v := map_cell_index_dynamic(vs, info_vs, i)
|
v := map_cell_index_dynamic(vs, info_vs, i)
|
||||||
@@ -614,7 +646,9 @@ map_shrink_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) ->
|
|||||||
// Only need to do this comparison on each actually added pair, so do not
|
// Only need to do this comparison on each actually added pair, so do not
|
||||||
// fold it into the for loop comparator as a micro-optimization.
|
// fold it into the for loop comparator as a micro-optimization.
|
||||||
n -= 1
|
n -= 1
|
||||||
if n == 0 do break
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(rawptr(ks), allocator)
|
free(rawptr(ks), allocator)
|
||||||
@@ -632,7 +666,9 @@ map_free :: proc(m: Raw_Map, loc := #caller_location) -> Allocator_Error {
|
|||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
map_lookup_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (index: uintptr, ok: bool) {
|
map_lookup_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> (index: uintptr, ok: bool) {
|
||||||
if map_len(m) == 0 do return 0, false
|
if map_len(m) == 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
h := info.hash(rawptr(k), 0)
|
h := info.hash(rawptr(k), 0)
|
||||||
p := map_desired_position(m, h)
|
p := map_desired_position(m, h)
|
||||||
d := uintptr(0)
|
d := uintptr(0)
|
||||||
@@ -663,9 +699,9 @@ map_insert_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k,
|
|||||||
map_grow_dynamic(m, info) or_return
|
map_grow_dynamic(m, info) or_return
|
||||||
}
|
}
|
||||||
hashed := info.hash(rawptr(k), 0)
|
hashed := info.hash(rawptr(k), 0)
|
||||||
result := map_insert_hash_dynamic(m^, info, hashed, k, v)
|
value = map_insert_hash_dynamic(m^, info, hashed, k, v)
|
||||||
m.len += 1
|
m.len += 1
|
||||||
return result, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as map_insert_dynamic but does not return address to the inserted element.
|
// Same as map_insert_dynamic but does not return address to the inserted element.
|
||||||
@@ -680,9 +716,8 @@ map_add_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k, v:
|
|||||||
}
|
}
|
||||||
|
|
||||||
map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> bool {
|
map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, k: uintptr) -> bool {
|
||||||
when size_of(Map_Hash) == 4 do MASK :: Map_Hash(0x8000_0000)
|
MASK :: 1 << (size_of(Map_Hash)*8 - 1)
|
||||||
when size_of(Map_Hash) == 8 do MASK :: Map_Hash(0x8000_0000_0000_0000)
|
|
||||||
when size_of(Map_Hash) == 16 do MASK :: Map_Hash(0x8000_0000_0000_0000_0000_0000_0000_0000)
|
|
||||||
index := map_lookup_dynamic(m^, info, k) or_return
|
index := map_lookup_dynamic(m^, info, k) or_return
|
||||||
_, _, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
_, _, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
||||||
hs[index] |= MASK
|
hs[index] |= MASK
|
||||||
@@ -691,7 +726,9 @@ map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #n
|
|||||||
}
|
}
|
||||||
|
|
||||||
map_clear_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) {
|
map_clear_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info) {
|
||||||
if m.data == 0 do return
|
if m.data == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
_, _, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
_, _, hs, _, _ := map_kvh_data_dynamic(m^, info)
|
||||||
intrinsics.mem_zero(rawptr(hs), map_cap(m^) * size_of(Map_Hash))
|
intrinsics.mem_zero(rawptr(hs), map_cap(m^) * size_of(Map_Hash))
|
||||||
m.len = 0
|
m.len = 0
|
||||||
@@ -705,16 +742,13 @@ __dynamic_map_get :: proc "contextless" (m: rawptr, #no_alias info: ^Map_Info, k
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = index
|
vs := map_kvh_data_values_dynamic(rm, info)
|
||||||
// TODO(bill)
|
return rawptr(map_cell_index_dynamic(vs, &info.vs, index))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr {
|
__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr {
|
||||||
// value, _ := map_insert_dynamic(m, info, uintptr(key), uintptr(value))
|
value, _ := map_insert_dynamic(m, info, uintptr(key), uintptr(value))
|
||||||
// return rawptr(value)
|
return rawptr(value)
|
||||||
// TODO(bill)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_reserve :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uint, loc := #caller_location) {
|
__dynamic_map_reserve :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uint, loc := #caller_location) {
|
||||||
|
|||||||
Reference in New Issue
Block a user