@webkrafters/trie
Version:
Trie - trie data structure accepting any data type
924 lines (923 loc) • 33.4 kB
JavaScript
"use strict";
var _excluded = ["length"];
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _superPropGet(t, o, e, r) { var p = _get2(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
function _get2() { return _get2 = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get2.apply(null, arguments); }
function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ChildNodes = exports.Node = exports.sameValueZero = exports.lessThanValue = exports.getDescriptor = exports.LT_ARG_TYPES_MISMATCH_MSG = exports.LT_TYPES_MSG = void 0;
exports.robustHash = robustHash;
exports.bSearch = bSearch;
exports.isIterable = isIterable;
exports.toArray = toArray;
;
;
;
;
;
;
exports.LT_TYPES_MSG = 'Default LessThan matcher can only be used with `null` values and `string`, `number`, `bigint`, `boolean` and `undefined` value types. For any other type, please provide a custom `isLessThanValue` function option.';
exports.LT_ARG_TYPES_MISMATCH_MSG = 'Default LessThan matcher requires both matched values to be of the same type and also accepts `undefined` and `null` values.';
var typeMapping = {
string: undefined,
number: undefined,
bigint: undefined,
"boolean": undefined,
undefined: undefined
};
exports.getDescriptor = function () {
var t = Object.prototype.toString;
return function (obj) {
var desc = t.call(obj);
return desc.slice(desc.indexOf(' ') + 1, -1);
};
}();
var lessThanValue = function lessThanValue(a, b) {
var typeA = _typeof(a);
var typeB = _typeof(b);
if (typeA === 'undefined' || a === null) {
return typeB !== 'undefined';
}
if (typeB === 'undefined' || b === null) {
return false;
}
if (!(typeA in typeMapping && typeB in typeMapping)) {
throw new TypeError(exports.LT_TYPES_MSG);
}
if (typeA !== typeB) {
throw new TypeError(exports.LT_ARG_TYPES_MISMATCH_MSG);
}
return a < b;
};
exports.lessThanValue = lessThanValue;
var sameValueZero = function sameValueZero(a, b) {
return a === b || a !== a && b !== b;
};
exports.sameValueZero = sameValueZero;
var TRIE_DESC = 'webKrafters.Trie';
var NODE_DESC = 'wbKrafters.Trie.Node';
var Trie = /*#__PURE__*/function () {
function Trie(data) {
var _opts$sorted, _opts$lessThanMatcher, _opts$equalityMatcher;
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Trie);
this.sorted = (_opts$sorted = opts.sorted) !== null && _opts$sorted !== void 0 ? _opts$sorted : false;
this.isLessThanValue = opts.sorted === true ? (_opts$lessThanMatcher = opts.lessThanMatcher) !== null && _opts$lessThanMatcher !== void 0 ? _opts$lessThanMatcher : exports.lessThanValue : null;
this.isSameValue = (_opts$equalityMatcher = opts.equalityMatcher) !== null && _opts$equalityMatcher !== void 0 ? _opts$equalityMatcher : exports.sameValueZero;
this.root = new Node(null, this.isSameValue, this.isLessThanValue, typeof data === 'undefined' || Array.isArray(data) ? data : (0, exports.getDescriptor)(data) === TRIE_DESC ? data.asTrieableNode().children : data.data === null ? data.children : [data]);
}
return _createClass(Trie, [{
key: "isEmpty",
get: function get() {
return this.root.isEmpty;
}
}, {
key: "size",
get: function get() {
return this.root.size;
}
}, {
key: "add",
value: function add(data) {
this.root.addChild(_toConsumableArray(data));
}
}, {
key: "addMany",
value: function addMany(data) {
for (var dLen = data.length, d = 0; d < dLen; d++) {
isIterable(data[d]) ? this.add(data[d]) : this.merge(data[d]);
}
}
}, {
key: "asArray",
value: function asArray() {
var completeSequencesOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
var array = this.root.asArray(completeSequencesOnly);
for (var i = array.length; i--;) {
if (array[i].length) {
return array;
}
}
return [];
}
}, {
key: "asTrieableNode",
value: function asTrieableNode() {
return this.root.asTrieableNode();
}
}, {
key: "clear",
value: function clear() {
this.root.empty();
}
}, {
key: "clone",
value: function clone() {
return new Trie(this.asTrieableNode().children, {
equalityMatcher: this.isSameValue,
lessThanMatcher: this.isLessThanValue,
sorted: this.sorted
});
}
}, {
key: "getAllStartingWith",
value: function getAllStartingWith() {
var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var completeSequencesOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
return this._getAllStartingWith(_toConsumableArray(prefix), completeSequencesOnly);
}
}, {
key: "getFarthestIn",
value: function getFarthestIn() {
var sequence = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var _sequence = toArray(sequence);
return _sequence.slice(0, this.root.getDeepestNodeIn(_sequence).index + 1);
}
}, {
key: "has",
value: function has(sequence) {
var _this$root$getChildPr;
return !!((_this$root$getChildPr = this.root.getChildPrefixEnd(toArray(sequence))) !== null && _this$root$getChildPr !== void 0 && _this$root$getChildPr.isSequenceBoundary);
}
}, {
key: "isSame",
value: function isSame(trie) {
return this === trie;
}
}, {
key: "matches",
value: function matches(graph) {
if (this.isSame(graph)) {
return true;
}
var g = graph;
if ((0, exports.getDescriptor)(graph) === TRIE_DESC) {
g = g.root;
} else if (Array.isArray(g)) {
if (isIterable(g[0])) {
var _g = new Array(g.length);
for (var i = _g.length; i--;) {
_g[i] = toArray(g[i]);
}
g = _g;
} else {
g = {
children: g,
data: null,
isBoundary: false,
parent: null
};
}
}
return this.root.isEqual(g);
}
}, {
key: "merge",
value: function merge(data) {
if ((0, exports.getDescriptor)(data) === TRIE_DESC) {
for (var children = data.root.childNodes.list(), cLen = children.length, c = 0; c < cLen; c++) {
this.root.merge(children[c]);
}
return;
}
if (data.data !== null) {
return this.root.mergeTrieableNode(data);
}
for (var _children = data.children, _cLen = _children.length, _c = 0; _c < _cLen; _c++) {
this.root.mergeTrieableNode(_children[_c]);
}
}
}, {
key: "remove",
value: function remove(data) {
return this.root.removeChild(toArray(data));
}
}, {
key: "removeAllStartingWith",
value: function removeAllStartingWith() {
var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var suffixStartNode = this.root.getChildPrefixEnd(toArray(prefix));
suffixStartNode === null || suffixStartNode === void 0 || suffixStartNode.parentNode.childNodes.remove(suffixStartNode);
}
}, {
key: "removeMany",
value: function removeMany(data) {
var results = [];
for (var dLen = data.length, d = 0; d < dLen; d++) {
results.push(this.remove(data[d]) ? "SUCCESSFUL" : "FAILED");
}
return results;
}
}, {
key: "_getNodeAtPrefixEnd",
value: function _getNodeAtPrefixEnd(prefix) {
var pSequence = toArray(prefix);
return pSequence.length ? this.root.getChildPrefixEnd(pSequence) : this.root;
}
}, {
key: "_getAllStartingWith",
value: function _getAllStartingWith(prefix, completeSequencesOnly) {
var suffixStartNode = this._getNodeAtPrefixEnd(prefix);
if (!suffixStartNode || this.root === suffixStartNode) {
return [];
}
var sequences = suffixStartNode.asArray(completeSequencesOnly);
for (var s = sequences.length; s--;) {
sequences[s] = prefix.concat(sequences[s]);
}
return sequences;
}
}], [{
key: "makeTrieable",
value: function makeTrieable(node, keyMap) {
var _children3;
var parentNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var t = {
data: node[keyMap.data],
parent: parentNode
};
try {
if (keyMap.isBoundary in node && node[keyMap.isBoundary] === true) {
t.isBoundary = node[keyMap.isBoundary];
}
} catch (e) {
t.data = node;
return t;
}
if (Array.isArray(keyMap.children)) {
var _children2 = [];
for (var cMap = keyMap.children, cLen = cMap.length, c = 0; c < cLen; c++) {
if (!(cMap[c] in node)) {
_children2.push({
data: null,
parent: t
});
continue;
}
try {
keyMap.data in node[cMap[c]] && _children2.push(Trie.makeTrieable(node[cMap[c]], keyMap, t));
} catch (e) {
_children2.push({
data: node[cMap[c]],
parent: t
});
}
}
if (_children2.length) {
t.children = _children2;
}
return t;
}
if (!(keyMap.children in node) || typeof node[keyMap.children] === 'undefined' || node[keyMap.children] === null) {
return t;
}
var children = node[keyMap.children];
if (typeof ((_children3 = children) === null || _children3 === void 0 ? void 0 : _children3[Symbol.iterator]) !== 'function') {
children = [children];
}
t.children = [];
for (var _cLen2 = children.length, _c2 = 0; _c2 < _cLen2; _c2++) {
t.children.push(Trie.makeTrieable(children[_c2], keyMap, t));
}
return t;
}
}]);
}();
exports["default"] = Trie;
Trie.prototype[Symbol.toStringTag] = TRIE_DESC;
var Node = /*#__PURE__*/function () {
function Node(data) {
var isEqualValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : exports.sameValueZero;
var isLessThanValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var successorData = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
var pNode = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
var isSequenceBoundary = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
_classCallCheck(this, Node);
this._data = data;
this._pNode = pNode;
this._isEqualValue = isEqualValue;
this._isLessThanValue = isLessThanValue;
this._cNodes = isLessThanValue !== null ? new SortedChildNodes(this._isEqualValue, this._isLessThanValue) : new ChronoChildNodes(this._isEqualValue);
this._isSequenceBoundary = isSequenceBoundary;
for (var dLen = successorData.length, d = 0; d < dLen; d++) {
isIterable(successorData[d]) ? this.addChild(_toConsumableArray(successorData[d])) : this.mergeTrieableNode(successorData[d]);
}
}
return _createClass(Node, [{
key: "childNodes",
get: function get() {
return this._cNodes;
}
}, {
key: "data",
get: function get() {
return this._data;
}
}, {
key: "isEmpty",
get: function get() {
return !this._countSequences(1);
}
}, {
key: "isRoot",
get: function get() {
return !this._pNode;
}
}, {
key: "isSequenceBoundary",
get: function get() {
return this._isSequenceBoundary;
},
set: function set(flag) {
this._isSequenceBoundary = flag;
}
}, {
key: "parentNode",
get: function get() {
return this._pNode;
}
}, {
key: "size",
get: function get() {
return this._countSequences();
}
}, {
key: "addChild",
value: function addChild(childData) {
if (!childData.length) {
if (!this.isRoot) {
this._isSequenceBoundary = true;
}
return;
}
var data = childData.shift();
var existingChild = this._cNodes.get(data);
existingChild !== null ? existingChild.addChild(childData) : this._cNodes.set(new Node(data, this._isEqualValue, this._isLessThanValue, [childData], this, childData.length === 0));
}
}, {
key: "asArray",
value: function asArray() {
var completeSequencesOnly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var successors = [];
var cLen = this._cNodes.size;
if (this._isSequenceBoundary || !completeSequencesOnly && !cLen) {
var path = new Array(depth);
path[depth - 1] = this._data;
successors.push(path);
}
if (!cLen) {
return successors;
}
for (var cNodes = this._cNodes.list(), c = 0; c < cLen; c++) {
var grandSuccessors = cNodes[c].asArray(completeSequencesOnly, depth + 1);
for (var gLen = grandSuccessors.length, g = 0; g < gLen; g++) {
if (!this.isRoot) {
grandSuccessors[g][depth - 1] = this._data;
}
successors.push(grandSuccessors[g]);
}
}
return successors;
}
}, {
key: "asTrieableNode",
value: function asTrieableNode() {
var parentTrieableNode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var trieableNode = {
children: [],
data: this._data,
isBoundary: this._isSequenceBoundary,
parent: parentTrieableNode
};
for (var children = this._cNodes.list(), cLen = children.length, c = 0; c < cLen; c++) {
trieableNode.children.push(children[c].asTrieableNode(trieableNode));
}
return trieableNode;
}
}, {
key: "empty",
value: function empty() {
this._cNodes.clear();
}
}, {
key: "getChildPrefixEnd",
value: function getChildPrefixEnd() {
var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var deepestInfo = this.getDeepestNodeIn(prefix);
return deepestInfo.index === prefix.length - 1 ? deepestInfo.node : null;
}
}, {
key: "getDeepestNodeIn",
value: function getDeepestNodeIn() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [],
sLen = _ref.length,
sequence = _objectWithoutProperties(_ref, _excluded);
var result = {
index: -1,
node: null
};
if (!sLen) {
return result;
}
var s = 0;
var currentNode = this;
do {
if (!currentNode.childNodes.size) {
return result;
}
currentNode = currentNode.childNodes.get(sequence[s]);
if (currentNode === null) {
return result;
}
result.index = s;
result.node = currentNode;
s++;
} while (s < sLen);
return result;
}
}, {
key: "isEqual",
value: function isEqual(graph) {
var arr = this.asArray();
var cArr = !Array.isArray(graph) ? ((0, exports.getDescriptor)(graph) === NODE_DESC ? graph : new Trie(graph)).asArray() : _toConsumableArray(graph);
if (cArr.length !== arr.length) {
return false;
}
for (var a = arr.length; a--;) {
var thisSequence = arr[a];
for (var c = cArr.length; c--;) {
var compSequence = cArr[c];
if (compSequence.length !== thisSequence.length) {
continue;
}
var found = true;
for (var i = compSequence.length; i--;) {
if (!this._isEqualValue(compSequence[i], thisSequence[i])) {
found = false;
break;
}
}
if (found) {
cArr.splice(c, 1);
break;
}
}
}
return !cArr.length;
}
}, {
key: "merge",
value: function merge(node) {
var match = this._cNodes.get(node.data);
if (match === null) {
this._cNodes.set(node);
return;
}
if (!match.isSequenceBoundary) {
match.isSequenceBoundary = node.isSequenceBoundary;
}
for (var d = 0, data = node._cNodes.list(), dLen = data.length; d < dLen; d++) {
match.merge(data[d]);
}
return;
}
}, {
key: "mergeTrieableNode",
value: function mergeTrieableNode(trieableNode) {
var match = this._cNodes.get(trieableNode.data);
if (match === null) {
this._cNodes.set(new Node(trieableNode.data, this._isEqualValue, this._isLessThanValue, trieableNode.children, this, trieableNode.isBoundary));
return;
}
if (!match.isSequenceBoundary) {
match.isSequenceBoundary = trieableNode.isBoundary;
}
for (var d = 0, data = trieableNode.children, dLen = data.length; d < dLen; d++) {
match.mergeTrieableNode(data[d]);
}
return;
}
}, {
key: "removeChild",
value: function removeChild(childData) {
var status = this._removeChild(childData);
return status === "REMOVED" || status === "UPDATED";
}
}, {
key: "_countSequences",
value: function _countSequences() {
var minCount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
value: 0
};
count.value += this._isSequenceBoundary && !this.isRoot ? 1 : 0;
for (var cNodes = this._cNodes.list(), c = cNodes.length; c--;) {
cNodes[c]._countSequences(minCount, count);
if (minCount > 0 && minCount === count.value) {
break;
}
}
return count.value;
}
}, {
key: "_removeChild",
value: function _removeChild(childData) {
var currentChildIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var currentNode = this._cNodes.get(childData[currentChildIndex]);
if (currentNode === null) {
return "NOOP";
}
if (currentChildIndex === childData.length - 1) {
if (!currentNode._isSequenceBoundary) {
return "NOOP";
}
if (currentNode._cNodes.size) {
currentNode._isSequenceBoundary = false;
return "UPDATED";
}
var siblings = currentNode._pNode._cNodes;
siblings.remove(currentNode);
return siblings.size ? "UPDATED" : "REMOVED";
}
var status = currentNode._removeChild(childData, currentChildIndex + 1);
if (status === "REMOVED") {
if (currentNode._isSequenceBoundary) {
return "UPDATED";
}
var _siblings = currentNode._pNode._cNodes;
_siblings.remove(currentNode);
if (_siblings.size) {
return "UPDATED";
}
}
return status;
}
}]);
}();
exports.Node = Node;
Node.prototype[Symbol.toStringTag] = NODE_DESC;
var ChildNodes = /*#__PURE__*/function () {
function ChildNodes(isEqualityValue) {
_classCallCheck(this, ChildNodes);
this.clear();
this.isEqualValue = isEqualityValue;
}
return _createClass(ChildNodes, [{
key: "size",
get: function get() {
return this.keys.length;
}
}, {
key: "clear",
value: function clear() {
this.codes = [];
this.keys = [];
this.buckets = [];
}
}, {
key: "get",
value: function get(key) {
var code;
if (this._optForKeyLocator(key)) {
var i = this.indexOf(key);
if (i === -1) {
return null;
}
code = this.codes[i];
}
return this._get(key, code);
}
}, {
key: "list",
value: function list() {
var nodes = [];
for (var codes = this.codes, cLen = codes.length, c = 0; c < cLen; c++) {
var bucket = this.buckets[codes[c]];
for (var b = bucket.length; b--;) {
if (bucket[b][1] !== c) {
continue;
}
nodes.push(bucket[b][0]);
break;
}
}
return nodes;
}
}, {
key: "remove",
value: function remove(node) {
var _ref2 = this._optForKeyLocator(node.data) ? this._getEntryByKeyIndex(this.indexOf(node.data)) : this._getEntry(node.data),
code = _ref2.code,
bucketIndex = _ref2.bucketIndex;
this._splice(code, bucketIndex);
}
}, {
key: "set",
value: function set(node) {
this._set(node);
}
}, {
key: "_get",
value: function _get(key) {
var code = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var _this$_getEntry = this._getEntry(key, code),
value = _this$_getEntry.value;
if (value === null) {
return null;
}
return value[0];
}
}, {
key: "_getEntry",
value: function _getEntry(key) {
var code = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
if (code === null) {
code = robustHash(key);
}
var entry = {
code: code,
value: null,
bucketIndex: -1
};
var bucket = this.buckets[code];
if (typeof bucket === 'undefined') {
return entry;
}
for (var b = bucket.length; b--;) {
if (this.isEqualValue(key, bucket[b][0].data)) {
entry.bucketIndex = b;
entry.value = bucket[b];
return entry;
}
}
return entry;
}
}, {
key: "_getEntryByKeyIndex",
value: function _getEntryByKeyIndex(i) {
if (i === -1) {
return;
}
var key = this.keys[i];
var code = this.codes[i];
return this._getEntry(key, code);
}
}, {
key: "_set",
value: function _set(node) {
var code = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var key = node.data;
var _this$_getEntry2 = this._getEntry(key, code),
_code = _this$_getEntry2.code,
value = _this$_getEntry2.value;
if (value !== null) {
return;
}
this._splice(_code, node);
}
}, {
key: "_splice",
value: function _splice(a, b) {
var i = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
if (typeof b === 'number') {
if (b < 0 || b > this.size - 1) {
return;
}
i = this.buckets[a][b][1];
this.buckets[a].splice(b, 1);
this.codes.splice(i, 1);
this.keys.splice(i, 1);
return this._syncBuckets(i);
}
if ((0, exports.getDescriptor)(b) !== NODE_DESC) {
return;
}
var size = this.size;
i = i < 0 || i > size ? size : i;
if (typeof this.buckets[a] === 'undefined') {
this.buckets[a] = [[b, i]];
} else {
this.buckets[a].push([b, i]);
}
this.codes.splice(i, 0, a);
this.keys.splice(i, 0, b.data);
this._syncBuckets(i + 1);
}
}, {
key: "_syncBuckets",
value: function _syncBuckets() {
var startKeyIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
for (var codes = this.codes, keys = this.keys, cLen = codes.length, c = startKeyIndex; c < cLen; c++) {
var _this$_getEntry3 = this._getEntry(keys[c], codes[c]),
code = _this$_getEntry3.code,
bucketIndex = _this$_getEntry3.bucketIndex;
this.buckets[code][bucketIndex][1] = c;
}
}
}]);
}();
exports.ChildNodes = ChildNodes;
var ChronoChildNodes = /*#__PURE__*/function (_ChildNodes) {
function ChronoChildNodes(isEqualValue) {
_classCallCheck(this, ChronoChildNodes);
return _callSuper(this, ChronoChildNodes, [isEqualValue]);
}
_inherits(ChronoChildNodes, _ChildNodes);
return _createClass(ChronoChildNodes, [{
key: "indexOf",
value: function indexOf(key) {
for (var k = this.keys.length; k--;) {
if (this.isEqualValue(key, this.keys[k])) {
return k;
}
}
return -1;
}
}, {
key: "set",
value: function set(node) {
this._optForKeyLocator(node.data) && this.indexOf(node.data) !== -1 || _superPropGet(ChronoChildNodes, "set", this, 3)([node]);
}
}, {
key: "_optForKeyLocator",
value: function _optForKeyLocator(key) {
return _typeof(key) === 'object' && Object.keys(key).length < this.keys.length;
}
}]);
}(ChildNodes);
var SortedChildNodes = /*#__PURE__*/function (_ChildNodes2) {
function SortedChildNodes(isEqualValue, isLessThanValue) {
var _this;
_classCallCheck(this, SortedChildNodes);
_this = _callSuper(this, SortedChildNodes, [isEqualValue]);
_this._keyComparator = null;
_this._isLessThanValue = isLessThanValue;
return _this;
}
_inherits(SortedChildNodes, _ChildNodes2);
return _createClass(SortedChildNodes, [{
key: "indexOf",
value: function indexOf(key) {
var t = this._getClosestKeyIndex(key);
return t.desc === 0 ? t.index : -1;
}
}, {
key: "set",
value: function set(node) {
var _this$_getClosestKeyI = this._getClosestKeyIndex(node.data),
desc = _this$_getClosestKeyI.desc,
index = _this$_getClosestKeyI.index;
if (desc === 0) {
return;
}
if (desc === -1) {
index += 1;
}
this._splice(robustHash(node.data), node, index);
}
}, {
key: "_getClosestKeyIndex",
value: function _getClosestKeyIndex(key) {
if (this._keyComparator === null) {
this._keyComparator = this._compareKeys.bind(this);
}
return bSearch(key, this.keys, this._keyComparator);
}
}, {
key: "_compareKeys",
value: function _compareKeys(keyA, keyB) {
if (this.isEqualValue(keyA, keyB)) {
return 0;
}
if (this._isLessThanValue(keyA, keyB)) {
return -1;
}
return 1;
}
}, {
key: "_optForKeyLocator",
value: function _optForKeyLocator(key) {
return _typeof(key) === 'object';
}
}]);
}(ChildNodes);
function robustHash(key) {
return Math.abs(runHash(key));
}
function runHash(key) {
var visited = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
if (key === null) {
return 0;
}
switch (_typeof(key)) {
case 'string':
return stringHash(key);
case 'number':
return key;
case 'boolean':
return key ? 1 : 0;
case 'function':
return stringHash(key.toString());
case 'undefined':
return 0;
case 'symbol':
return stringHash(key.description);
}
{
var _key = key;
if ('hashCode' in _key) {
return runHash(typeof _key.hashCode === 'function' ? _key.hashCode() : _key.hashCode);
}
}
var _bSearch = bSearch(key, visited),
desc = _bSearch.desc,
index = _bSearch.index;
if (desc === 0) {
return 0;
}
visited.splice(index + (desc === -1 ? 1 : 0), 0, key);
var hash = 0;
if (Array.isArray(key)) {
for (var k = key.length; k--;) {
hash += runHash(key[k], visited);
}
return hash;
}
for (var keys = Object.keys(key).sort(), _k = keys.length; _k--;) {
if (keys[_k] === 'hashCode') {
continue;
}
hash += runHash(key[keys[_k]], visited);
}
return hash;
}
function stringHash(key) {
var hash = 0;
for (var k = key.length; k--;) {
hash = hash * 31 + key.charCodeAt(k) | 0;
}
return hash;
}
;
function bSearch(needle, haystack) {
var compare = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultComparator;
var startIndex = 0;
var endIndex = haystack.length - 1;
var res = {
index: endIndex,
desc: 1
};
while (startIndex <= endIndex) {
res.index = Math.floor((startIndex + endIndex) / 2);
var midValue = haystack[res.index];
res.desc = compare(midValue, needle);
if (res.desc === 0) {
break;
}
if (res.desc === -1) {
startIndex = res.index + 1;
continue;
}
endIndex = res.index - 1;
}
return res;
}
function defaultComparator(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
function isIterable(sequence) {
if (sequence === null) {
return false;
}
if (typeof sequence[Symbol.iterator] === 'function') {
return true;
}
var type = (0, exports.getDescriptor)(sequence);
return type === 'Array' || type === 'String';
}
function toArray(sequence) {
return Array.isArray(sequence) ? sequence : _toConsumableArray(sequence);
}