Skip to content

Commit

Permalink
1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Baker committed Jan 31, 2018
1 parent 0cdd82f commit 28d365e
Show file tree
Hide file tree
Showing 3 changed files with 668 additions and 0 deletions.
180 changes: 180 additions & 0 deletions dist/amd/can-key-tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*can-key-tree@1.0.0#can-key-tree*/
define([
'require',
'exports',
'module',
'can-reflect'
], function (require, exports, module) {
var reflect = require('can-reflect');
function isBuiltInPrototype(obj) {
if (obj === Object.prototype) {
return true;
}
var protoString = Object.prototype.toString.call(obj);
var isNotObjObj = protoString !== '[object Object]';
var isObjSomething = protoString.indexOf('[object ') !== -1;
return isNotObjObj && isObjSomething;
}
function getDeepSize(root, level) {
if (level === 0) {
return reflect.size(root);
} else if (reflect.size(root) === 0) {
return 0;
} else {
var count = 0;
reflect.each(root, function (value) {
count += getDeepSize(value, level - 1);
});
return count;
}
}
function getDeep(node, items, depth, maxDepth) {
if (!node) {
return;
}
if (maxDepth === depth) {
if (reflect.isMoreListLikeThanMapLike(node)) {
reflect.addValues(items, reflect.toArray(node));
} else {
throw new Error('can-key-tree: Map-type leaf containers are not supported yet.');
}
} else {
reflect.each(node, function (value) {
getDeep(value, items, depth + 1, maxDepth);
});
}
}
function clearDeep(node, keys, maxDepth, deleteHandler) {
if (maxDepth === keys.length) {
if (reflect.isMoreListLikeThanMapLike(node)) {
var valuesToRemove = reflect.toArray(node);
if (deleteHandler) {
valuesToRemove.forEach(function (value) {
deleteHandler.apply(null, keys.concat(value));
});
}
reflect.removeValues(node, valuesToRemove);
} else {
throw new Error('can-key-tree: Map-type leaf containers are not supported yet.');
}
} else {
reflect.each(node, function (value, key) {
clearDeep(value, keys.concat(key), maxDepth, deleteHandler);
reflect.deleteKeyValue(node, key);
});
}
}
var KeyTree = function (treeStructure, callbacks) {
this.callbacks = callbacks || {};
this.treeStructure = treeStructure;
var FirstConstructor = treeStructure[0];
if (reflect.isConstructorLike(FirstConstructor)) {
this.root = new FirstConstructor();
} else {
this.root = FirstConstructor;
}
};
reflect.assign(KeyTree.prototype, {
add: function (keys) {
if (keys.length > this.treeStructure.length) {
throw new Error('can-key-tree: Can not add path deeper than tree.');
}
var place = this.root;
var rootWasEmpty = reflect.size(this.root) === 0;
for (var i = 0; i < keys.length - 1; i++) {
var key = keys[i];
var childNode = reflect.getKeyValue(place, key);
if (!childNode) {
var Constructor = this.treeStructure[i + 1];
if (isBuiltInPrototype(Constructor.prototype)) {
childNode = new Constructor();
} else {
childNode = new Constructor(key);
}
reflect.setKeyValue(place, key, childNode);
}
place = childNode;
}
if (reflect.isMoreListLikeThanMapLike(place)) {
reflect.addValues(place, [keys[keys.length - 1]]);
} else {
throw new Error('can-key-tree: Map types are not supported yet.');
}
if (rootWasEmpty && this.callbacks.onFirst) {
this.callbacks.onFirst.call(this);
}
return this;
},
getNode: function (keys) {
var node = this.root;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
node = reflect.getKeyValue(node, key);
if (!node) {
return;
}
}
return node;
},
get: function (keys) {
var node = this.getNode(keys);
if (this.treeStructure.length === keys.length) {
return node;
} else {
var Type = this.treeStructure[this.treeStructure.length - 1];
var items = new Type();
getDeep(node, items, keys.length, this.treeStructure.length - 1);
return items;
}
},
delete: function (keys, deleteHandler) {
var parentNode = this.root, path = [this.root], lastKey = keys[keys.length - 1];
for (var i = 0; i < keys.length - 1; i++) {
var key = keys[i];
var childNode = reflect.getKeyValue(parentNode, key);
if (childNode === undefined) {
return false;
} else {
path.push(childNode);
}
parentNode = childNode;
}
if (!keys.length) {
clearDeep(parentNode, [], this.treeStructure.length - 1, deleteHandler);
} else if (keys.length === this.treeStructure.length) {
if (reflect.isMoreListLikeThanMapLike(parentNode)) {
if (deleteHandler) {
deleteHandler.apply(null, keys.concat(lastKey));
}
reflect.removeValues(parentNode, [lastKey]);
} else {
throw new Error('can-key-tree: Map types are not supported yet.');
}
} else {
var nodeToRemove = reflect.getKeyValue(parentNode, lastKey);
if (nodeToRemove !== undefined) {
clearDeep(nodeToRemove, keys, this.treeStructure.length - 1, deleteHandler);
reflect.deleteKeyValue(parentNode, lastKey);
} else {
return false;
}
}
for (i = path.length - 2; i >= 0; i--) {
if (reflect.size(parentNode) === 0) {
parentNode = path[i];
reflect.deleteKeyValue(parentNode, keys[i]);
} else {
break;
}
}
if (this.callbacks.onEmpty && reflect.size(this.root) === 0) {
this.callbacks.onEmpty.call(this);
}
return true;
},
size: function () {
return getDeepSize(this.root, this.treeStructure.length - 1);
}
});
module.exports = KeyTree;
});
173 changes: 173 additions & 0 deletions dist/cjs/can-key-tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*can-key-tree@1.0.0#can-key-tree*/
var reflect = require('can-reflect');
function isBuiltInPrototype(obj) {
if (obj === Object.prototype) {
return true;
}
var protoString = Object.prototype.toString.call(obj);
var isNotObjObj = protoString !== '[object Object]';
var isObjSomething = protoString.indexOf('[object ') !== -1;
return isNotObjObj && isObjSomething;
}
function getDeepSize(root, level) {
if (level === 0) {
return reflect.size(root);
} else if (reflect.size(root) === 0) {
return 0;
} else {
var count = 0;
reflect.each(root, function (value) {
count += getDeepSize(value, level - 1);
});
return count;
}
}
function getDeep(node, items, depth, maxDepth) {
if (!node) {
return;
}
if (maxDepth === depth) {
if (reflect.isMoreListLikeThanMapLike(node)) {
reflect.addValues(items, reflect.toArray(node));
} else {
throw new Error('can-key-tree: Map-type leaf containers are not supported yet.');
}
} else {
reflect.each(node, function (value) {
getDeep(value, items, depth + 1, maxDepth);
});
}
}
function clearDeep(node, keys, maxDepth, deleteHandler) {
if (maxDepth === keys.length) {
if (reflect.isMoreListLikeThanMapLike(node)) {
var valuesToRemove = reflect.toArray(node);
if (deleteHandler) {
valuesToRemove.forEach(function (value) {
deleteHandler.apply(null, keys.concat(value));
});
}
reflect.removeValues(node, valuesToRemove);
} else {
throw new Error('can-key-tree: Map-type leaf containers are not supported yet.');
}
} else {
reflect.each(node, function (value, key) {
clearDeep(value, keys.concat(key), maxDepth, deleteHandler);
reflect.deleteKeyValue(node, key);
});
}
}
var KeyTree = function (treeStructure, callbacks) {
this.callbacks = callbacks || {};
this.treeStructure = treeStructure;
var FirstConstructor = treeStructure[0];
if (reflect.isConstructorLike(FirstConstructor)) {
this.root = new FirstConstructor();
} else {
this.root = FirstConstructor;
}
};
reflect.assign(KeyTree.prototype, {
add: function (keys) {
if (keys.length > this.treeStructure.length) {
throw new Error('can-key-tree: Can not add path deeper than tree.');
}
var place = this.root;
var rootWasEmpty = reflect.size(this.root) === 0;
for (var i = 0; i < keys.length - 1; i++) {
var key = keys[i];
var childNode = reflect.getKeyValue(place, key);
if (!childNode) {
var Constructor = this.treeStructure[i + 1];
if (isBuiltInPrototype(Constructor.prototype)) {
childNode = new Constructor();
} else {
childNode = new Constructor(key);
}
reflect.setKeyValue(place, key, childNode);
}
place = childNode;
}
if (reflect.isMoreListLikeThanMapLike(place)) {
reflect.addValues(place, [keys[keys.length - 1]]);
} else {
throw new Error('can-key-tree: Map types are not supported yet.');
}
if (rootWasEmpty && this.callbacks.onFirst) {
this.callbacks.onFirst.call(this);
}
return this;
},
getNode: function (keys) {
var node = this.root;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
node = reflect.getKeyValue(node, key);
if (!node) {
return;
}
}
return node;
},
get: function (keys) {
var node = this.getNode(keys);
if (this.treeStructure.length === keys.length) {
return node;
} else {
var Type = this.treeStructure[this.treeStructure.length - 1];
var items = new Type();
getDeep(node, items, keys.length, this.treeStructure.length - 1);
return items;
}
},
delete: function (keys, deleteHandler) {
var parentNode = this.root, path = [this.root], lastKey = keys[keys.length - 1];
for (var i = 0; i < keys.length - 1; i++) {
var key = keys[i];
var childNode = reflect.getKeyValue(parentNode, key);
if (childNode === undefined) {
return false;
} else {
path.push(childNode);
}
parentNode = childNode;
}
if (!keys.length) {
clearDeep(parentNode, [], this.treeStructure.length - 1, deleteHandler);
} else if (keys.length === this.treeStructure.length) {
if (reflect.isMoreListLikeThanMapLike(parentNode)) {
if (deleteHandler) {
deleteHandler.apply(null, keys.concat(lastKey));
}
reflect.removeValues(parentNode, [lastKey]);
} else {
throw new Error('can-key-tree: Map types are not supported yet.');
}
} else {
var nodeToRemove = reflect.getKeyValue(parentNode, lastKey);
if (nodeToRemove !== undefined) {
clearDeep(nodeToRemove, keys, this.treeStructure.length - 1, deleteHandler);
reflect.deleteKeyValue(parentNode, lastKey);
} else {
return false;
}
}
for (i = path.length - 2; i >= 0; i--) {
if (reflect.size(parentNode) === 0) {
parentNode = path[i];
reflect.deleteKeyValue(parentNode, keys[i]);
} else {
break;
}
}
if (this.callbacks.onEmpty && reflect.size(this.root) === 0) {
this.callbacks.onEmpty.call(this);
}
return true;
},
size: function () {
return getDeepSize(this.root, this.treeStructure.length - 1);
}
});
module.exports = KeyTree;
Loading

0 comments on commit 28d365e

Please sign in to comment.