You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					437 lines
				
				10 KiB
			
		
		
			
		
	
	
					437 lines
				
				10 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Mnemonist LRUCache
							 | 
						||
| 
								 | 
							
								 * ===================
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * JavaScript implementation of the LRU Cache data structure. To save up
							 | 
						||
| 
								 | 
							
								 * memory and allocations this implementation represents its underlying
							 | 
						||
| 
								 | 
							
								 * doubly-linked list as static arrays and pointers. Thus, memory is allocated
							 | 
						||
| 
								 | 
							
								 * only once at instantiation and JS objects are never created to serve as
							 | 
						||
| 
								 | 
							
								 * pointers. This also means this implementation does not trigger too many
							 | 
						||
| 
								 | 
							
								 * garbage collections.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Note that to save up memory, a LRU Cache can be implemented using a singly
							 | 
						||
| 
								 | 
							
								 * linked list by storing predecessors' pointers as hashmap values.
							 | 
						||
| 
								 | 
							
								 * However, this means more hashmap lookups and would probably slow the whole
							 | 
						||
| 
								 | 
							
								 * thing down. What's more, pointers are not the things taking most space in
							 | 
						||
| 
								 | 
							
								 * memory.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								var Iterator = require('obliterator/iterator'),
							 | 
						||
| 
								 | 
							
								    forEach = require('obliterator/foreach'),
							 | 
						||
| 
								 | 
							
								    typed = require('./utils/typed-arrays.js'),
							 | 
						||
| 
								 | 
							
								    iterables = require('./utils/iterables.js');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * LRUCache.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @constructor
							 | 
						||
| 
								 | 
							
								 * @param {function} Keys     - Array class for storing keys.
							 | 
						||
| 
								 | 
							
								 * @param {function} Values   - Array class for storing values.
							 | 
						||
