aboutsummaryrefslogtreecommitdiff
path: root/core/reflect/iterator.odin
blob: 2e143284aca25d67306bdd8637b344f848a3a0d5 (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
package reflect

import "core:runtime"

@(require_results)
iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) {
	if val == nil || it == nil {
		return
	}

	ti := type_info_base(type_info_of(val.id))
	#partial switch info in ti.variant {
	case Type_Info_Pointer:
		if ptr := (^rawptr)(val.data)^; ptr != nil {
			return iterate_array(any{ptr, info.elem.id}, it)
		}
	case Type_Info_Array:
		if it^ < info.count {
			elem.data = rawptr(uintptr(val.data) + uintptr(it^ * info.elem_size))
			elem.id = info.elem.id
			ok = true
			it^ += 1
		}
	case Type_Info_Slice:
		array := (^runtime.Raw_Slice)(val.data)
		if it^ < array.len {
			elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size))
			elem.id = info.elem.id
			ok = true
			it^ += 1
		}
	case Type_Info_Dynamic_Array:
		array := (^runtime.Raw_Dynamic_Array)(val.data)
		if it^ < array.len {
			elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size))
			elem.id = info.elem.id
			ok = true
			it^ += 1
		}
	}

	return
}

@(require_results)
iterate_map :: proc(val: any, it: ^int) -> (key, value: any, ok: bool) {
	if val == nil || it == nil {
		return
	}
	ti := type_info_base(type_info_of(val.id))
	#partial switch info in ti.variant {
	case Type_Info_Pointer:
		if ptr := (^rawptr)(val.data)^; ptr != nil {
			return iterate_map(any{ptr, info.elem.id}, it)
		}
	case Type_Info_Map:
		if info.map_info == nil {
			break
		}
		rm := (^runtime.Raw_Map)(val.data)
		ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(rm^, info.map_info)
		for /**/ ; it^ < int(runtime.map_cap(rm^)); it^ += 1 {
			if hash := hs[it^]; runtime.map_hash_is_valid(hash) {
				key_ptr   := runtime.map_cell_index_dynamic(ks, info.map_info.ks, uintptr(it^))
				value_ptr := runtime.map_cell_index_dynamic(vs, info.map_info.vs, uintptr(it^))

				key.data   = rawptr(key_ptr)
				value.data = rawptr(value_ptr)
				key.id     = info.key.id
				value.id   = info.value.id
				ok = true
				break
			}

		}
	}
	return
}