-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathnode_16.go
219 lines (174 loc) · 4.74 KB
/
node_16.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
package art
// 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)])
for i := int(n.childrenLen); i > pos; i-- {
n.present.shiftRight(i)
}
}
// insertChildAt inserts a new child at the given position.
func (n *node16) insertChildAt(pos int, ch byte, child *nodeRef) {
if pos < 0 || pos > node16Max {
return
}
if pos == node16Max {
n.children[pos] = child
} else {
n.keys[pos] = ch
n.present.setAt(pos)
n.children[pos] = child
n.childrenLen++
}
}
// deleChild removes a child from the node.
func (n *node16) deleteChild(kc keyChar) int {
if kc.invalid {
// clear the zero byte child reference
n.children[node16Max] = nil
} else if idx := n.index(kc); idx >= 0 {
n.deleteChildAt(idx)
n.clearLastElement()
}
return int(n.childrenLen)
}
// deleteChildAt removes a child at the given position.
func (n *node16) deleteChildAt(idx int) {
childrenLen := int(n.childrenLen)
if idx >= childrenLen {
return
}
// Shift keys and children to the left, overwriting the deleted index
copy(n.keys[idx:], n.keys[idx+1:childrenLen])
copy(n.children[idx:], n.children[idx+1:childrenLen])
// shift elements to the left to fill the gap
for i := idx; i < childrenLen && i+1 < node16Max; i++ {
n.present.shiftLeft(i)
}
n.childrenLen--
}
// clearLastElement clears the last element in the node.
func (n *node16) clearLastElement() {
lastIdx := int(n.childrenLen)
n.keys[lastIdx] = 0
n.present.clearAt(lastIdx)
n.children[lastIdx] = nil
}