-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathart.go
2872 lines (2306 loc) · 69.9 KB
/
art.go
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// https://github.com/plar/go-adaptive-radix-tree
//
// - 基本概念与常量定义
// - 接口设计(Node、Tree、Iterator)
// - 核心结构:nodeRef、leaf、nodeX(node4、node16、node48、node256)
// - 树的增删查遍历逻辑
// - 辅助函数与调试工具
//
// 整个自适应基数树(ART)的实现要点:
//
// - nodeRef + kind:用一个统一的 nodeRef 封装各种节点类型,配合 kind 来做类型判断、强转,可以显著减少到处做类型断言的复杂度。
// - leaf:真正存储 key-value 的地方;prefix 存不下时就会分裂为内部节点。
// - 内部节点 node4/16/48/256:通过不同大小的分支存储方式,加速增删查效率并节省内存。
// - Grow/Shrink:在插入/删除时动态调整节点类型,使得节点分支数量和节点容量“相匹配”,提升性能。
// - 前缀 prefix:存储在内部节点中,用来优化搜索时的比较性能(一次比较多个字符)。
// - version:用来检测迭代器遍历过程中的并发修改。
package main
import (
"bytes"
"errors"
"fmt"
"strings"
"unsafe"
)
func main() {
DumpTree()
SimpleTree()
}
func DumpTree() {
tree := NewTree()
terms := []string{"A", "a", "aa"}
for _, term := range terms {
tree.Insert(Key(term), term)
}
fmt.Println(tree)
}
func SimpleTree() {
tree := NewTree()
tree.Insert(Key("Hi, I'm Key"), "Nice to meet you, I'm Value")
value, found := tree.Search(Key("Hi, I'm Key"))
if found {
fmt.Printf("Search value=%v\n", value)
}
tree.ForEach(func(node Node) bool {
fmt.Printf("Callback value=%v\n", node.Value())
return true
})
for it := tree.Iterator(); it.HasNext(); {
value, _ := it.Next()
fmt.Printf("Iterator value=%v\n", value.Value())
}
}
// #region api
// Key represents the type used for keys in the Adaptive Radix Tree.
// It can consist of any byte sequence, including Unicode characters and null bytes.
type Key []byte
// Value is an interface representing the value type stored in the tree.
// Any type of data can be stored as a Value.
type Value any
// Node types.
const (
Leaf Kind = 0
Node4 Kind = 1
Node16 Kind = 2
Node48 Kind = 3
Node256 Kind = 4
)
// Traverse Options.
const (
// Iterate only over leaf nodes.
TraverseLeaf = 1
// Iterate only over non-leaf nodes.
TraverseNode = 2
// Iterate over all nodes in the tree.
TraverseAll = TraverseLeaf | TraverseNode
// Iterate in reverse order.
TraverseReverse = 4
)
// These errors can be returned when iteration over the tree.
var (
ErrConcurrentModification = errors.New("concurrent modification has been detected")
ErrNoMoreNodes = errors.New("there are no more nodes in the tree")
)
// Kind is a node type.
type Kind int
// String returns string representation of the Kind value.
func (k Kind) String() string {
return []string{"Leaf", "Node4", "Node16", "Node48", "Node256"}[k]
}
// Callback defines the function type used during tree traversal.
// It is invoked for each node visited in the traversal.
// If the callback function returns false, the iteration is terminated early.
type Callback func(node Node) (cont bool)
// Node represents a node within the Adaptive Radix Tree.
type Node interface {
// Kind returns the type of the node, distinguishing between leaf and internal nodes.
Kind() Kind
// Key returns the key associated with a leaf node.
// This method should only be called on leaf nodes.
// Calling this on a non-leaf node will return nil.
Key() Key
// Value returns the value stored in a leaf node.
// This method should only be called on leaf nodes.
// Calling this on a non-leaf node will return nil.
Value() Value
}
// Iterator provides a mechanism to traverse nodes in key order within the tree.
type Iterator interface {
// HasNext returns true if there are more nodes to visit during the iteration.
// Use this method to check for remaining nodes before calling Next.
HasNext() bool
// Next returns the next node in the iteration and advances the iterator's position.
// !If the iteration has no more nodes, it returns ErrNoMoreNodes error.
// Ensure you call HasNext before invoking Next to avoid errors.
// !If the tree has been structurally modified since the iterator was created,
// it returns an ErrConcurrentModification error.
Next() (Node, error)
}
// Tree is an Adaptive Radix Tree interface.
type Tree interface {
// Insert adds a new key-value pair into the tree.
// If the key already exists in the tree, it updates its value and returns the old value along with true.
// If the key is new, it returns nil and false.
Insert(key Key, value Value) (oldValue Value, updated bool)
// Delete removes the specified key and its associated value from the tree.
// If the key is found and deleted, it returns the removed value and true.
// If the key does not exist, it returns nil and false.
Delete(key Key) (value Value, deleted bool)
// Search retrieves the value associated with the specified key in the tree.
// If the key exists, it returns the value and true.
// If the key does not exist, it returns nil and false.
Search(key Key) (value Value, found bool)
// ForEach iterates over all the nodes in the tree, invoking a provided callback function for each node.
// By default, it processes leaf nodes in ascending order.
// The iteration can be customized using options:
// - Pass TraverseReverse to iterate over nodes in descending order.
// The iteration stops if the callback function returns false, allowing for early termination.
ForEach(callback Callback, options ...int)
// ForEachPrefix iterates over all leaf nodes whose keys start with the specified keyPrefix,
// invoking a provided callback function for each matching node.
// By default, the iteration processes nodes in ascending order.
// Use the TraverseReverse option to iterate over nodes in descending order.
// Iteration stops if the callback function returns false, allowing for early termination.
ForEachPrefix(keyPrefix Key, callback Callback, options ...int)
// Iterator returns an iterator for traversing leaf nodes in the tree.
// By default, the iteration occurs in ascending order.
// To traverse nodes in reverse (descending) order, pass the TraverseReverse option.
Iterator(options ...int) Iterator
// Minimum retrieves the leaf node with the smallest key in the tree.
// If such a leaf is found, it returns its value and true.
// If the tree is empty, it returns nil and false.
Minimum() (Value, bool)
// Maximum retrieves the leaf node with the largest key in the tree.
// If such a leaf is found, it returns its value and true.
// If the tree is empty, it returns nil and false.
Maximum() (Value, bool)
// Size returns the number of key-value pairs stored in the tree.
Size() int
}
// NewTree creates a new adaptive radix tree.
func NewTree() Tree {
return newTree()
}
// #endregion
// #region consts
// node constraints.
const (
node4Min = 2 // minimum number of children for node4.
node4Max = 4 // maximum number of children for node4.
node16Min = node4Max + 1 // minimum number of children for node16.
node16Max = 16 // maximum number of children for node16.
node48Min = node16Max + 1 // minimum number of children for node48.
node48Max = 48 // maximum number of children for node48.
node256Min = node48Max + 1 // minimum number of children for node256.
node256Max = 256 // maximum number of children for node256.
)
const (
// maxPrefixLen is maximum prefix length for internal nodes.
maxPrefixLen = 10
)
// #endregion
// #region factory
// nodeFactory is an interface for creating various types of ART nodes,
// including nodes with different capacities and leaf nodes.
type nodeFactory interface {
newNode4() *nodeRef
newNode16() *nodeRef
newNode48() *nodeRef
newNode256() *nodeRef
newLeaf(key Key, value interface{}) *nodeRef
}
// make sure that objFactory implements all methods of nodeFactory interface.
var _ nodeFactory = &objFactory{}
//nolint:gochecknoglobals
var (
factory = newObjFactory()
)
// newTree creates a new tree.
func newTree() *tree {
return &tree{
version: 0,
root: nil,
size: 0,
}
}
// objFactory implements nodeFactory interface.
type objFactory struct{}
// newObjFactory creates a new objFactory.
func newObjFactory() nodeFactory {
return &objFactory{}
}
// Simple obj factory implementation.
func (f *objFactory) newNode4() *nodeRef {
return &nodeRef{
kind: Node4,
ref: unsafe.Pointer(new(node4)), //#nosec:G103
}
}
// newNode16 creates a new node16 as a nodeRef.
func (f *objFactory) newNode16() *nodeRef {
return &nodeRef{
kind: Node16,
ref: unsafe.Pointer(new(node16)), //#nosec:G103
}
}
// newNode48 creates a new node48 as a nodeRef.
func (f *objFactory) newNode48() *nodeRef {
return &nodeRef{
kind: Node48,
ref: unsafe.Pointer(new(node48)), //#nosec:G103
}
}
// newNode256 creates a new node256 as a nodeRef.
func (f *objFactory) newNode256() *nodeRef {
return &nodeRef{
kind: Node256,
ref: unsafe.Pointer(new(node256)), //#nosec:G103
}
}
// newLeaf creates a new leaf node as a nodeRef.
// It clones the key to avoid any source key mutation.
func (f *objFactory) newLeaf(key Key, value interface{}) *nodeRef {
keyClone := make(Key, len(key))
copy(keyClone, key)
return &nodeRef{
kind: Leaf,
ref: unsafe.Pointer(&leaf{ //#nosec:G103
key: keyClone,
value: value,
}),
}
}
// #endregion
// #region nodeRef
// indexNotFound is a special index value
// that indicates that the index is not found.
const indexNotFound = -1
// nodeNotFound is a special node pointer
// that indicates that the node is not found
// for different internal tree operations.
var nodeNotFound *nodeRef //nolint:gochecknoglobals
// nodeRef stores all available tree nodes leaf and nodeX types
// as a ref to *unsafe* pointer.
// The kind field is used to determine the type of the node.
type nodeRef struct {
ref unsafe.Pointer
kind Kind
}
type nodeLeafer interface {
minimum() *leaf
maximum() *leaf
}
type nodeSizeManager interface {
hasCapacityForChild() bool
grow() *nodeRef
isReadyToShrink() bool
shrink() *nodeRef
}
type nodeOperations interface {
addChild(kc keyChar, child *nodeRef)
deleteChild(kc keyChar) int
}
type nodeChildren interface {
childAt(idx int) **nodeRef
allChildren() []*nodeRef
}
type nodeKeyIndexer interface {
index(kc keyChar) int
}
// noder is an interface that defines methods that
// must be implemented by nodeRef and all node types.
// extra interfaces are used to group methods by their purpose
// and help with code readability.
type noder interface {
nodeLeafer
nodeOperations
nodeChildren
nodeKeyIndexer
nodeSizeManager
}
// toNode converts the nodeRef to specific node type.
// the idea is to avoid type assertion in the code in multiple places.
func toNode(nr *nodeRef) noder {
if nr == nil {
return noopNoder
}
switch nr.kind { //nolint:exhaustive
case Node4:
return nr.node4()
case Node16:
return nr.node16()
case Node48:
return nr.node48()
case Node256:
return nr.node256()
default:
return noopNoder
}
}
// noop is a no-op noder implementation.
type noop struct{}
func (*noop) minimum() *leaf { return nil }
func (*noop) maximum() *leaf { return nil }
func (*noop) index(keyChar) int { return indexNotFound }
func (*noop) childAt(int) **nodeRef { return &nodeNotFound }
func (*noop) allChildren() []*nodeRef { return nil }
func (*noop) hasCapacityForChild() bool { return true }
func (*noop) grow() *nodeRef { return nil }
func (*noop) isReadyToShrink() bool { return false }
func (*noop) shrink() *nodeRef { return nil }
func (*noop) addChild(keyChar, *nodeRef) {}
func (*noop) deleteChild(keyChar) int { return 0 }
// noopNoder is the default Noder implementation.
var noopNoder noder = &noop{} //nolint:gochecknoglobals
// assert that all node types implement noder interface.
var _ noder = (*node4)(nil)
var _ noder = (*node16)(nil)
var _ noder = (*node48)(nil)
var _ noder = (*node256)(nil)
// assert that nodeRef implements public Node interface.
var _ Node = (*nodeRef)(nil)
// Kind returns the node kind.
func (nr *nodeRef) Kind() Kind {
return nr.kind
}
// Key returns the node key for leaf nodes.
// for nodeX types, it returns nil.
func (nr *nodeRef) Key() Key {
if nr.isLeaf() {
return nr.leaf().key
}
return nil
}
// Value returns the node value for leaf nodes.
// for nodeX types, it returns nil.
func (nr *nodeRef) Value() Value {
if nr.isLeaf() {
return nr.leaf().value
}
return nil
}
// isLeaf returns true if the node is a leaf node.
func (nr *nodeRef) isLeaf() bool {
return nr.kind == Leaf
}
// setPrefix sets the node prefix with the new prefix and prefix length.
func (nr *nodeRef) setPrefix(newPrefix []byte, prefixLen int) {
n := nr.node()
n.prefixLen = uint16(prefixLen) //#nosec:G115
for i := 0; i < minInt(prefixLen, maxPrefixLen); i++ {
n.prefix[i] = newPrefix[i]
}
}
// minimum returns itself if the node is a leaf node.
// otherwise it returns the minimum leaf node under the current node.
func (nr *nodeRef) minimum() *leaf {
if nr.kind == Leaf {
return nr.leaf()
}
return toNode(nr).minimum()
}
// maximum returns itself if the node is a leaf node.
// otherwise it returns the maximum leaf node under the current node.
func (nr *nodeRef) maximum() *leaf {
if nr.kind == Leaf {
return nr.leaf()
}
return toNode(nr).maximum()
}
// findChildByKey returns the child node reference for the given key.
func (nr *nodeRef) findChildByKey(key Key, keyOffset int) **nodeRef {
n := toNode(nr)
idx := n.index(key.charAt(keyOffset))
return n.childAt(idx)
}
// nodeX/leaf casts the nodeRef to the specific nodeX/leaf type.
func (nr *nodeRef) node() *node { return (*node)(nr.ref) } // node casts nodeRef to node.
func (nr *nodeRef) node4() *node4 { return (*node4)(nr.ref) } // node4 casts nodeRef to node4.
func (nr *nodeRef) node16() *node16 { return (*node16)(nr.ref) } // node16 casts nodeRef to node16.
func (nr *nodeRef) node48() *node48 { return (*node48)(nr.ref) } // node48 casts nodeRef to node48.
func (nr *nodeRef) node256() *node256 { return (*node256)(nr.ref) } // node256 casts nodeRef to node256.
func (nr *nodeRef) leaf() *leaf { return (*leaf)(nr.ref) } // leaf casts nodeRef to leaf.
// addChild adds a new child node to the current node.
// If the node is full, it grows to the next node type.
func (nr *nodeRef) addChild(kc keyChar, child *nodeRef) {
n := toNode(nr)
if n.hasCapacityForChild() {
n.addChild(kc, child)
} else {
bigNode := n.grow() // grow to the next node type
bigNode.addChild(kc, child) // recursively add the child to the new node
replaceNode(nr, bigNode) // replace the current node with the new node
}
}
// deleteChild deletes the child node from the current node.
// If the node can shrink after, it shrinks to the previous node type.
func (nr *nodeRef) deleteChild(kc keyChar) bool {
shrank := false
n := toNode(nr)
n.deleteChild(kc)
if n.isReadyToShrink() {
shrank = true
smallNode := n.shrink() // shrink to the previous node type
replaceNode(nr, smallNode) // replace the current node with the shrank node
}
return shrank
}
// match finds the first mismatched index between
// the node's prefix and the specified key prefix.
// This approach efficiently identifies the mismatch by
// leveraging the node's existing prefix data.
func (nr *nodeRef) match(key Key, keyOffset int) int /* 1st mismatch index*/ {
// calc the remaining key length from offset
keyRemaining := len(key) - keyOffset
if keyRemaining < 0 {
return 0
}
n := nr.node()
// the maximum length we can check against the node's prefix
maxPrefixLen := minInt(int(n.prefixLen), maxPrefixLen)
limit := minInt(maxPrefixLen, keyRemaining)
// compare the key against the node's prefix
for i := 0; i < limit; i++ {
if n.prefix[i] != key[keyOffset+i] {
return i
}
}
return limit
}
// matchDeep returns the first index where the key mismatches,
// starting with the node's prefix(see match) and continuing with the minimum leaf's key.
// It returns the mismatch index or matches up to the key's end.
func (nr *nodeRef) matchDeep(key Key, keyOffset int) int /* mismatch index*/ {
mismatchIdx := nr.match(key, keyOffset)
if mismatchIdx < maxPrefixLen {
return mismatchIdx
}
leafKey := nr.minimum().key
limit := minInt(len(leafKey), len(key)) - keyOffset
for ; mismatchIdx < limit; mismatchIdx++ {
if leafKey[keyOffset+mismatchIdx] != key[keyOffset+mismatchIdx] {
break
}
}
return mismatchIdx
}
// #endregion
// #region nodeLeaf
// Leaf node stores the key-value pair.
type leaf struct {
key Key
value interface{}
}
// match returns true if the leaf node's key matches the given key.
func (l *leaf) match(key Key) bool {
return len(l.key) == len(key) && bytes.Equal(l.key, key)
}
// prefixMatch returns true if the leaf node's key has the given key as a prefix.
func (l *leaf) prefixMatch(key Key) bool {
if key == nil || len(l.key) < len(key) {
return false
}
return bytes.Equal(l.key[:len(key)], key)
}
// #endregion
// #region node
// prefix used in the node to store the key prefix.
// it is used to improve leaf key comparison performance.
type prefix [maxPrefixLen]byte
// node is the base struct for all node types.
// it contains the common fields for all nodeX types.
type node struct {
prefix prefix // prefix of the node
prefixLen uint16 // length of the prefix
childrenLen uint16 // number of children in the node4, node16, node48, node256
}
// replaceRef is used to replace node in-place by updating the reference.
func replaceRef(oldNode **nodeRef, newNode *nodeRef) {
*oldNode = newNode
}
// replaceNode is used to replace node in-place by updating the node.
func replaceNode(oldNode *nodeRef, newNode *nodeRef) {
*oldNode = *newNode
}
// #endregion
// #region node4
// node4 represents a node with 4 children.
type node4 struct {
node
children [node4Max + 1]*nodeRef // pointers to the child nodes, +1 is for the zero byte child
keys [node4Max]byte // keys for the children
present [node4Max]byte // present bits for the keys
}
// minimum returns the minimum leaf node.
func (n *node4) minimum() *leaf {
return nodeMinimum(n.children[:])
}
// maximum returns the maximum leaf node.
func (n *node4) maximum() *leaf {
return nodeMaximum(n.children[:n.childrenLen])
}
// index returns the index of the given character.
func (n *node4) index(kc keyChar) int {
if kc.invalid {
return node4Max
}
return findIndex(n.keys[:n.childrenLen], kc.ch)
}
// childAt returns the child at the given index.
func (n *node4) childAt(idx int) **nodeRef {
if idx < 0 || idx >= len(n.children) {
return &nodeNotFound
}
return &n.children[idx]
}
func (n *node4) allChildren() []*nodeRef {
return n.children[:]
}
// hasCapacityForChild returns true if the node has room for more children.
func (n *node4) hasCapacityForChild() bool {
return n.childrenLen < node4Max
}
// grow converts the node4 into the node16.
func (n *node4) grow() *nodeRef {
an16 := factory.newNode16()
n16 := an16.node16()
copyNode(&n16.node, &n.node)
n16.children[node16Max] = n.children[node4Max] // copy zero byte child
for i := 0; i < int(n.childrenLen); i++ {
// skip if the key is not present
if n.present[i] == 0 {
continue
}
// copy elements from n4 to n16 to the last position
n16.insertChildAt(i, n.keys[i], n.children[i])
}
return an16
}
// isReadyToShrink returns true if the node is under-utilized and ready to shrink.
func (n *node4) isReadyToShrink() bool {
// we have to return the number of children for the current node(node4) as
// `node.numChildren` plus one if zero node is not nil.
// For all higher nodes(16/48/256) we simply copy zero node to a smaller node
// see deleteChild() and shrink() methods for implementation details
numChildren := n.childrenLen
if n.children[node4Max] != nil {
numChildren++
}
return numChildren < node4Min
}
// shrink converts the node4 into the leaf node or a node with fewer children.
func (n *node4) shrink() *nodeRef {
// Select the non-nil child node
var nonNilChild *nodeRef
if n.children[0] != nil {
nonNilChild = n.children[0]
} else {
nonNilChild = n.children[node4Max]
}
// if the only child is a leaf node, return it
if nonNilChild.isLeaf() {
return nonNilChild
}
// update the prefix of the child node
n.adjustPrefix(nonNilChild.node())
return nonNilChild
}
// adjustPrefix handles prefix adjustments for a non-leaf child.
func (n *node4) adjustPrefix(childNode *node) {
nodePrefLen := int(n.prefixLen)
// at this point, the node has only one child
// copy the key part of the current node as prefix
if nodePrefLen < maxPrefixLen {
n.prefix[nodePrefLen] = n.keys[0]
nodePrefLen++
}
// copy the part of child prefix that fits into the current node
if nodePrefLen < maxPrefixLen {
childPrefLen := minInt(int(childNode.prefixLen), maxPrefixLen-nodePrefLen)
copy(n.prefix[nodePrefLen:], childNode.prefix[:childPrefLen])
nodePrefLen += childPrefLen
}
// copy the part of the current node prefix that fits into the child node
prefixLen := minInt(nodePrefLen, maxPrefixLen)
copy(childNode.prefix[:], n.prefix[:prefixLen])
childNode.prefixLen += n.prefixLen + 1
}
// addChild adds a new child to the node.
func (n *node4) addChild(kc keyChar, child *nodeRef) {
pos := n.findInsertPos(kc)
n.makeRoom(pos)
n.insertChildAt(pos, kc.ch, child)
}
// find the insert position for the new child.
func (n *node4) findInsertPos(kc keyChar) int {
if kc.invalid {
return node4Max
}
numChildren := int(n.childrenLen)
for i := 0; i < numChildren; i++ {
if n.keys[i] > kc.ch {
return i
}
}
return numChildren
}
// makeRoom creates space for the new child by shifting the elements to the right.
func (n *node4) makeRoom(pos int) {
if pos < 0 || pos >= int(n.childrenLen) {
return
}
for i := int(n.childrenLen); i > pos; i-- {
n.keys[i] = n.keys[i-1]
n.present[i] = n.present[i-1]
n.children[i] = n.children[i-1]
}
}
// insertChildAt inserts the child at the given position.
func (n *node4) insertChildAt(pos int, ch byte, child *nodeRef) {
if pos == node4Max {
n.children[pos] = child
} else {
n.keys[pos] = ch
n.present[pos] = 1
n.children[pos] = child
n.childrenLen++
}
}
// deleteChild deletes the child from the node.
func (n *node4) deleteChild(kc keyChar) int {
if kc.invalid {
// clear the zero byte child reference
n.children[node4Max] = nil
} else if idx := n.index(kc); idx >= 0 {
n.deleteChildAt(idx)
n.clearLastElement()
}
// we have to return the number of children for the current node(node4) as
// `n.numChildren` plus one if null node is not nil.
// `Shrink` method can be invoked after this method,
// `Shrink` can convert this node into a leaf node type.
// For all higher nodes(16/48/256) we simply copy null node to a smaller node
// see deleteChild() and shrink() methods for implementation details
numChildren := int(n.childrenLen)
if n.children[node4Max] != nil {
numChildren++
}
return numChildren
}
// deleteChildAt deletes the child at the given index
// by shifting the elements to the left to overwrite deleted child.
func (n *node4) deleteChildAt(idx int) {
for i := idx; i < int(n.childrenLen) && i+1 < node4Max; i++ {
n.keys[i] = n.keys[i+1]
n.present[i] = n.present[i+1]
n.children[i] = n.children[i+1]
}
n.childrenLen--
}
// clearLastElement clears the last element in the node.
func (n *node4) clearLastElement() {
lastIdx := int(n.childrenLen)
n.keys[lastIdx] = 0
n.present[lastIdx] = 0
n.children[lastIdx] = nil
}
// #endregion
// #region node16
// present16 is a bitfield to store the presence of keys in the node16.
// node16 needs 16 bits to store the presence of keys.
type present16 uint16
func (p present16) hasChild(idx int) bool {
return p&(1<<idx) != 0
}
func (p *present16) setAt(idx int) {
*p |= 1 << idx
}
func (p *present16) clearAt(idx int) {
*p &= ^(1 << idx)
}
func (p *present16) shiftRight(idx int) {
p.clearAt(idx)
*p |= ((*p & (1 << (idx - 1))) << 1)
}
func (p *present16) shiftLeft(idx int) {
p.clearAt(idx)
*p |= ((*p & (1 << (idx + 1))) >> 1)
}
// node16 represents a node with 16 children.
type node16 struct {
node
children [node16Max + 1]*nodeRef // +1 is for the zero byte child
keys [node16Max]byte
present present16
}
// minimum returns the minimum leaf node.
func (n *node16) minimum() *leaf {
return nodeMinimum(n.children[:])
}
// maximum returns the maximum leaf node.
func (n *node16) maximum() *leaf {
return nodeMaximum(n.children[:n.childrenLen])
}
// index returns the child index for the given key.
func (n *node16) index(kc keyChar) int {
if kc.invalid {
return node16Max
}
return findIndex(n.keys[:n.childrenLen], kc.ch)
}
// childAt returns the child at the given index.
func (n *node16) childAt(idx int) **nodeRef {
if idx < 0 || idx >= len(n.children) {
return &nodeNotFound
}
return &n.children[idx]
}
func (n *node16) allChildren() []*nodeRef {
return n.children[:]
}
// hasCapacityForChild returns true if the node has room for more children.
func (n *node16) hasCapacityForChild() bool {
return n.childrenLen < node16Max
}
// grow converts the node to a node48.
func (n *node16) grow() *nodeRef {
an48 := factory.newNode48()
n48 := an48.node48()
copyNode(&n48.node, &n.node)
n48.children[node48Max] = n.children[node16Max] // copy zero byte child
for numChildren, i := 0, 0; i < int(n.childrenLen); i++ {
if !n.hasChild(i) {
continue // skip if the key is not present
}
n48.insertChildAt(numChildren, n.keys[i], n.children[i])
numChildren++
}
return an48
}
// caShrinkNode returns true if the node can be shriken.
func (n *node16) isReadyToShrink() bool {
return n.childrenLen < node16Min
}
// shrink converts the node16 into the node4.
func (n *node16) shrink() *nodeRef {
an4 := factory.newNode4()
n4 := an4.node4()
copyNode(&n4.node, &n.node)
n4.children[node4Max] = n.children[node16Max]
for i := 0; i < node4Max; i++ {
n4.keys[i] = n.keys[i]
if n.hasChild(i) {
n4.present[i] = 1
}
n4.children[i] = n.children[i]
if n4.children[i] != nil {
n4.childrenLen++
}
}
return an4
}
func (n *node16) hasChild(idx int) bool {
return n.present.hasChild(idx)
}
// addChild adds a new child to the node.
func (n *node16) addChild(kc keyChar, child *nodeRef) {
pos := n.findInsertPos(kc)
n.makeRoom(pos)
n.insertChildAt(pos, kc.ch, child)
}
// find the insert position for the new child.
func (n *node16) findInsertPos(kc keyChar) int {
if kc.invalid {
return node16Max
}
for i := 0; i < int(n.childrenLen); i++ {
if n.keys[i] > kc.ch {
return i
}
}
return int(n.childrenLen)
}
// makeRoom makes room for a new child at the given position.
func (n *node16) makeRoom(pos int) {
if pos < 0 || pos >= int(n.childrenLen) {
return
}
// Shift keys and children to the right starting from the position
copy(n.keys[pos+1:], n.keys[pos:int(n.childrenLen)])
copy(n.children[pos+1:], n.children[pos:int(n.childrenLen)])