strictly-hash
Version:
A strict Hash implementation allowing key restriction and virtualization
230 lines (225 loc) • 6.24 kB
JavaScript
// Generated by CoffeeScript 1.10.0
var global;
global = typeof exports !== "undefined" && exports !== null ? exports : window;
global.Hash = (function() {
'use strict';
function Hash(_o, restrict_keys, restrict_values) {
var _kinds, escapeKey, i, key, len, object, ref, unescapeKey, validValue;
if (_o == null) {
_o = {};
}
if (restrict_keys == null) {
restrict_keys = [];
}
if (restrict_values == null) {
restrict_values = {};
}
object = {};
escapeKey = function(key) {
if (key.length > 2 && key.charCodeAt(0) === 95 && key.charCodeAt(1) === 95) {
return key + "%";
} else {
return "" + key;
}
};
unescapeKey = function(key) {
if (key.length > 2 && key.charCodeAt(0) === 95 && key.charCodeAt(1) === 95) {
return "" + (key.substr(0, key.length - 1));
} else {
return "" + key;
}
};
_kinds = {
Array: Array,
Boolean: Boolean,
Number: Number,
Object: Object,
String: String
};
validValue = function(val, restrict) {
if (typeof restrict === 'string') {
if (restrict.match(/^(typeof|cast)+:+/)) {
return typeof val === (restrict.split(':')[1] || "").toLowerCase();
} else {
return val === restrict;
}
} else {
if (typeof restrict === 'object' && restrict.length) {
return 0 <= restrict.indexOf(val);
}
}
return false;
};
this.get = (function(_this) {
return function(key) {
return object[escapeKey(key)];
};
})(this);
this.set = (function(_this) {
return function(key, value) {
var k, kind, v;
if (typeof key === 'string') {
if (restrict_keys.length && 0 > restrict_keys.indexOf(key)) {
return _this;
}
if (restrict_values.hasOwnProperty(key)) {
if (restrict_values[key].match(/^cast:+/)) {
kind = restrict_values[key].split(':')[1];
if (!_kinds[kind]) {
return _this;
}
value = _kinds[kind](value);
}
if (restrict_values[key].match(/^class:+/)) {
kind = restrict_values[key].split(':')[1];
if (!(function() {
return new Function("return typeof " + kind + " === 'function';");
})(kind)) {
return _this;
}
value = (new Function('value', "return new " + kind + "(value);"))(value);
}
if (!validValue(value, restrict_values[key])) {
return _this;
}
}
object[escapeKey(key)] = value;
} else if (typeof key === 'object') {
for (k in key) {
v = key[k];
_this.set(k, v);
}
}
return _this;
};
})(this);
ref = Object.keys(_o);
for (i = 0, len = ref.length; i < len; i++) {
key = ref[i];
this.set(key, _o[key]);
}
this.has = (function(_this) {
return function(key) {
return object.hasOwnProperty(escapeKey(key));
};
})(this);
this.del = (function(_this) {
return function(key) {
if (_this.has(key)) {
return delete object[escapeKey(key)];
}
};
})(this);
this.forEach = (function(_this) {
return function(iterator, scope) {
var _results;
_results = [];
for (key in object) {
if (!object.hasOwnProperty(key)) {
continue;
}
_results.push(iterator.call(scope, object[key], unescapeKey(key)));
}
return _results;
};
})(this);
this.keys = (function(_this) {
return function() {
var keys;
keys = [];
_this.forEach(function(value, key) {
return keys.push(key);
});
return keys;
};
})(this);
this.valueOf = (function(_this) {
return function() {
return object;
};
})(this);
this.toJSON = (function(_this) {
return function() {
return object;
};
})(this);
this.toString = (function(_this) {
return function(pretty) {
if (pretty == null) {
pretty = false;
}
return JSON.stringify(_this.toJSON(), null, (pretty ? 2 : void 0));
};
})(this);
this.canFreeze = (function(_this) {
return function() {
return typeof Object.freeze === 'function';
};
})(this);
this.freeze = (function(_this) {
return function() {
if (_this.canFreeze()) {
Object.freeze(_this);
Object.freeze(object);
}
return _this;
};
})(this);
this.isFrozen = (function(_this) {
return function() {
if (_this.canFreeze()) {
return Object.isFrozen(object);
} else {
return false;
}
};
})(this);
this.canSeal = (function(_this) {
return function() {
return typeof Object.seal === 'function';
};
})(this);
this.seal = (function(_this) {
return function() {
if (_this.canSeal()) {
Object.seal(_this);
Object.seal(object);
}
return _this;
};
})(this);
this.isSealed = (function(_this) {
return function() {
if (_this.canSeal()) {
return Object.isSealed(object);
} else {
return false;
}
};
})(this);
this.canPreventExtensions = (function(_this) {
return function() {
return typeof Object.preventExtensions === 'function';
};
})(this);
this.isExtensible = (function(_this) {
return function() {
if (_this.canPreventExtensions()) {
return Object.isExtensible(object);
} else {
return true;
}
};
})(this);
this.preventExtensions = (function(_this) {
return function() {
if (_this.canPreventExtensions()) {
Object.preventExtensions(_this);
Object.preventExtensions(object);
}
return _this;
};
})(this);
}
return Hash;
})();