map.odin 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package slice
  2. import "core:intrinsics"
  3. import "core:runtime"
  4. _ :: intrinsics
  5. _ :: runtime
  6. map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K) {
  7. keys = make(type_of(keys), len(m), allocator)
  8. i := 0
  9. for key in m {
  10. keys[i] = key
  11. i += 1
  12. }
  13. return
  14. }
  15. map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (values: []V) {
  16. values = make(type_of(values), len(m), allocator)
  17. i := 0
  18. for _, value in m {
  19. values[i] = value
  20. i += 1
  21. }
  22. return
  23. }
  24. Map_Entry :: struct($Key, $Value: typeid) {
  25. key: Key,
  26. value: Value,
  27. }
  28. Map_Entry_Info :: struct($Key, $Value: typeid) {
  29. hash: uintptr,
  30. key: Key,
  31. value: Value,
  32. }
  33. map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V)) {
  34. entries = make(type_of(entries), len(m), allocator)
  35. i := 0
  36. for key, value in m {
  37. entries[i].key = key
  38. entries[i].value = value
  39. i += 1
  40. }
  41. return
  42. }
  43. map_entry_infos :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V)) #no_bounds_check {
  44. m := m
  45. rm := (^runtime.Raw_Map)(&m)
  46. info := runtime.type_info_base(type_info_of(M)).variant.(runtime.Type_Info_Map)
  47. gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct)
  48. ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array)
  49. entry_type := ed.elem.variant.(runtime.Type_Info_Struct)
  50. key_offset := entry_type.offsets[2]
  51. value_offset := entry_type.offsets[3]
  52. entry_size := uintptr(ed.elem_size)
  53. entries = make(type_of(entries), rm.entries.len)
  54. data := uintptr(rm.entries.data)
  55. for i in 0..<rm.entries.len {
  56. header := (^runtime.Map_Entry_Header)(data)
  57. hash := header.hash
  58. key := (^K)(data + key_offset)^
  59. value := (^V)(data + value_offset)^
  60. entries[i] = {hash, key, value}
  61. data += entry_size
  62. }
  63. return
  64. }