@@ -5,11 +5,6 @@ const TextEncoder = require('text-encoding').TextEncoder
55
66const encoder = new TextEncoder ( 'utf-8' )
77
8- const LBRANCH = 0
9- const RBRANCH = 1
10- const EXTENSION = 2
11- const VALUE = 3
12-
138const RadixTree = module . exports = class RadixTree {
149 /**
1510 * @param opts
@@ -18,10 +13,17 @@ const RadixTree = module.exports = class RadixTree {
1813 * @param opts.dag {object} an instance if [ipfs.dag](https://github.com/ipfs/js-ipfs#dag). If there is no `opts.graph` this will be used to create a new graph instance.
1914 */
2015 constructor ( opts ) {
21- this . root = opts . root || { '/' : undefined }
16+ this . root = opts . root || { '/' : RadixTree . emptyTreeState }
2217 this . graph = opts . graph || new Graph ( opts . dag )
2318 }
2419
20+ /**
21+ * returns the state of an empty tree
22+ */
23+ static get emptyTreeState ( ) {
24+ return [ undefined , undefined ]
25+ }
26+
2527 /**
2628 * returns an Uint1Array constructir which is used to repersent keys
2729 * @returns {object }
@@ -43,13 +45,14 @@ const RadixTree = module.exports = class RadixTree {
4345 let index = 0
4446 let root = this . root
4547 let parent
48+
4649 while ( 1 ) {
4750 // load the root
4851 const exNode = await this . graph . get ( root , EXTENSION , true )
4952 if ( exNode ) {
5053 let extensionIndex = 0
51- const extensionLen = getExLength ( root )
5254 const extension = getExtension ( root )
55+ const extensionLen = extension . length
5356 let subKey
5457 subKey = key . slice ( index , index + extensionLen )
5558
@@ -127,40 +130,35 @@ const RadixTree = module.exports = class RadixTree {
127130 value = { '/' : value }
128131 }
129132
130- // initial set
131- if ( this . root [ '/' ] === undefined ) {
132- this . root [ '/' ] = createNode ( key , [ ] , value ) [ '/' ]
133+ const result = await this . _get ( key )
134+ let root = result . root
135+
136+ if ( result . value ) {
137+ setValue ( root , value )
133138 } else {
134- const result = await this . _get ( key )
135- let root = result . root
139+ if ( result . extensionIndex !== undefined ) {
140+ // split the extension node in two
141+ let extension = getExtension ( root )
142+ const extensionKey = extension [ result . extensionIndex ]
143+ const remExtension = extension . subarray ( result . extensionIndex + 1 )
144+ extension = extension . subarray ( 0 , result . extensionIndex )
145+
146+ setExtension ( root , remExtension )
147+ const branch = [ ]
148+ branch [ extensionKey ] = { '/' : root [ '/' ] }
149+ root [ '/' ] = createNode ( extension , branch ) [ '/' ]
150+ }
136151
137- if ( result . value ) {
138- setValue ( root , value )
152+ // if there are remaning key segments create an extension node
153+ if ( result . index < key . length ) {
154+ const keySegment = key [ result . index ]
155+ const extension = key . subarray ( result . index + 1 , key . length )
156+ const newNode = createNode ( extension , [ ] , value )
157+ const rootBranch = getBranch ( root )
158+ rootBranch [ keySegment ] = newNode
159+ setBranch ( root , rootBranch )
139160 } else {
140- if ( result . extensionIndex !== undefined ) {
141- // split the extension node in two
142- let extension = getExtension ( root )
143- const extensionKey = extension [ result . extensionIndex ]
144- const remExtension = extension . subarray ( result . extensionIndex + 1 )
145- extension = extension . subarray ( 0 , result . extensionIndex )
146-
147- setExtension ( root , remExtension )
148- const branch = [ ]
149- branch [ extensionKey ] = { '/' : root [ '/' ] }
150- root [ '/' ] = createNode ( extension , branch ) [ '/' ]
151- }
152-
153- // if there are remaning key segments create an extension node
154- if ( result . index < key . length ) {
155- const keySegment = key [ result . index ]
156- const extension = key . subarray ( result . index + 1 , key . length )
157- const newNode = createNode ( extension , [ ] , value )
158- const rootBranch = getBranch ( root )
159- rootBranch [ keySegment ] = newNode
160- setBranch ( root , rootBranch )
161- } else {
162- setValue ( root , value )
163- }
161+ setValue ( root , value )
164162 }
165163 }
166164 }
@@ -184,7 +182,7 @@ const RadixTree = module.exports = class RadixTree {
184182 joinNodes ( root )
185183 } else {
186184 if ( ! parent ) {
187- root [ '/' ] = undefined
185+ root [ '/' ] = RadixTree . emptyTreeState
188186 } else {
189187 let branch = getBranch ( parent )
190188 branch = branch . map ( node => node === root ? undefined : node )
@@ -257,6 +255,11 @@ function createNode (ex, branch, value) {
257255}
258256
259257// helper functions for nodes
258+ const LBRANCH = 0
259+ const RBRANCH = 1
260+ const EXTENSION = 2
261+ const VALUE = 3
262+
260263function setBranch ( node , branch ) {
261264 node [ '/' ] [ LBRANCH ] = branch [ 0 ]
262265 node [ '/' ] [ RBRANCH ] = branch [ 1 ]
@@ -276,16 +279,13 @@ function deleteValue (node) {
276279
277280function getExtension ( node ) {
278281 if ( node [ '/' ] [ EXTENSION ] ) {
279- return RadixTree . toTypedArray ( node [ '/' ] [ EXTENSION ] [ 1 ] ) . subarray ( 0 , getExLength ( node ) )
282+ const len = node [ '/' ] [ EXTENSION ] [ 0 ]
283+ return RadixTree . toTypedArray ( node [ '/' ] [ EXTENSION ] [ 1 ] ) . subarray ( 0 , len )
280284 } else {
281285 return [ ]
282286 }
283287}
284288
285- function getExLength ( node ) {
286- return node [ '/' ] [ EXTENSION ] [ 0 ]
287- }
288-
289289function setExtension ( node , ex ) {
290290 if ( ex && ex . length ) {
291291 node [ '/' ] [ EXTENSION ] = [ ex . length , Buffer . from ( ex . buffer ) ]
0 commit comments