diff --git a/lib/bcoin/rbt.js b/lib/bcoin/rbt.js index ab931cd6..d9ee63c7 100644 --- a/lib/bcoin/rbt.js +++ b/lib/bcoin/rbt.js @@ -479,24 +479,13 @@ RBT.prototype.snapshot = function snapshot() { */ RBT.prototype.traverse = function traverse(test) { - var current = this.root; - var stack = []; + var current = this.min(this.root); var items = []; - for (;;) { - if (!current.isNull()) { - if (test(current)) - items.push(current.copy()); - stack.push(current); - current = current.left; - continue; - } - - if (stack.length === 0) - break; - - current = stack.pop(); - current = current.right; + while (!current.isNull()) { + if (test(current)) + items.push(current.copy()); + current = this.successor(current); } return items; @@ -519,8 +508,8 @@ RBT.prototype.dump = function dump() { */ RBT.prototype.range = function range(gte, lte) { - var current = this.root; - var stack = []; + var root = this.root; + var current = SENTINEL; var items = []; var cmp; @@ -530,63 +519,44 @@ RBT.prototype.range = function range(gte, lte) { if (typeof lte === 'string') lte = new Buffer(lte, 'ascii'); - for (;;) { - if (!current.isNull()) { - cmp = this.rangeCompare(current.key, gte, lte); + if (gte) { + // Find the node closest to our gte key. + while (!root.isNull()) { + cmp = this.compare(gte, root.key); + if (cmp === 0) { - items.push(current.copy()); - stack.push(current); + current = root; + break; } - if (cmp <= 0) - current = current.left; - else - current = current.right; - continue; + + if (cmp < 0) { + current = root; + root = root.left; + } else { + root = root.right; + } + } + } else { + // Descend into the left subtree. + current = this.min(root); + } + + // Walk the tree in order. + while (!current.isNull()) { + if (lte) { + // Stop once we hit a key above our lte key. + cmp = this.compare(current.key, lte); + if (cmp > 0) + break; } - if (stack.length === 0) - break; - - current = stack.pop(); - current = current.right; + items.push(current.copy()); + current = this.successor(current); } return items; }; -/** - * Comparator for {@link RBT#range}. - * @param {Buffer} key - * @param {Buffer} gteKey - * @param {Buffer} lteKey - * @returns {Number} - */ - -RBT.prototype.rangeCompare = function rangeCompare(key, gteKey, lteKey) { - var gte, lte; - - if (gteKey) - gte = this.compare(key, gteKey); - else - gte = 0; - - if (lteKey) - lte = this.compare(key, lteKey); - else - lte = 0; - - if (gte >= 0 && lte <= 0) - return 0; - - if (lte > 0) - return -1; - - if (gte < 0) - return 1; - - assert(false); -}; - /** * Open the database (leveldown method). * @param {Object?} options