aboutsummaryrefslogtreecommitdiff
path: root/core/slice/map.odin
blob: b9ec795a578d20b2232f0dc8801af8456696b969 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package slice

import "intrinsics"
import "core:runtime"
import "core:mem"

_ :: intrinsics;
_ :: runtime;
_ :: mem;

map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K) {
	keys = make(type_of(keys), len(m), allocator);
	i := 0;
	for key in m {
		keys[i] = key;
		i += 1;
	}
	return;
}
map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (values: []V) {
	values = make(type_of(values), len(m), allocator);
	i := 0;
	for _, value in m {
		values[i] = value;
		i += 1;
	}
	return;
}

Map_Entry :: struct(Key, Value: typeid) {
	key:   Key,
	value: Value,
}

Map_Entry_Info :: struct(Key, Value: typeid) {
	hash:  uintptr,
	key:   Key,
	value: Value,
}


map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V)) {
	entries = make(type_of(entries), len(m), allocator);
	i := 0;
	for key, value in m {
		entries[i].key   = key;
		entries[i].value = value;
		i += 1;
	}
	return;
}

map_entry_infos :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V)) #no_bounds_check {
	m := m;
	rm := (^mem.Raw_Map)(&m);

	info := runtime.type_info_base(type_info_of(M)).variant.(runtime.Type_Info_Map);
	gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct);
	ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array);
	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);

	data := uintptr(rm.entries.data);
	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;
}