index.jsView |
---|
23 | 23 … | async _get (key) { |
24 | 24 … | let index = 0 |
25 | 25 … | let root = this.root |
26 | 26 … | while (1) { |
27 | | - if (isExtension(root)) { |
| 27 … | + if (hasExtension(root)) { |
28 | 28 … | let extensionIndex = 0 |
29 | | - const extensionLen = getLength(root) |
| 29 … | + const extensionLen = getExLength(root) |
30 | 30 … | const extension = getExtension(root) |
31 | 31 … | let subKey |
32 | 32 … | subKey = key.slice(index, index + extensionLen) |
33 | 33 … | |
50 | 50 … | if (keySegment !== undefined) { |
51 | 51 … | const branch = getBranch(root) |
52 | 52 … | await this.graph.get(branch, keySegment) |
53 | 53 … | |
54 | | - root = branch[keySegment] |
| 54 … | + const nextRoot = branch[keySegment] |
| 55 … | + if (!nextRoot) { |
| 56 … | + return { |
| 57 … | + root: root, |
| 58 … | + index: index |
| 59 … | + } |
| 60 … | + } else { |
| 61 … | + root = nextRoot |
| 62 … | + } |
55 | 63 … | } else { |
56 | 64 … | break |
57 | 65 … | } |
58 | 66 … | |
59 | 67 … | index++ |
60 | 68 … | } |
61 | 69 … | |
62 | | - const node = getBranch(root) |
63 | | - |
64 | | - let value |
65 | | - if (Array.isArray(node)) { |
66 | | - value = node[this.radix] |
67 | | - } else { |
68 | | - value = node |
69 | | - } |
| 70 … | + let value = getValue(root) |
70 | 71 … | |
71 | 72 … | if (value.length >= 32) { |
72 | 73 … | value = await this.graph.get(root, root.length - 1) |
73 | 74 … | } |
79 | 80 … | } |
80 | 81 … | } |
81 | 82 … | |
82 | 83 … | async get (key) { |
83 | | - key = this.formatKey(key) |
| 84 … | + key = RadixTree.formatKey(key) |
84 | 85 … | const result = await this._get(key) |
85 | 86 … | return result.value |
86 | 87 … | } |
87 | 88 … | |
88 | 89 … | async set (key, value) { |
89 | | - key = this.formatKey(key) |
| 90 … | + key = RadixTree.formatKey(key) |
90 | 91 … | |
91 | 92 … | |
92 | 93 … | if (this.root['/'] === null) { |
93 | | - this.root['/'] = createExtension(key, value)['/'] |
| 94 … | + this.root['/'] = createNode(value, key)['/'] |
94 | 95 … | return |
95 | 96 … | } |
96 | 97 … | |
97 | 98 … | const result = await this._get(key) |
98 | 99 … | let root = result.root |
99 | | - let keySegment = key[result.index] |
100 | 100 … | |
| 101 … | + if (result.value) { |
| 102 … | + setValue(root, value) |
| 103 … | + return |
| 104 … | + } |
| 105 … | + |
101 | 106 … | if (result.extensionIndex !== undefined) { |
102 | 107 … | |
103 | 108 … | let extension = getExtension(root) |
104 | 109 … | const extensionKey = extension[result.extensionIndex] |
105 | 110 … | const remExtension = extension.subarray(result.extensionIndex + 1) |
106 | 111 … | extension = extension.subarray(0, result.extensionIndex) |
107 | 112 … | |
108 | | - const node = getNode(root) |
109 | | - let newNode |
110 | | - |
111 | | - if (extension.length) { |
112 | | - setExtension(root, extension) |
113 | | - newNode = [] |
114 | | - setNode(root, newNode) |
115 | | - } else { |
116 | | - newNode = root['/'] = [] |
117 | | - } |
118 | | - |
119 | | - |
120 | | - if (remExtension.length) { |
121 | | - newNode[extensionKey] = createExtension(remExtension, node) |
122 | | - } else { |
123 | | - newNode[extensionKey] = node |
124 | | - } |
| 113 … | + setExtension(root, remExtension) |
| 114 … | + const branch = [] |
| 115 … | + branch[extensionKey] = {'/': root['/']} |
| 116 … | + root['/'] = createNode(null, extension, branch)['/'] |
125 | 117 … | } |
126 | 118 … | |
127 | | - let newNode |
128 | | - if (result.index + 1 < key.length) { |
129 | | - |
| 119 … | + |
| 120 … | + if (result.index < key.length) { |
| 121 … | + const keySegment = key[result.index] |
130 | 122 … | const extension = key.subarray(result.index + 1, key.length) |
131 | | - newNode = createExtension(extension, value) |
| 123 … | + const newNode = createNode(value, extension) |
| 124 … | + const rootBranch = getBranch(root) |
| 125 … | + rootBranch[keySegment] = newNode |
132 | 126 … | } else { |
133 | | - newNode = value |
| 127 … | + setValue(root, value) |
134 | 128 … | } |
135 | | - |
136 | | - let targetNode = getBranch(root) |
137 | | - |
138 | | - |
139 | | - if (keySegment === undefined) { |
140 | | - targetNode[this.radix] = newNode |
141 | | - } else { |
142 | | - targetNode[keySegment] = newNode |
143 | | - } |
144 | 129 … | } |
145 | 130 … | |
146 | 131 … | |
147 | 132 … | |
185 | 170 … | |
186 | 171 … | |
187 | 172 … | |
188 | 173 … | |
189 | | - isEmptyNode (node) { |
190 | | - return node.evey(el => !el) |
191 | | - } |
192 | | - formatKey (key) { |
| 174 … | + static formatKey (key) { |
193 | 175 … | if (typeof key === 'string') { |
194 | 176 … | key = encoder.encode(key) |
195 | 177 … | return new RadixTree.ArrayConstructor(key.buffer) |
196 | 178 … | } else { |
199 | 181 … | } |
200 | 182 … | } |
201 | 183 … | |
202 | 184 … | function getBranch (node) { |
203 | | - if (isExtension(node)) { |
204 | | - return getNode(node) |
205 | | - } else { |
206 | | - return node['/'] |
207 | | - } |
| 185 … | + return node['/'].branch |
208 | 186 … | } |
209 | 187 … | |
210 | | -function isExtension (node) { |
| 188 … | +function getValue (node) { |
| 189 … | + return node['/'].value |
|
| 190 … | +} |
| 191 … | + |
| 192 … | +function hasExtension (node) { |
211 | 193 … | return !!node['/'].extension |
212 | 194 … | } |
213 | 195 … | |
214 | 196 … | function getExtension (node) { |
215 | | - return RadixTree.toTypedArray(node['/'].extension).subarray(0, getLength(node)) |
| 197 … | + return RadixTree.toTypedArray(node['/'].extension[1]).subarray(0, getExLength(node)) |
216 | 198 … | } |
217 | 199 … | |
218 | | -function getNode (node) { |
219 | | - return node['/'].node |
| 200 … | +function getExLength (node) { |
| 201 … | + return node['/'].extension[0] |
220 | 202 … | } |
221 | 203 … | |
222 | | -function getLength (node) { |
223 | | - return node['/'].length |
224 | | -} |
225 | | - |
226 | 204 … | function setExtension (node, ex) { |
227 | | - node['/'].extension = new Buffer(ex.buffer) |
228 | | - node['/'].length = ex.length |
| 205 … | + if (ex && ex.length) { |
| 206 … | + node['/'].extension = [ex.length, new Buffer(ex.buffer)] |
| 207 … | + } else { |
| 208 … | + node['/'].extension = null |
| 209 … | + } |
229 | 210 … | } |
230 | 211 … | |
231 | | -function setNode (node, val) { |
232 | | - node['/'].node = val |
| 212 … | +function setValue (node, val) { |
| 213 … | + node['/'].value = val |
233 | 214 … | } |
234 | 215 … | |
235 | | -function createExtension (ex, node) { |
| 216 … | +function createNode (value, ex, branch = []) { |
| 217 … | + if (ex && ex.length) { |
| 218 … | + ex = [ex.length, new Buffer(ex.buffer)] |
| 219 … | + } else { |
| 220 … | + ex = null |
| 221 … | + } |
| 222 … | + |
236 | 223 … | return { |
237 | 224 … | '/': { |
238 | | - extension: new Buffer(ex.buffer), |
239 | | - node: node, |
240 | | - length: ex.length |
| 225 … | + extension: ex, |
| 226 … | + branch: branch, |
| 227 … | + value: value |
241 | 228 … | } |
242 | 229 … | } |
243 | 230 … | } |