aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-08-29 11:45:11 +0100
committergingerBill <bill@gingerbill.org>2021-08-29 11:45:11 +0100
commita5c31bbee06cdd3f76ecf1b2abb24c4950735e4a (patch)
treee8713a7e3d68c4d210672287e24cedef92d2524c
parentb88e9452685f9e2c0d9dd1ba0609f5158252c45b (diff)
Add `map_insert` which returns the pointer to inserted value
-rw-r--r--core/mem/raw.odin11
-rw-r--r--core/runtime/core_builtin.odin9
-rw-r--r--core/runtime/dynamic_map_internal.odin25
3 files changed, 35 insertions, 10 deletions
diff --git a/core/mem/raw.odin b/core/mem/raw.odin
index c4c5182e6..99712e9e5 100644
--- a/core/mem/raw.odin
+++ b/core/mem/raw.odin
@@ -58,3 +58,14 @@ raw_dynamic_array_data :: proc(a: $T/[dynamic]$E) -> ^E {
raw_data :: proc{raw_array_data, raw_string_data, raw_slice_data, raw_dynamic_array_data};
+Poly_Raw_Map_Entry :: struct($Key, $Value: typeid) {
+ hash: uintptr,
+ next: int,
+ key: Key,
+ value: Value,
+}
+
+Poly_Raw_Map :: struct($Key, $Value: typeid) {
+ hashes: []int,
+ entries: [dynamic]Poly_Raw_Map_Entry(Key, Value),
+} \ No newline at end of file
diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin
index 9a90800c4..88e769056 100644
--- a/core/runtime/core_builtin.odin
+++ b/core/runtime/core_builtin.odin
@@ -523,6 +523,15 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
return true;
}
+@builtin
+map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) {
+ key, value := key, value;
+ h := __get_map_header(m);
+ hash := __get_map_hash(&key);
+
+ data := uintptr(__dynamic_map_set(h, hash, &value, loc));
+ return (^V)(data + h.value_offset);
+}
@builtin
diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin
index 8bb8975b6..6e54ba441 100644
--- a/core/runtime/dynamic_map_internal.odin
+++ b/core/runtime/dynamic_map_internal.odin
@@ -193,27 +193,28 @@ __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller
}
__dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check {
- new_header: Map_Header = header;
- nm := Raw_Map{};
- nm.entries.allocator = m.entries.allocator;
- nm.hashes = m.hashes;
- new_header.m = &nm;
-
c := context;
if m.entries.allocator.procedure != nil {
c.allocator = m.entries.allocator;
}
context = c;
+
+ nm := Raw_Map{};
+ nm.entries.allocator = m.entries.allocator;
+ nm.hashes = m.hashes;
+
+ new_header: Map_Header = header;
+ new_header.m = &nm;
new_count := new_count;
new_count = max(new_count, 2*m.entries.len);
- __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
__slice_resize(&nm.hashes, new_count, m.entries.allocator, loc);
for i in 0 ..< new_count {
nm.hashes[i] = -1;
}
+ __dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
for i in 0 ..< m.entries.len {
if len(nm.hashes) == 0 {
__dynamic_map_grow(new_header, loc);
@@ -253,7 +254,7 @@ __dynamic_map_get :: proc(h: Map_Header, hash: Map_Hash) -> rawptr {
return nil;
}
-__dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) #no_bounds_check {
+__dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check {
index: int;
assert(value != nil);
@@ -277,7 +278,7 @@ __dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #
e := __dynamic_map_get_entry(h, index);
e.hash = hash.hash;
-
+
key := rawptr(uintptr(e) + h.key_offset);
mem_copy(key, hash.key_ptr, h.key_size);
@@ -286,7 +287,11 @@ __dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #
if __dynamic_map_full(h) {
__dynamic_map_grow(h, loc);
+ index = __dynamic_map_find(h, hash).entry_index;
+ assert(index >= 0);
}
+
+ return __dynamic_map_get_entry(h, index);
}
@@ -297,7 +302,7 @@ __dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
}
__dynamic_map_full :: #force_inline proc "contextless" (using h: Map_Header) -> bool {
- return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
+ return int(0.75 * f64(len(m.hashes))) <= m.entries.len;
}