UNPKG

ndn-js-contrib

Version:

Reusable 'Classes' for Named Data Networking: NameTree, PIT, FIB, ContentStore, Interfaces, and Transports

283 lines (282 loc) 8.52 kB
var Name = require('ndn-js/js/name.js').Name; function checkNode(functionName, node) { if (!(node && node._isNTN)) throw new Error(functionName + ": invalid argument, requires a NameTreeNode"); } var NameTree = function NameTree() { this.root = new NameTree.Node(new Name("")); var self = this; this[Symbol.iterator] = function NameTree_Iterator() { var iter; if (self._traversal_direction + 1 === 0) { throw new Error("NameTree[Symbol.iterator](): must use NameTree.up(prefix)/.left(prefix)/.right(prefix) to set traversal direction"); } else if (self._traversal_direction === NameTree.TRAVERSE_UP) { iter = new Prefix_Iterator(self, self._traversal_prefix, self._skipper()); } else { iter = new Suffix_Iterator(self, self._traversal_prefix, self._traversal_direction, this._skipper()); } self._traversal_direction = -1; self._traversal_prefix = null; return iter; }; return this; }; NameTree.TRAVERSE_LEFT = 0; NameTree.TRAVERSE_RIGHT = 1; NameTree.TRAVERSE_UP = 2; module.exports = NameTree; NameTree.prototype.insert = function NameTree_insert(node) { var curr = this.root; while (!curr.equals(node)) { curr = curr.insert(node); } curr.insert(node); return this; }; NameTree.prototype.remove = function NameTree_remove(prefix) { this.up(prefix); var first = true, item = null, removeSuffix; var $__3 = true; var $__4 = false; var $__5 = undefined; try { for (var $__1 = void 0, $__0 = (this)[$traceurRuntime.toProperty(Symbol.iterator)](); !($__3 = ($__1 = $__0.next()).done); $__3 = true) { var node = $__1.value; { if (first) { item = node.getItem(); node.setItem(null); } first = false; if (removeSuffix) node.remove(removeSuffix); removeSuffix = false; if (node.isEmpty() && node.prefix.size() > 0) removeSuffix = node.prefix.get(-1); else { node.updateDepth(~(prefix.size() - node.prefix.size())); } } } } catch ($__6) { $__4 = true; $__5 = $__6; } finally { try { if (!$__3 && $__0.return != null) { $__0.return(); } } finally { if ($__4) { throw $__5; } } } if (removeSuffix) this.root.remove(removeSuffix); else this.root.updateDepth(~prefix.size()); return item; }; NameTree.prototype.get = function NameTree_get(prefix) { var node = new NameTree.Node(prefix); var curr = this.root; while (!curr.equals(node)) { curr = curr.insert(node); } node = curr; return node; }; function Prefix_Iterator(nameTree, prefix, skip) { var node = new NameTree.Node(prefix); var curr = nameTree.root; this._stack = []; while (!curr.equals(node)) { if (!skip(curr)) this._stack.push(curr); curr = curr.insert(node); } if (!skip(curr)) this._stack.push(curr); } Prefix_Iterator.prototype.next = function NameTree_Iterator_next() { var done = (this._stack.length === 0); if (!done) var next = this._stack.pop(); return { value: next, done: done }; }; function Suffix_Iterator(nameTree, prefix, _reverse, skip) { this._stack = [(_reverse) ? nameTree.get(prefix)._reverse()[Symbol.iterator]() : nameTree.get(prefix)[Symbol.iterator]()]; this._reverse = _reverse; this.skip = skip; this.first = [nameTree.get(prefix)]; return this; } Suffix_Iterator.prototype.next = function Suffix_Iterator_next() { if (this.first.length) { return (!this.skip(this.first[0])) ? { value: this.first.pop(), done: false } : { value: null, done: true }; } var iter = this._stack.pop(); while (iter) { do { var next = iter.next(); if (next.done) break; } while (this.skip(next.value)); if (!next.done) { this._stack.push(iter); this._stack.push((this._reverse) ? next.value._reverse()[Symbol.iterator]() : next.value[Symbol.iterator]()); return next; } else { iter = this._stack.pop(); } } return { value: null, done: true }; }; NameTree.prototype.skip = function NameTree_skip(skip) { var self = this; this._skipper = function _skipper() { self._skipper = NameTree.prototype._skipper; return skip; }; }; NameTree.prototype._skipper = function NameTree__skipper() { return function skip() { return false; }; }; NameTree.prototype.up = function NameTree_up(prefix, skip) { this._traversal_direction = NameTree.TRAVERSE_UP; this._traversal_prefix = prefix || this.head; }; NameTree.prototype.left = function NameTree_left(prefix) { this._traversal_direction = NameTree.TRAVERSE_LEFT; this._traversal_prefix = prefix || this.root.prefix; }; NameTree.prototype.right = function NameTree_right(prefix) { this._traversal_direction = NameTree.TRAVERSE_RIGHT; this._traversal_prefix = prefix || this.root.prefix; }; NameTree.prototype._traversal_direction = -1; NameTree.prototype._traversal_start = null; NameTree.Node = function NameTree_Node(prefix, item) { this.item = item; this.children = []; this.prefix = prefix; this.depth = 0; var self = this; this[Symbol.iterator] = function NameTree_Node_Iterator() { var iter = new Child_Iterator(self, self._traversal_direction, self._skipper()); self._traversal_direction = NameTree.TRAVERSE_LEFT; return iter; }; return this; }; NameTree.Node.prototype.depth = function NameTree_Node_depth() { return this.depth; }; NameTree.Node.prototype.skip = NameTree.prototype.skip; NameTree.Node.prototype._skipper = NameTree.prototype._skipper; NameTree.Node.prototype.equals = function NameTree_Node_equals(node) { return this.prefix.equals(node.prefix); }; NameTree.Node.prototype.getItem = function NameTree_Node_getItem() { return this.item; }; NameTree.Node.prototype.setItem = function NameTree_Node_setItem(item) { this.item = item; }; NameTree.Node.prototype.indexOf = function NameTree_Node_indexOf(suffix) { var min = 0, max = this.children.length - 1, guess, comparison; while (min <= max) { guess = Math.floor((min + max) / 2); if (this.children[guess].prefix.get(-1).equals(suffix)) { return guess; } else { comparison = this.children[guess].prefix.get(-1).compare(suffix); if (comparison < 0) min = ++guess; else max = --guess; } } return ~(max + 1); }; NameTree.Node.prototype.insert = function NameTree_Node_insert(node) { if (this.equals(node)) { if (this.item && node.item) throw new Error("NameTree.Node.insert: Already have that node with an Item"); else if (!this.getItem() && node.getItem()) { this.setItem(node.getItem()); } return this; } var suffix = node.prefix.get(this.prefix.size()), childIndex = this.indexOf(suffix), insertion; if (childIndex < 0) { childIndex = ~childIndex; insertion = new NameTree.Node(node.prefix.getPrefix(this.prefix.size() + 1)); this.children.splice(childIndex, 0, insertion); } else { insertion = this.children[childIndex]; } this.updateDepth(node.prefix.size() - this.prefix.size()); return insertion; }; NameTree.Node.prototype.updateDepth = function NameTree_Node_updateDepth(depth) { this.depth = (depth && depth > this.depth) ? depth : (depth) ? this.depth : (this.children.length === 0) ? 0 : Math.max.apply(null, this.children.map(function(child) { return child.depth; })) + 1; }; NameTree.Node.prototype.remove = function NameTree_Node_remove(suffix) { var childIndex = this.indexOf(suffix), node; if (childIndex < 0) node = null; else node = this.children.splice(childIndex, 1)[0]; this.updateDepth(); return node; }; NameTree.Node.prototype._reverse = function NameTree_Node__reverse() { this._traversal_direction = NameTree.TRAVERSE_RIGHT; return this; }; NameTree.Node.prototype.isEmpty = function NameTree_Node_isEmpty() { return (!this.children.length && !this.item); }; NameTree.Node.prototype._traversal_direction = NameTree.TRAVERSE_LEFT; function Child_Iterator(node, direction, skip) { this.direction = direction; this.children = node.children.slice(0); this.skip = skip; } Child_Iterator.prototype.next = function() { var next; do { next = (!this.direction) ? this.children.shift() : this.children.pop(); } while (next && this.skip(next)); return { done: (!next && !this.children.length) ? true : false, value: next }; };