| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 | 
							- // stringmap.js
 
- // MIT licensed, see LICENSE file
 
- // Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
 
- var StringMap = (function() {
 
-     "use strict";
 
-     // to save us a few characters
 
-     var hasOwnProperty = Object.prototype.hasOwnProperty;
 
-     var create = (function() {
 
-         function hasOwnEnumerableProps(obj) {
 
-             for (var prop in obj) {
 
-                 if (hasOwnProperty.call(obj, prop)) {
 
-                     return true;
 
-                 }
 
-             }
 
-             return false;
 
-         }
 
-         // FF <= 3.6:
 
-         // o = {}; o.hasOwnProperty("__proto__" or "__count__" or "__parent__") => true
 
-         // o = {"__proto__": null}; Object.prototype.hasOwnProperty.call(o, "__proto__" or "__count__" or "__parent__") => false
 
-         function hasOwnPollutedProps(obj) {
 
-             return hasOwnProperty.call(obj, "__count__") || hasOwnProperty.call(obj, "__parent__");
 
-         }
 
-         var useObjectCreate = false;
 
-         if (typeof Object.create === "function") {
 
-             if (!hasOwnEnumerableProps(Object.create(null))) {
 
-                 useObjectCreate = true;
 
-             }
 
-         }
 
-         if (useObjectCreate === false) {
 
-             if (hasOwnEnumerableProps({})) {
 
-                 throw new Error("StringMap environment error 0, please file a bug at https://github.com/olov/stringmap/issues");
 
-             }
 
-         }
 
-         // no throw yet means we can create objects without own enumerable props (safe-guard against VMs and shims)
 
-         var o = (useObjectCreate ? Object.create(null) : {});
 
-         var useProtoClear = false;
 
-         if (hasOwnPollutedProps(o)) {
 
-             o.__proto__ = null;
 
-             if (hasOwnEnumerableProps(o) || hasOwnPollutedProps(o)) {
 
-                 throw new Error("StringMap environment error 1, please file a bug at https://github.com/olov/stringmap/issues");
 
-             }
 
-             useProtoClear = true;
 
-         }
 
-         // no throw yet means we can create objects without own polluted props (safe-guard against VMs and shims)
 
-         return function() {
 
-             var o = (useObjectCreate ? Object.create(null) : {});
 
-             if (useProtoClear) {
 
-                 o.__proto__ = null;
 
-             }
 
-             return o;
 
-         };
 
-     })();
 
-     // stringmap ctor
 
-     function stringmap(optional_object) {
 
-         // use with or without new
 
-         if (!(this instanceof stringmap)) {
 
-             return new stringmap(optional_object);
 
-         }
 
-         this.obj = create();
 
-         this.hasProto = false; // false (no __proto__ key) or true (has __proto__ key)
 
-         this.proto = undefined; // value for __proto__ key when hasProto is true, undefined otherwise
 
-         if (optional_object) {
 
-             this.setMany(optional_object);
 
-         }
 
-     };
 
-     // primitive methods that deals with data representation
 
-     stringmap.prototype.has = function(key) {
 
-         // The type-check of key in has, get, set and delete is important because otherwise an object
 
-         // {toString: function() { return "__proto__"; }} can avoid the key === "__proto__" test.
 
-         // The alternative to type-checking would be to force string conversion, i.e. key = String(key);
 
-         if (typeof key !== "string") {
 
-             throw new Error("StringMap expected string key");
 
-         }
 
-         return (key === "__proto__" ?
 
-             this.hasProto :
 
-             hasOwnProperty.call(this.obj, key));
 
-     };
 
-     stringmap.prototype.get = function(key) {
 
-         if (typeof key !== "string") {
 
-             throw new Error("StringMap expected string key");
 
-         }
 
-         return (key === "__proto__" ?
 
-             this.proto :
 
-             (hasOwnProperty.call(this.obj, key) ? this.obj[key] : undefined));
 
-     };
 
-     stringmap.prototype.set = function(key, value) {
 
-         if (typeof key !== "string") {
 
-             throw new Error("StringMap expected string key");
 
-         }
 
-         if (key === "__proto__") {
 
-             this.hasProto = true;
 
-             this.proto = value;
 
-         } else {
 
-             this.obj[key] = value;
 
-         }
 
-     };
 
-     stringmap.prototype.remove = function(key) {
 
-         if (typeof key !== "string") {
 
-             throw new Error("StringMap expected string key");
 
-         }
 
-         var didExist = this.has(key);
 
-         if (key === "__proto__") {
 
-             this.hasProto = false;
 
-             this.proto = undefined;
 
-         } else {
 
-             delete this.obj[key];
 
-         }
 
-         return didExist;
 
-     };
 
-     // alias remove to delete but beware:
 
-     // sm.delete("key"); // OK in ES5 and later
 
-     // sm['delete']("key"); // OK in all ES versions
 
-     // sm.remove("key"); // OK in all ES versions
 
-     stringmap.prototype['delete'] = stringmap.prototype.remove;
 
-     stringmap.prototype.isEmpty = function() {
 
-         for (var key in this.obj) {
 
-             if (hasOwnProperty.call(this.obj, key)) {
 
-                 return false;
 
-             }
 
-         }
 
-         return !this.hasProto;
 
-     };
 
-     stringmap.prototype.size = function() {
 
-         var len = 0;
 
-         for (var key in this.obj) {
 
-             if (hasOwnProperty.call(this.obj, key)) {
 
-                 ++len;
 
-             }
 
-         }
 
-         return (this.hasProto ? len + 1 : len);
 
-     };
 
-     stringmap.prototype.keys = function() {
 
-         var keys = [];
 
-         for (var key in this.obj) {
 
-             if (hasOwnProperty.call(this.obj, key)) {
 
-                 keys.push(key);
 
-             }
 
-         }
 
-         if (this.hasProto) {
 
-             keys.push("__proto__");
 
-         }
 
-         return keys;
 
-     };
 
-     stringmap.prototype.values = function() {
 
-         var values = [];
 
-         for (var key in this.obj) {
 
-             if (hasOwnProperty.call(this.obj, key)) {
 
-                 values.push(this.obj[key]);
 
-             }
 
-         }
 
-         if (this.hasProto) {
 
-             values.push(this.proto);
 
-         }
 
-         return values;
 
-     };
 
-     stringmap.prototype.items = function() {
 
-         var items = [];
 
-         for (var key in this.obj) {
 
-             if (hasOwnProperty.call(this.obj, key)) {
 
-                 items.push([key, this.obj[key]]);
 
-             }
 
-         }
 
-         if (this.hasProto) {
 
-             items.push(["__proto__", this.proto]);
 
-         }
 
-         return items;
 
-     };
 
-     // methods that rely on the above primitives
 
-     stringmap.prototype.setMany = function(object) {
 
-         if (object === null || (typeof object !== "object" && typeof object !== "function")) {
 
-             throw new Error("StringMap expected Object");
 
-         }
 
-         for (var key in object) {
 
-             if (hasOwnProperty.call(object, key)) {
 
-                 this.set(key, object[key]);
 
-             }
 
-         }
 
-         return this;
 
-     };
 
-     stringmap.prototype.merge = function(other) {
 
-         var keys = other.keys();
 
-         for (var i = 0; i < keys.length; i++) {
 
-             var key = keys[i];
 
-             this.set(key, other.get(key));
 
-         }
 
-         return this;
 
-     };
 
-     stringmap.prototype.map = function(fn) {
 
-         var keys = this.keys();
 
-         for (var i = 0; i < keys.length; i++) {
 
-             var key = keys[i];
 
-             keys[i] = fn(this.get(key), key); // re-use keys array for results
 
-         }
 
-         return keys;
 
-     };
 
-     stringmap.prototype.forEach = function(fn) {
 
-         var keys = this.keys();
 
-         for (var i = 0; i < keys.length; i++) {
 
-             var key = keys[i];
 
-             fn(this.get(key), key);
 
-         }
 
-     };
 
-     stringmap.prototype.clone = function() {
 
-         var other = stringmap();
 
-         return other.merge(this);
 
-     };
 
-     stringmap.prototype.toString = function() {
 
-         var self = this;
 
-         return "{" + this.keys().map(function(key) {
 
-             return JSON.stringify(key) + ":" + JSON.stringify(self.get(key));
 
-         }).join(",") + "}";
 
-     };
 
-     return stringmap;
 
- })();
 
- if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
 
-     module.exports = StringMap;
 
- }
 
 
  |