117 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			117 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | /** | ||
|  |  * Module dependencies. | ||
|  |  */ | ||
|  | 
 | ||
|  | var crypto = require('crypto') | ||
|  |   , nodes = require('../nodes'); | ||
|  | 
 | ||
|  | var MemoryCache = module.exports = function(options) { | ||
|  |   options = options || {}; | ||
|  |   this.limit = options['cache limit'] || 256; | ||
|  |   this._cache = {}; | ||
|  |   this.length = 0; | ||
|  |   this.head = this.tail = null; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Set cache item with given `key` to `value`. | ||
|  |  * | ||
|  |  * @param {String} key | ||
|  |  * @param {Object} value | ||
|  |  * @api private | ||
|  |  */ | ||
|  | 
 | ||
|  | MemoryCache.prototype.set = function(key, value) { | ||
|  |   var clone = value.clone() | ||
|  |     , item; | ||
|  | 
 | ||
|  |   clone.filename = nodes.filename; | ||
|  |   clone.lineno = nodes.lineno; | ||
|  |   clone.column = nodes.column; | ||
|  |   item = { key: key, value: clone }; | ||
|  |   this._cache[key] = item; | ||
|  | 
 | ||
|  |   if (this.tail) { | ||
|  |     this.tail.next = item; | ||
|  |     item.prev = this.tail; | ||
|  |   } else { | ||
|  |     this.head = item; | ||
|  |   } | ||
|  | 
 | ||
|  |   this.tail = item; | ||
|  |   if (this.length++ == this.limit) this.purge(); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Get cache item with given `key`. | ||
|  |  * | ||
|  |  * @param {String} key | ||
|  |  * @return {Object} | ||
|  |  * @api private | ||
|  |  */ | ||
|  | 
 | ||
|  | MemoryCache.prototype.get = function(key) { | ||
|  |   var item = this._cache[key] | ||
|  |     , val = item.value.clone(); | ||
|  | 
 | ||
|  |   if (item == this.tail) return val; | ||
|  |   if (item.next) { | ||
|  |     if (item == this.head) this.head = item.next; | ||
|  |     item.next.prev = item.prev; | ||
|  |   } | ||
|  |   if (item.prev) item.prev.next = item.next; | ||
|  | 
 | ||
|  |   item.next = null; | ||
|  |   item.prev = this.tail; | ||
|  | 
 | ||
|  |   if (this.tail) this.tail.next = item; | ||
|  |   this.tail = item; | ||
|  | 
 | ||
|  |   return val; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Check if cache has given `key`. | ||
|  |  * | ||
|  |  * @param {String} key | ||
|  |  * @return {Boolean} | ||
|  |  * @api private | ||
|  |  */ | ||
|  | 
 | ||
|  | MemoryCache.prototype.has = function(key) { | ||
|  |   return !!this._cache[key]; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Generate key for the source `str` with `options`. | ||
|  |  * | ||
|  |  * @param {String} str | ||
|  |  * @param {Object} options | ||
|  |  * @return {String} | ||
|  |  * @api private | ||
|  |  */ | ||
|  | 
 | ||
|  | MemoryCache.prototype.key = function(str, options) { | ||
|  |   var hash = crypto.createHash('sha1'); | ||
|  |   hash.update(str + options.prefix); | ||
|  |   return hash.digest('hex'); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Remove the oldest item from the cache. | ||
|  |  * | ||
|  |  * @api private | ||
|  |  */ | ||
|  | 
 | ||
|  | MemoryCache.prototype.purge = function() { | ||
|  |   var item = this.head; | ||
|  | 
 | ||
|  |   if (this.head.next) { | ||
|  |     this.head = this.head.next; | ||
|  |     this.head.prev = null; | ||
|  |   } | ||
|  | 
 | ||
|  |   this._cache[item.key] = item.prev = item.next = null; | ||
|  |   this.length--; | ||
|  | }; |