Advertisement
pram

Javascript Map Implementation

Feb 26th, 2013
395
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function Map(storageId) {
  2.     this.current = undefined;
  3.     this.size = 0;
  4.     this.storageId = storageId;
  5.     if (this.storageId) {
  6.         this.keys = new Array();
  7.         this.disableLinking();
  8.     }
  9. }
  10.  
  11. Map.noop = function() {
  12.     return this;
  13. };
  14.  
  15. Map.illegal = function() {
  16.     throw new Error("illegal operation for maps without linking");
  17. };
  18.  
  19. // map initialisation from existing object
  20. // doesn't add inherited properties if not explicitly instructed to:
  21. // omitting foreignKeys means foreignKeys === undefined, i.e. == false
  22. // --> inherited properties won't be added
  23. Map.from = function(obj, foreignKeys) {
  24.     var map = new Map;
  25.     for(var prop in obj) {
  26.         if(foreignKeys || obj.hasOwnProperty(prop))
  27.             map.put(prop, obj[prop]);
  28.     }
  29.     return map;
  30. };
  31.  
  32. Map.prototype.disableLinking = function() {
  33.     this.link = Map.noop;
  34.     this.unlink = Map.noop;
  35.     this.disableLinking = Map.noop;
  36.  
  37.     this.next = Map.illegal;
  38.     this.key = Map.illegal;
  39.     this.value = Map.illegal;
  40. //    this.removeAll = Map.illegal;
  41.  
  42.  
  43.     return this;
  44. };
  45.  
  46. // overwrite in Map instance if necessary
  47. Map.prototype.hash = function(value) {
  48.     return (typeof value) + ' ' + (value instanceof Object ?
  49.         (value.__hash || (value.__hash = ++arguments.callee.current)) :
  50.         value.toString());
  51. };
  52.  
  53. Map.prototype.hash.current = 0;
  54.  
  55. // --- mapping functions
  56.  
  57. Map.prototype.get = function(key) {
  58.     var item = this[this.hash(key)];
  59.     if (item === undefined) {
  60.         if (this.storageId) {
  61.             try {
  62.                 var itemStr = localStorage.getItem(this.storageId + key);
  63.                 if (itemStr && itemStr !== 'undefined') {
  64.                     item = JSON.parse(itemStr);
  65.                     this[this.hash(key)] = item;
  66.                     this.keys.push(key);
  67.                     ++this.size;
  68.                 }
  69.             } catch (e) {
  70.                 printObject(e);
  71.             }
  72.         }
  73.     }
  74.     return item === undefined ? undefined : item.value;
  75. };
  76.  
  77. Map.prototype.put = function(key, value) {
  78.     var hash = this.hash(key);
  79.  
  80.     if(this[hash] === undefined) {
  81.         var item = { key : key, value : value };
  82.         this[hash] = item;
  83.  
  84.         this.link(item);
  85.         ++this.size;
  86.     }
  87.     else this[hash].value = value;
  88.     if (this.storageId) {
  89.         this.keys.push(key);
  90.         try {
  91.             localStorage.setItem(this.storageId + key, JSON.stringify(this[hash]));
  92.         } catch (e) {
  93.             printObject(e);
  94.         }
  95.     }
  96.     return this;
  97. };
  98.  
  99. Map.prototype.remove = function(key) {
  100.     var hash = this.hash(key);
  101.     var item = this[hash];
  102.     if(item !== undefined) {
  103.         --this.size;
  104.         this.unlink(item);
  105.  
  106.         delete this[hash];
  107.     }
  108.     if (this.storageId) {
  109.         try {
  110.             localStorage.setItem(this.storageId + key, undefined);
  111.         } catch (e) {
  112.             printObject(e);
  113.         }
  114.     }
  115.     return this;
  116. };
  117.  
  118. // only works if linked
  119. Map.prototype.removeAll = function() {
  120.     if (this.storageId) {
  121.         for (var i=0; i<this.keys.length; i++) {
  122.             this.remove(this.keys[i]);
  123.         }
  124.         this.keys.length = 0;
  125.     } else {
  126.         while(this.size)
  127.             this.remove(this.key());
  128.     }
  129.     return this;
  130. };
  131.  
  132. // --- linked list helper functions
  133.  
  134. Map.prototype.link = function(item) {
  135.     if (this.storageId) {
  136.         return;
  137.     }
  138.     if(this.size == 0) {
  139.         item.prev = item;
  140.         item.next = item;
  141.         this.current = item;
  142.     }
  143.     else {
  144.         item.prev = this.current.prev;
  145.         item.prev.next = item;
  146.         item.next = this.current;
  147.         this.current.prev = item;
  148.     }
  149. };
  150.  
  151. Map.prototype.unlink = function(item) {
  152.     if (this.storageId) {
  153.         return;
  154.     }
  155.     if(this.size == 0)
  156.         this.current = undefined;
  157.     else {
  158.         item.prev.next = item.next;
  159.         item.next.prev = item.prev;
  160.         if(item === this.current)
  161.             this.current = item.next;
  162.     }
  163. };
  164.  
  165. // --- iterator functions - only work if map is linked
  166.  
  167. Map.prototype.next = function() {
  168.     this.current = this.current.next;
  169. };
  170.  
  171. Map.prototype.key = function() {
  172.     if (this.storageId) {
  173.         return undefined;
  174.     } else {
  175.         return this.current.key;
  176.     }
  177. };
  178.  
  179. Map.prototype.value = function() {
  180.     if (this.storageId) {
  181.         return undefined;
  182.     }
  183.     return this.current.value;
  184. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement