git ssb

0+

wanderer🌟 / js-dfinity-radix-tree



Commit 2adb9b0653c1e154ac7159d623207f66d623e599

drop the idea of multipe radix support

wanderer committed on 8/4/2017, 8:06:42 PM
Parent: c5000f3abc5af622b60625081dd851aae564cd02

Files changed

index.jschanged
tests/index.jschanged
index.jsView
@@ -3,59 +3,42 @@
33 const TextEncoder = require('text-encoding').TextEncoder
44
55 const encoder = new TextEncoder('utf-8')
66
7-module.exports = class RadixTree {
7 +const RadixTree = module.exports = class RadixTree {
88 constructor (opts) {
99 this.root = opts.root || {'/': null}
1010 this.dag = opts.dag
11- this.radix = opts.radix || 2
11 + this.radix = 2
1212 this.graph = new Graph(this.dag)
1313 }
1414
15- get ArrayConstructor () {
16- switch (this.radix) {
17- case 2:
18- return Uint1Array
19- case 8:
20- return Uint8Array
21- case 16:
22- return Uint16Array
23- case 32:
24- return Uint32Array
25- }
15 + static get ArrayConstructor () {
16 + return Uint1Array
2617 }
2718
28- toTypedArray (array) {
29- return new this.ArrayConstructor(new Uint8Array(array).buffer)
19 + static toTypedArray (array) {
20 + return new RadixTree.ArrayConstructor(new Uint8Array(array).buffer)
3021 }
3122
3223 async _get (key) {
3324 let index = 0
3425 let root = this.root
35- while (key.length > index) {
26 + while (1) {
3627 if (isExtension(root)) {
3728 let extensionIndex = 0
38- const extension = this.toTypedArray(getExtension(root))
29 + const extensionLen = getLength(root)
30 + const extension = getExtension(root)
3931 let subKey
40- // alll extension are padded to 8 bit alignment. So we need to update
41- // the index later to count for the added padding
42- let padLen
43- if (this.radix === 2) {
44- subKey = key.slice(index, index + extension.length)
45- padLen = subKey.length
46- subKey = new this.ArrayConstructor(subKey.buffer)
47- padLen = subKey.length - padLen
48- } else {
49- subKey = key.subarray(index, extension.length)
50- }
32 + subKey = key.slice(index, index + extensionLen)
33 +
5134 // checks the extension against the key
52- while (extensionIndex < extension.length && extension[extensionIndex] === subKey[extensionIndex]) {
35 + while (extensionIndex < extensionLen && extension[extensionIndex] === subKey[extensionIndex]) {
5336 extensionIndex++
5437 }
55- index += extensionIndex - padLen
38 + index += extensionIndex
5639 // check if we compelete travered the extension
57- if (extensionIndex !== extension.length) {
40 + if (extensionIndex !== extensionLen) {
5841 return {
5942 extensionIndex: extensionIndex,
6043 root: root,
6144 index: index
@@ -63,12 +46,15 @@
6346 }
6447 }
6548
6649 let keySegment = key[index]
67- if (keySegment) {
50 + if (keySegment !== undefined) {
6851 const branch = getBranch(root)
6952 await this.graph.get(branch, keySegment)
53 + // preseves the '/'
7054 root = branch[keySegment]
55 + } else {
56 + break
7157 }
7258
7359 index++
7460 }
@@ -76,9 +62,9 @@
7662 const node = getBranch(root)
7763 // get the value
7864 let value
7965 if (Array.isArray(node)) {
80- value = node[node.length - 1]
66 + value = node[this.radix]
8167 } else {
8268 value = node
8369 }
8470
@@ -94,21 +80,18 @@
9480 }
9581
9682 async get (key) {
9783 key = this.formatKey(key)
98- const results = await this._get(key)
99- return results.value
84 + const result = await this._get(key)
85 + return result.value
10086 }
10187
10288 async set (key, value) {
10389 key = this.formatKey(key)
10490
10591 // initial set
10692 if (this.root['/'] === null) {
107- this.root['/'] = {
108- extension: new Buffer(key.buffer),
109- node: value
110- }
93 + this.root['/'] = createExtension(key, value)['/']
11194 return
11295 }
11396
11497 const result = await this._get(key)
@@ -116,27 +99,27 @@
11699 let keySegment = key[result.index]
117100
118101 if (result.extensionIndex !== undefined) {
119102 // split the extension node in two
120- let extension = this.toTypedArray(getExtension(root))
121- const extensionKey = extension[result.extensionIndex + 1]
122- const remExtension = extension.subarray(1 - result.extensionIndex)
103 + let extension = getExtension(root)
104 + const extensionKey = extension[result.extensionIndex]
105 + const remExtension = extension.subarray(result.extensionIndex + 1)
123106 extension = extension.subarray(0, result.extensionIndex)
124107
125108 const node = getNode(root)
126109 let newNode
127110 // create the new extension node
128111 if (extension.length) {
129- setExtension(root, new Buffer(extension.buffer))
112 + setExtension(root, extension)
130113 newNode = []
131114 setNode(root, newNode)
132115 } else {
133116 newNode = root['/'] = []
134117 }
135118
136119 // save the remainer of the extension node
137120 if (remExtension.length) {
138- newNode[extensionKey] = createExtension(new Buffer(remExtension.buffer), node)
121 + newNode[extensionKey] = createExtension(remExtension, node)
139122 } else {
140123 newNode[extensionKey] = node
141124 }
142125 }
@@ -144,9 +127,9 @@
144127 let newNode
145128 if (result.index + 1 < key.length) {
146129 // if there are remaning key segments create an extension node
147130 const extension = key.subarray(result.index + 1, key.length)
148- newNode = createExtension(new Buffer(extension.buffer), value)
131 + newNode = createExtension(extension, value)
149132 } else {
150133 newNode = value
151134 }
152135
@@ -208,45 +191,53 @@
208191 }
209192 formatKey (key) {
210193 if (typeof key === 'string') {
211194 key = encoder.encode(key)
195 + return new RadixTree.ArrayConstructor(key.buffer)
196 + } else {
197 + return key
212198 }
213- return new this.ArrayConstructor(key.buffer)
214199 }
215200 }
216201
217202 function getBranch (node) {
218203 if (isExtension(node)) {
219204 return getNode(node)
220205 } else {
221- return root['/']
206 + return node['/']
222207 }
223208 }
224209
225210 function isExtension (node) {
226211 return !!node['/'].extension
227212 }
228213
229214 function getExtension (node) {
230- return node['/'].extension
215 + return RadixTree.toTypedArray(node['/'].extension).subarray(0, getLength(node))
231216 }
232217
233218 function getNode (node) {
234219 return node['/'].node
235220 }
236221
222 +function getLength (node) {
223 + return node['/'].length
224 +}
225 +
237226 function setExtension (node, ex) {
238- node['/'].extension = ex
227 + node['/'].extension = new Buffer(ex.buffer)
228 + node['/'].length = ex.length
239229 }
240230
241231 function setNode (node, val) {
242232 node['/'].node = val
243233 }
244234
245-function createExtension(ex, node) {
235 +function createExtension (ex, node) {
246236 return {
247237 '/': {
248- extension: ex,
249- node: node
238 + extension: new Buffer(ex.buffer),
239 + node: node,
240 + length: ex.length
250241 }
251242 }
252243 }
tests/index.jsView
@@ -7,25 +7,51 @@
77 start: false
88 })
99
1010 node.on('ready', () => {
11- tape('set', async t => {
11 + tape('set and get', async t => {
1212 const tree = new RadixTree({
1313 dag: node.dag
1414 })
1515 try {
1616 await tree.set('test', 'cat')
1717 let val = await tree.get('test')
1818 t.equals(val, 'cat')
1919 await tree.set('te', 'blop')
20- // console.log(JSON.stringify(tree.root, null, 2))
2120 val = await tree.get('test')
2221 t.equals(val, 'cat')
2322
2423 val = await tree.get('te')
2524 t.equals(val, 'blop')
25 +
26 + await tree.set('rad', 'cat2')
27 +
28 + val = await tree.get('rad')
29 + t.equals(val, 'cat2')
2630 } catch (e) {
2731 console.log(e)
2832 }
2933 t.end()
3034 })
35 +
36 + tape('branch nodes', async t => {
37 + const tree = new RadixTree({
38 + dag: node.dag
39 + })
40 + try {
41 + let key0 = new RadixTree.ArrayConstructor([1, 1, 0, 0])
42 + await tree.set(key0, 'cat')
43 + let key1 = new RadixTree.ArrayConstructor([0, 1, 0, 1])
44 + await tree.set(key1, 'cat2')
45 + let val = await tree.get(key0)
46 + t.equals(val, 'cat')
47 + val = await tree.get(key1)
48 + t.equals(val, 'cat2')
49 +
50 + let key3 = new RadixTree.ArrayConstructor([0, 1, 0, 1, 1])
51 + await tree.set(key3, 'test')
52 + } catch (e) {
53 + console.log(e)
54 + }
55 + t.end()
56 + })
3157 })

Built with git-ssb-web