v2 / vlib / builtin / sorted_map.v
441 lines · 412 sloc · 10.48 KB · 3d79993ef4fc8e0dd7847be3d48f6fd14965e7ab
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4
5module builtin
6
7// B-trees are balanced search trees with all leaves at
8// the same level. B-trees are generally faster than
9// binary search trees due to the better locality of
10// reference, since multiple keys are stored in one node.
11
12// The number for `degree` has been picked through vigor-
13// ous benchmarking but can be changed to any number > 1.
14// `degree` determines the maximum length of each node.
15// TODO: the @[markused] tag here is needed as a workaround for
16// compilation with `-cc clang -usecache`; added in https://github.com/vlang/v/pull/25034
17
18@[markused]
19const degree = 6
20const mid_index = degree - 1
21const max_len = 2 * degree - 1
22const children_bytes = sizeof(voidptr) * (max_len + 1)
23
24pub struct SortedMap {
25 value_bytes int
26mut:
27 root &mapnode
28pub mut:
29 len int
30}
31
32struct mapnode {
33mut:
34 children &voidptr
35 len int
36 keys [11]string // TODO: Should use `max_len`
37 values [11]voidptr // TODO: Should use `max_len`
38}
39
40fn new_sorted_map(n int, value_bytes int) SortedMap { // TODO: Remove `n`
41 return SortedMap{
42 value_bytes: value_bytes
43 root: new_node()
44 len: 0
45 }
46}
47
48fn new_sorted_map_init(n int, value_bytes int, keys &string, values voidptr) SortedMap {
49 mut out := new_sorted_map(n, value_bytes)
50 for i in 0 .. n {
51 unsafe {
52 out.set(keys[i], &u8(values) + i * value_bytes)
53 }
54 }
55 return out
56}
57
58// The tree is initialized with an empty node as root to
59// avoid having to check whether the root is null for
60// each insertion.
61fn new_node() &mapnode {
62 return &mapnode{
63 children: unsafe { nil }
64 len: 0
65 }
66}
67
68// This implementation does proactive insertion, meaning
69// that splits are done top-down and not bottom-up.
70fn (mut m SortedMap) set(key string, value voidptr) {
71 mut node := m.root
72 mut child_index := 0
73 mut parent := &mapnode(unsafe { nil })
74 for {
75 if node.len == max_len {
76 if parent == unsafe { nil } {
77 parent = new_node()
78 m.root = parent
79 }
80 parent.split_child(child_index, mut node)
81 if key == parent.keys[child_index] {
82 unsafe {
83 vmemcpy(parent.values[child_index], value, m.value_bytes)
84 }
85 return
86 }
87 if key < parent.keys[child_index] {
88 node = unsafe { &mapnode(parent.children[child_index]) }
89 } else {
90 node = unsafe { &mapnode(parent.children[child_index + 1]) }
91 }
92 }
93 mut i := 0
94 for i < node.len && key > node.keys[i] {
95 i++
96 }
97 if i != node.len && key == node.keys[i] {
98 unsafe {
99 vmemcpy(node.values[i], value, m.value_bytes)
100 }
101 return
102 }
103 if node.children == unsafe { nil } {
104 mut j := node.len - 1
105 for j >= 0 && key < node.keys[j] {
106 node.keys[j + 1] = node.keys[j]
107 node.values[j + 1] = node.values[j]
108 j--
109 }
110 node.keys[j + 1] = key
111 unsafe {
112 node.values[j + 1] = malloc(m.value_bytes)
113 vmemcpy(node.values[j + 1], value, m.value_bytes)
114 }
115 node.len++
116 m.len++
117 return
118 }
119 parent = node
120 child_index = i
121 node = unsafe { &mapnode(node.children[child_index]) }
122 }
123}
124
125fn (mut n mapnode) split_child(child_index int, mut y mapnode) {
126 mut z := new_node()
127 z.len = mid_index
128 y.len = mid_index
129 for j := mid_index - 1; j >= 0; j-- {
130 z.keys[j] = y.keys[j + degree]
131 z.values[j] = y.values[j + degree]
132 }
133 if y.children != unsafe { nil } {
134 z.children = unsafe { &voidptr(malloc(int(children_bytes))) }
135 for jj := degree - 1; jj >= 0; jj-- {
136 unsafe {
137 z.children[jj] = y.children[jj + degree]
138 }
139 }
140 }
141 unsafe {
142 if n.children == nil {
143 n.children = &voidptr(malloc(int(children_bytes)))
144 }
145 n.children[n.len + 1] = n.children[n.len]
146 }
147 for j := n.len; j > child_index; j-- {
148 n.keys[j] = n.keys[j - 1]
149 n.values[j] = n.values[j - 1]
150 unsafe {
151 n.children[j] = n.children[j - 1]
152 }
153 }
154 n.keys[child_index] = y.keys[mid_index]
155 n.values[child_index] = y.values[mid_index]
156 unsafe {
157 n.children[child_index] = voidptr(y)
158 n.children[child_index + 1] = voidptr(z)
159 }
160 n.len++
161}
162
163@[direct_array_access]
164fn (m SortedMap) get(key string, out voidptr) bool {
165 mut node := m.root
166 for {
167 mut i := node.len - 1
168 for i >= 0 && key < node.keys[i] {
169 i--
170 }
171 if i != -1 && key == node.keys[i] {
172 unsafe {
173 vmemcpy(out, node.values[i], m.value_bytes)
174 }
175 return true
176 }
177 if node.children == unsafe { nil } {
178 break
179 }
180 node = unsafe { &mapnode(node.children[i + 1]) }
181 }
182 return false
183}
184
185fn (m SortedMap) exists(key string) bool {
186 if m.root == unsafe { nil } { // TODO: find out why root can be nil
187 return false
188 }
189 mut node := m.root
190 for {
191 mut i := node.len - 1
192 for i >= 0 && key < node.keys[i] {
193 i--
194 }
195 if i != -1 && key == node.keys[i] {
196 return true
197 }
198 if node.children == unsafe { nil } {
199 break
200 }
201 node = unsafe { &mapnode(node.children[i + 1]) }
202 }
203 return false
204}
205
206fn (n &mapnode) find_key(k string) int {
207 mut idx := 0
208 for idx < n.len && n.keys[idx] < k {
209 idx++
210 }
211 return idx
212}
213
214fn (mut n mapnode) remove_key(k string) bool {
215 idx := n.find_key(k)
216 if idx < n.len && n.keys[idx] == k {
217 if n.children == unsafe { nil } {
218 n.remove_from_leaf(idx)
219 } else {
220 n.remove_from_non_leaf(idx)
221 }
222 return true
223 } else {
224 if n.children == unsafe { nil } {
225 return false
226 }
227 flag := if idx == n.len { true } else { false }
228 if unsafe { &mapnode(n.children[idx]) }.len < degree {
229 n.fill(idx)
230 }
231
232 mut node := &mapnode(unsafe { nil })
233 if flag && idx > n.len {
234 node = unsafe { &mapnode(n.children[idx - 1]) }
235 } else {
236 node = unsafe { &mapnode(n.children[idx]) }
237 }
238 return node.remove_key(k)
239 }
240}
241
242fn (mut n mapnode) remove_from_leaf(idx int) {
243 for i := idx + 1; i < n.len; i++ {
244 n.keys[i - 1] = n.keys[i]
245 n.values[i - 1] = n.values[i]
246 }
247 n.len--
248}
249
250fn (mut n mapnode) remove_from_non_leaf(idx int) {
251 k := n.keys[idx]
252 if unsafe { &mapnode(n.children[idx]) }.len >= degree {
253 mut current := unsafe { &mapnode(n.children[idx]) }
254 for current.children != unsafe { nil } {
255 current = unsafe { &mapnode(current.children[current.len]) }
256 }
257 predecessor := current.keys[current.len - 1]
258 n.keys[idx] = predecessor
259 n.values[idx] = current.values[current.len - 1]
260 mut node := unsafe { &mapnode(n.children[idx]) }
261 node.remove_key(predecessor)
262 } else if unsafe { &mapnode(n.children[idx + 1]) }.len >= degree {
263 mut current := unsafe { &mapnode(n.children[idx + 1]) }
264 for current.children != unsafe { nil } {
265 current = unsafe { &mapnode(current.children[0]) }
266 }
267 successor := current.keys[0]
268 n.keys[idx] = successor
269 n.values[idx] = current.values[0]
270 mut node := unsafe { &mapnode(n.children[idx + 1]) }
271 node.remove_key(successor)
272 } else {
273 n.merge(idx)
274 mut node := unsafe { &mapnode(n.children[idx]) }
275 node.remove_key(k)
276 }
277}
278
279fn (mut n mapnode) fill(idx int) {
280 if idx != 0 && unsafe { &mapnode(n.children[idx - 1]) }.len >= degree {
281 n.borrow_from_prev(idx)
282 } else if idx != n.len && unsafe { &mapnode(n.children[idx + 1]) }.len >= degree {
283 n.borrow_from_next(idx)
284 } else if idx != n.len {
285 n.merge(idx)
286 } else {
287 n.merge(idx - 1)
288 }
289}
290
291fn (mut n mapnode) borrow_from_prev(idx int) {
292 mut child := unsafe { &mapnode(n.children[idx]) }
293 mut sibling := unsafe { &mapnode(n.children[idx - 1]) }
294 for i := child.len - 1; i >= 0; i-- {
295 child.keys[i + 1] = child.keys[i]
296 child.values[i + 1] = child.values[i]
297 }
298 if child.children != unsafe { nil } {
299 for i := child.len; i >= 0; i-- {
300 unsafe {
301 child.children[i + 1] = child.children[i]
302 }
303 }
304 }
305 child.keys[0] = n.keys[idx - 1]
306 child.values[0] = n.values[idx - 1]
307 if child.children != unsafe { nil } {
308 unsafe {
309 child.children[0] = sibling.children[sibling.len]
310 }
311 }
312 n.keys[idx - 1] = sibling.keys[sibling.len - 1]
313 n.values[idx - 1] = sibling.values[sibling.len - 1]
314 child.len++
315 sibling.len--
316}
317
318fn (mut n mapnode) borrow_from_next(idx int) {
319 mut child := unsafe { &mapnode(n.children[idx]) }
320 mut sibling := unsafe { &mapnode(n.children[idx + 1]) }
321 child.keys[child.len] = n.keys[idx]
322 child.values[child.len] = n.values[idx]
323 if child.children != unsafe { nil } {
324 unsafe {
325 child.children[child.len + 1] = sibling.children[0]
326 }
327 }
328 n.keys[idx] = sibling.keys[0]
329 n.values[idx] = sibling.values[0]
330 for i := 1; i < sibling.len; i++ {
331 sibling.keys[i - 1] = sibling.keys[i]
332 sibling.values[i - 1] = sibling.values[i]
333 }
334 if sibling.children != unsafe { nil } {
335 for i := 1; i <= sibling.len; i++ {
336 unsafe {
337 sibling.children[i - 1] = sibling.children[i]
338 }
339 }
340 }
341 child.len++
342 sibling.len--
343}
344
345fn (mut n mapnode) merge(idx int) {
346 mut child := unsafe { &mapnode(n.children[idx]) }
347 sibling := unsafe { &mapnode(n.children[idx + 1]) }
348 child.keys[mid_index] = n.keys[idx]
349 child.values[mid_index] = n.values[idx]
350 for i in 0 .. sibling.len {
351 child.keys[i + degree] = sibling.keys[i]
352 child.values[i + degree] = sibling.values[i]
353 }
354 if child.children != unsafe { nil } {
355 for i := 0; i <= sibling.len; i++ {
356 unsafe {
357 child.children[i + degree] = sibling.children[i]
358 }
359 }
360 }
361 for i := idx + 1; i < n.len; i++ {
362 n.keys[i - 1] = n.keys[i]
363 n.values[i - 1] = n.values[i]
364 }
365 for i := idx + 2; i <= n.len; i++ {
366 unsafe {
367 n.children[i - 1] = n.children[i]
368 }
369 }
370 child.len += sibling.len + 1
371 n.len--
372 // free(sibling)
373}
374
375pub fn (mut m SortedMap) delete(key string) {
376 if m.root.len == 0 {
377 return
378 }
379
380 removed := m.root.remove_key(key)
381 if removed {
382 m.len--
383 }
384
385 if m.root.len == 0 {
386 // tmp := t.root
387 if m.root.children == unsafe { nil } {
388 return
389 } else {
390 m.root = unsafe { &mapnode(m.root.children[0]) }
391 }
392 // free(tmp)
393 }
394}
395
396// Insert all keys of the subtree into array `keys`
397// starting at `at`. Keys are inserted in order.
398fn (n &mapnode) subkeys(mut keys []string, at int) int {
399 mut position := at
400 if n.children != unsafe { nil } {
401 // Traverse children and insert
402 // keys inbetween children
403 for i in 0 .. n.len {
404 child := unsafe { &mapnode(n.children[i]) }
405 position += child.subkeys(mut keys, position)
406 keys[position] = n.keys[i]
407 position++
408 }
409 // Insert the keys of the last child
410 child := unsafe { &mapnode(n.children[n.len]) }
411 position += child.subkeys(mut keys, position)
412 } else {
413 // If leaf, insert keys
414 for i in 0 .. n.len {
415 keys[position + i] = n.keys[i]
416 }
417 position += n.len
418 }
419 // Return # of added keys
420 return position - at
421}
422
423pub fn (m &SortedMap) keys() []string {
424 mut keys := []string{len: m.len}
425 if m.root == unsafe { nil } || m.root.len == 0 {
426 return keys
427 }
428 m.root.subkeys(mut keys, 0)
429 return keys
430}
431
432fn (mut n mapnode) free() {
433 // TODO
434}
435
436pub fn (mut m SortedMap) free() {
437 if m.root == unsafe { nil } {
438 return
439 }
440 m.root.free()
441}
442