| 
								 | 
							
								 * @param {number}   capacity - Desired capacity.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function LRUCache(Keys, Values, capacity) {
							 | 
						||
| 
								 | 
							
								  if (arguments.length < 2) {
							 | 
						||
| 
								 | 
							
								    capacity = Keys;
							 | 
						||
| 
								 | 
							
								    Keys = null;
							 | 
						||
| 
								 | 
							
								    Values = null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.capacity = capacity;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof this.capacity !== 'number' || this.capacity <= 0)
							 | 
						||
| 
								 | 
							
								    throw new Error('mnemonist/lru-cache: capacity should be positive number.');
							 | 
						||
| 
								 | 
							
								  else if (!isFinite(this.capacity) || Math.floor(this.capacity) !== this.capacity)
							 | 
						||
| 
								 | 
							
								    throw new Error('mnemonist/lru-cache: capacity should be a finite positive integer.');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var PointerArray = typed.getPointerArray(capacity);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.forward = new PointerArray(capacity);
							 | 
						||
| 
								 | 
							
								  this.backward = new PointerArray(capacity);
							 | 
						||
| 
								 | 
							
								  this.K = typeof Keys === 'function' ? new Keys(capacity) : new Array(capacity);
							 | 
						||
| 
								 | 
							
								  this.V = typeof Values === 'function' ? new Values(capacity) : new Array(capacity);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Properties
							 | 
						||
| 
								 | 
							
								  this.size = 0;
							 | 
						||
| 
								 | 
							
								  this.head = 0;
							 | 
						||
| 
								 | 
							
								  this.tail = 0;
							 | 
						||
| 
								 | 
							
								  this.items = {};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to clear the structure.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return {undefined}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.clear = function() {
							 | 
						||
| 
								 | 
							
								  this.size = 0;
							 | 
						||
| 
								 | 
							
								  this.head = 0;
							 | 
						||
| 
								 | 
							
								  this.tail = 0;
							 | 
						||
| 
								 | 
							
								  this.items = {};
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to splay a value on top.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {number}   pointer - Pointer of the value to splay on top.
							 | 
						||
| 
								 | 
							
								 * @return {LRUCache}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.splayOnTop = function(pointer) {
							 | 
						||
| 
								 | 
							
								  var oldHead = this.head;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (this.head === pointer)
							 | 
						||
| 
								 | 
							
								    return this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var previous = this.backward[pointer],
							 | 
						||
| 
								 | 
							
								      next = this.forward[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (this.tail === pointer) {
							 | 
						||
| 
								 | 
							
								    this.tail = previous;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    this.backward[next] = previous;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.forward[previous] = next;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.backward[oldHead] = pointer;
							 | 
						||
| 
								 | 
							
								  this.head = pointer;
							 | 
						||
| 
								 | 
							
								  this.forward[pointer] = oldHead;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return this;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to set the value for the given key in the cache.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {any} key   - Key.
							 | 
						||
| 
								 | 
							
								 * @param  {any} value - Value.
							 | 
						||
| 
								 | 
							
								 * @return {undefined}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.set = function(key, value) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var pointer = this.items[key];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // The key already exists, we just need to update the value and splay on top
							 | 
						||
| 
								 | 
							
								  if (typeof pointer !== 'undefined') {
							 | 
						||
| 
								 | 
							
								    this.splayOnTop(pointer);
							 | 
						||
| 
								 | 
							
								    this.V[pointer] = value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // The cache is not yet full
							 | 
						||
| 
								 | 
							
								  if (this.size < this.capacity) {
							 | 
						||
| 
								 | 
							
								    pointer = this.size++;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Cache is full, we need to drop the last value
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    pointer = this.tail;
							 | 
						||
| 
								 | 
							
								    this.tail = this.backward[pointer];
							 | 
						||
| 
								 | 
							
								    delete this.items[this.K[pointer]];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Storing key & value
							 | 
						||
| 
								 | 
							
								  this.items[key] = pointer;
							 | 
						||
| 
								 | 
							
								  this.K[pointer] = key;
							 | 
						||
| 
								 | 
							
								  this.V[pointer] = value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Moving the item at the front of the list
							 | 
						||
| 
								 | 
							
								  this.forward[pointer] = this.head;
							 | 
						||
| 
								 | 
							
								  this.backward[this.head] = pointer;
							 | 
						||
| 
								 | 
							
								  this.head = pointer;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to set the value for the given key in the cache
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {any} key   - Key.
							 | 
						||
| 
								 | 
							
								 * @param  {any} value - Value.
							 | 
						||
| 
								 | 
							
								 * @return {{evicted: boolean, key: any, value: any}} An object containing the
							 | 
						||
| 
								 | 
							
								 * key and value of an item that was overwritten or evicted in the set
							 | 
						||
| 
								 | 
							
								 * operation, as well as a boolean indicating whether it was evicted due to
							 | 
						||
| 
								 | 
							
								 * limited capacity. Return value is null if nothing was evicted or overwritten
							 | 
						||
| 
								 | 
							
								 * during the set operation.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.setpop = function(key, value) {
							 | 
						||
| 
								 | 
							
								  var oldValue = null;
							 | 
						||
| 
								 | 
							
								  var oldKey = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var pointer = this.items[key];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // The key already exists, we just need to update the value and splay on top
							 | 
						||
| 
								 | 
							
								  if (typeof pointer !== 'undefined') {
							 | 
						||
| 
								 | 
							
								    this.splayOnTop(pointer);
							 | 
						||
| 
								 | 
							
								    oldValue = this.V[pointer];
							 | 
						||
| 
								 | 
							
								    this.V[pointer] = value;
							 | 
						||
| 
								 | 
							
								    return {evicted: false, key: key, value: oldValue};
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // The cache is not yet full
							 | 
						||
| 
								 | 
							
								  if (this.size < this.capacity) {
							 | 
						||
| 
								 | 
							
								    pointer = this.size++;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Cache is full, we need to drop the last value
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    pointer = this.tail;
							 | 
						||
| 
								 | 
							
								    this.tail = this.backward[pointer];
							 | 
						||
| 
								 | 
							
								    oldValue = this.V[pointer];
							 | 
						||
| 
								 | 
							
								    oldKey = this.K[pointer];
							 | 
						||
| 
								 | 
							
								    delete this.items[this.K[pointer]];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Storing key & value
							 | 
						||
| 
								 | 
							
								  this.items[key] = pointer;
							 | 
						||
| 
								 | 
							
								  this.K[pointer] = key;
							 | 
						||
| 
								 | 
							
								  this.V[pointer] = value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Moving the item at the front of the list
							 | 
						||
| 
								 | 
							
								  this.forward[pointer] = this.head;
							 | 
						||
| 
								 | 
							
								  this.backward[this.head] = pointer;
							 | 
						||
| 
								 | 
							
								  this.head = pointer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Return object if eviction took place, otherwise return null
							 | 
						||
| 
								 | 
							
								  if (oldKey) {
							 | 
						||
| 
								 | 
							
								    return {evicted: true, key: oldKey, value: oldValue};
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else {
							 | 
						||
| 
								 | 
							
								    return null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to check whether the key exists in the cache.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {any} key   - Key.
							 | 
						||
| 
								 | 
							
								 * @return {boolean}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.has = function(key) {
							 | 
						||
| 
								 | 
							
								  return key in this.items;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to get the value attached to the given key. Will move the
							 | 
						||
| 
								 | 
							
								 * related key to the front of the underlying linked list.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {any} key   - Key.
							 | 
						||
| 
								 | 
							
								 * @return {any}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.get = function(key) {
							 | 
						||
| 
								 | 
							
								  var pointer = this.items[key];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof pointer === 'undefined')
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.splayOnTop(pointer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return this.V[pointer];
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to get the value attached to the given key. Does not modify
							 | 
						||
| 
								 | 
							
								 * the ordering of the underlying linked list.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {any} key   - Key.
							 | 
						||
| 
								 | 
							
								 * @return {any}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.peek = function(key) {
							 | 
						||
| 
								 | 
							
								  var pointer = this.items[key];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof pointer === 'undefined')
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return this.V[pointer];
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to iterate over the cache's entries using a callback.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {function}  callback - Function to call for each item.
							 | 
						||
| 
								 | 
							
								 * @param  {object}    scope    - Optional scope.
							 | 
						||
| 
								 | 
							
								 * @return {undefined}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.forEach = function(callback, scope) {
							 | 
						||
| 
								 | 
							
								  scope = arguments.length > 1 ? scope : this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var i = 0,
							 | 
						||
| 
								 | 
							
								      l = this.size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var pointer = this.head,
							 | 
						||
| 
								 | 
							
								      keys = this.K,
							 | 
						||
| 
								 | 
							
								      values = this.V,
							 | 
						||
| 
								 | 
							
								      forward = this.forward;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while (i < l) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    callback.call(scope, values[pointer], keys[pointer], this);
							 | 
						||
| 
								 | 
							
								    pointer = forward[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i++;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to create an iterator over the cache's keys from most
							 | 
						||
| 
								 | 
							
								 * recently used to least recently used.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return {Iterator}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.keys = function() {
							 | 
						||
| 
								 | 
							
								  var i = 0,
							 | 
						||
| 
								 | 
							
								      l = this.size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var pointer = this.head,
							 | 
						||
| 
								 | 
							
								      keys = this.K,
							 | 
						||
| 
								 | 
							
								      forward = this.forward;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return new Iterator(function() {
							 | 
						||
| 
								 | 
							
								    if (i >= l)
							 | 
						||
| 
								 | 
							
								      return {done: true};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var key = keys[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i < l)
							 | 
						||
| 
								 | 
							
								      pointer = forward[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      done: false,
							 | 
						||
| 
								 | 
							
								      value: key
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to create an iterator over the cache's values from most
							 | 
						||
| 
								 | 
							
								 * recently used to least recently used.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return {Iterator}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.values = function() {
							 | 
						||
| 
								 | 
							
								  var i = 0,
							 | 
						||
| 
								 | 
							
								      l = this.size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var pointer = this.head,
							 | 
						||
| 
								 | 
							
								      values = this.V,
							 | 
						||
| 
								 | 
							
								      forward = this.forward;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return new Iterator(function() {
							 | 
						||
| 
								 | 
							
								    if (i >= l)
							 | 
						||
| 
								 | 
							
								      return {done: true};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var value = values[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i < l)
							 | 
						||
| 
								 | 
							
								      pointer = forward[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      done: false,
							 | 
						||
| 
								 | 
							
								      value: value
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Method used to create an iterator over the cache's entries from most
							 | 
						||
| 
								 | 
							
								 * recently used to least recently used.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return {Iterator}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.entries = function() {
							 | 
						||
| 
								 | 
							
								  var i = 0,
							 | 
						||
| 
								 | 
							
								      l = this.size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var pointer = this.head,
							 | 
						||
| 
								 | 
							
								      keys = this.K,
							 | 
						||
| 
								 | 
							
								      values = this.V,
							 | 
						||
| 
								 | 
							
								      forward = this.forward;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return new Iterator(function() {
							 | 
						||
| 
								 | 
							
								    if (i >= l)
							 | 
						||
| 
								 | 
							
								      return {done: true};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var key = keys[pointer],
							 | 
						||
| 
								 | 
							
								        value = values[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i < l)
							 | 
						||
| 
								 | 
							
								      pointer = forward[pointer];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      done: false,
							 | 
						||
| 
								 | 
							
								      value: [key, value]
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Attaching the #.entries method to Symbol.iterator if possible.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								if (typeof Symbol !== 'undefined')
							 | 
						||
| 
								 | 
							
								  LRUCache.prototype[Symbol.iterator] = LRUCache.prototype.entries;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Convenience known methods.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.prototype.inspect = function() {
							 | 
						||
| 
								 | 
							
								  var proxy = new Map();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var iterator = this.entries(),
							 | 
						||
| 
								 | 
							
								      step;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while ((step = iterator.next(), !step.done))
							 | 
						||
| 
								 | 
							
								    proxy.set(step.value[0], step.value[1]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Trick so that node displays the name of the constructor
							 | 
						||
| 
								 | 
							
								  Object.defineProperty(proxy, 'constructor', {
							 | 
						||
| 
								 | 
							
								    value: LRUCache,
							 | 
						||
| 
								 | 
							
								    enumerable: false
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return proxy;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if (typeof Symbol !== 'undefined')
							 | 
						||
| 
								 | 
							
								  LRUCache.prototype[Symbol.for('nodejs.util.inspect.custom')] = LRUCache.prototype.inspect;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Static @.from function taking an arbitrary iterable & converting it into
							 | 
						||
| 
								 | 
							
								 * a structure.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param  {Iterable} iterable - Target iterable.
							 | 
						||
| 
								 | 
							
								 * @param  {function} Keys     - Array class for storing keys.
							 | 
						||
| 
								 | 
							
								 * @param  {function} Values   - Array class for storing values.
							 | 
						||
| 
								 | 
							
								 * @param  {number}   capacity - Cache's capacity.
							 | 
						||
| 
								 | 
							
								 * @return {LRUCache}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								LRUCache.from = function(iterable, Keys, Values, capacity) {
							 | 
						||
| 
								 | 
							
								  if (arguments.length < 2) {
							 | 
						||
| 
								 | 
							
								    capacity = iterables.guessLength(iterable);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (typeof capacity !== 'number')
							 | 
						||
| 
								 | 
							
								      throw new Error('mnemonist/lru-cache.from: could not guess iterable length. Please provide desired capacity as last argument.');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (arguments.length === 2) {
							 | 
						||
| 
								 | 
							
								    capacity = Keys;
							 | 
						||
| 
								 | 
							
								    Keys = null;
							 | 
						||
| 
								 | 
							
								    Values = null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var cache = new LRUCache(Keys, Values, capacity);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  forEach(iterable, function(value, key) {
							 | 
						||
| 
								 | 
							
								    cache.set(key, value);
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return cache;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Exporting.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								module.exports = LRUCache;
							 |