mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Merge pull request #4533 from laytan/map-entry
add `map_entry` procedure
This commit is contained in:
@@ -936,6 +936,32 @@ map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves a pointer to the key and value for a possibly just inserted entry into the map.
|
||||||
|
|
||||||
|
If the `key` was not in the map `m`, an entry is inserted with the zero value and `just_inserted` will be `true`.
|
||||||
|
Otherwise the existing entry is left untouched and pointers to its key and value are returned.
|
||||||
|
|
||||||
|
If the map has to grow in order to insert the entry and the allocation fails, `err` is set and returned.
|
||||||
|
|
||||||
|
If `err` is `nil`, `key_ptr` and `value_ptr` are valid pointers and will not be `nil`.
|
||||||
|
|
||||||
|
WARN: User modification of the key pointed at by `key_ptr` should only be done if the new key is equal to (in hash) the old key.
|
||||||
|
If that is not the case you will corrupt the map.
|
||||||
|
*/
|
||||||
|
@(builtin, require_results)
|
||||||
|
map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr: ^K, value_ptr: ^V, just_inserted: bool, err: Allocator_Error) {
|
||||||
|
key := key
|
||||||
|
zero: V
|
||||||
|
|
||||||
|
_key_ptr, _value_ptr: rawptr
|
||||||
|
_key_ptr, _value_ptr, just_inserted, err = __dynamic_map_entry((^Raw_Map)(m), map_info(T), &key, &zero, loc)
|
||||||
|
|
||||||
|
key_ptr = (^K)(_key_ptr)
|
||||||
|
value_ptr = (^V)(_value_ptr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||||
|
|||||||
@@ -941,6 +941,29 @@ __dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
|
|||||||
return nil, rawptr(result)
|
return nil, rawptr(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key: rawptr, zero: rawptr, loc := #caller_location) -> (key_ptr: rawptr, value_ptr: rawptr, just_inserted: bool, err: Allocator_Error) {
|
||||||
|
hash := info.key_hasher(key, map_seed(m^))
|
||||||
|
|
||||||
|
if key_ptr, value_ptr = __dynamic_map_get_key_and_value(m, info, hash, key); value_ptr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
has_grown: bool
|
||||||
|
if err, has_grown = __dynamic_map_check_grow(m, info, loc); err != nil {
|
||||||
|
return
|
||||||
|
} else if has_grown {
|
||||||
|
hash = info.key_hasher(key, map_seed(m^))
|
||||||
|
}
|
||||||
|
|
||||||
|
value_ptr = rawptr(map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(zero)))
|
||||||
|
assert(value_ptr != nil)
|
||||||
|
key_ptr = rawptr(map_cell_index_dynamic(map_data(m^), info.ks, map_desired_position(m^, hash)))
|
||||||
|
|
||||||
|
m.len += 1
|
||||||
|
just_inserted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// IMPORTANT: USED WITHIN THE COMPILER
|
// IMPORTANT: USED WITHIN THE COMPILER
|
||||||
@(private)
|
@(private)
|
||||||
|
|||||||
Reference in New Issue
Block a user