v2 / vlib / builtin / map.c.v
137 lines · 127 sloc · 2.91 KB · a7912e4258c4c5888503bda40e924a89ac7c21c3
Raw
1module builtin
2
3fn C.wyhash(&u8, u64, u64, &u64) u64
4
5fn C.wyhash64(u64, u64) u64
6
7// fast_string_eq is intended to be fast when
8// the strings are very likely to be equal
9// TODO: add branch prediction hints
10@[inline]
11fn fast_string_eq(a string, b string) bool {
12 if a.len != b.len {
13 return false
14 }
15 unsafe {
16 return C.memcmp(a.str, b.str, b.len) == 0
17 }
18}
19
20fn map_hash_string(pkey voidptr) u64 {
21 key := *unsafe { &string(pkey) }
22 // XTODO remove voidptr cast once virtual C.consts can be declared
23 return C.wyhash(key.str, u64(key.len), 0, &u64(voidptr(C._wyp)))
24}
25
26fn map_hash_int_1(pkey voidptr) u64 {
27 return C.wyhash64(*unsafe { &u8(pkey) }, 0)
28}
29
30fn map_hash_int_2(pkey voidptr) u64 {
31 return C.wyhash64(*unsafe { &u16(pkey) }, 0)
32}
33
34fn map_hash_int_4(pkey voidptr) u64 {
35 return C.wyhash64(*unsafe { &u32(pkey) }, 0)
36}
37
38fn map_hash_int_8(pkey voidptr) u64 {
39 return C.wyhash64(*unsafe { &u64(pkey) }, 0)
40}
41
42fn map_enum_fn(kind int, esize int) voidptr {
43 if kind !in [1, 2, 3] {
44 panic('map_enum_fn: invalid kind')
45 }
46 if esize > 8 || esize < 0 {
47 panic('map_enum_fn: invalid esize')
48 }
49 if kind == 1 {
50 if esize > 4 {
51 return voidptr(map_hash_int_8)
52 }
53 if esize > 2 {
54 return voidptr(map_hash_int_4)
55 }
56 if esize > 1 {
57 return voidptr(map_hash_int_2)
58 }
59 if esize > 0 {
60 return voidptr(map_hash_int_1)
61 }
62 }
63 if kind == 2 {
64 if esize > 4 {
65 return voidptr(map_eq_int_8)
66 }
67 if esize > 2 {
68 return voidptr(map_eq_int_4)
69 }
70 if esize > 1 {
71 return voidptr(map_eq_int_2)
72 }
73 if esize > 0 {
74 return voidptr(map_eq_int_1)
75 }
76 }
77 if kind == 3 {
78 if esize > 4 {
79 return voidptr(map_clone_int_8)
80 }
81 if esize > 2 {
82 return voidptr(map_clone_int_4)
83 }
84 if esize > 1 {
85 return voidptr(map_clone_int_2)
86 }
87 if esize > 0 {
88 return voidptr(map_clone_int_1)
89 }
90 }
91 return unsafe { nil }
92}
93
94// Move all zeros to the end of the array and resize array
95fn (mut d DenseArray) zeros_to_end() {
96 // TODO: alloca?
97 mut tmp_value := unsafe { malloc(d.value_bytes) }
98 mut tmp_key := unsafe { malloc(d.key_bytes) }
99 mut count := 0
100 for i in 0 .. d.len {
101 if d.has_index(i) {
102 // swap (TODO: optimize)
103 unsafe {
104 if count != i {
105 // Swap keys
106 C.memcpy(tmp_key, d.key(count), d.key_bytes)
107 C.memcpy(d.key(count), d.key(i), d.key_bytes)
108 C.memcpy(d.key(i), tmp_key, d.key_bytes)
109 // Swap values
110 C.memcpy(tmp_value, d.value(count), d.value_bytes)
111 C.memcpy(d.value(count), d.value(i), d.value_bytes)
112 C.memcpy(d.value(i), tmp_value, d.value_bytes)
113 }
114 }
115 count++
116 }
117 }
118 unsafe {
119 free(tmp_value)
120 free(tmp_key)
121 d.deletes = 0
122 // TODO: reallocate instead as more deletes are likely
123 free(d.all_deleted)
124 d.all_deleted = nil
125 }
126 d.len = count
127 old_cap := d.cap
128 if count < 8 {
129 d.cap = 8
130 } else {
131 d.cap = count
132 }
133 unsafe {
134 d.values = realloc_data(d.values, d.value_bytes * old_cap, d.value_bytes * d.cap)
135 d.keys = realloc_data(d.keys, d.key_bytes * old_cap, d.key_bytes * d.cap)
136 }
137}
138