/** * This class manages a double-linked list. It provides an absolutely minimal container * interface. * * @class Ext.util.LRU * @private * @since 6.5.0 *//* eslint-disable indent */(function(LRU, prototype) {// @define Ext.util.LRU // NOTE: We have to implement this class old-school because it is used by the // platformConfig class processor (so Ext.define is not yet ready for action). (Ext.util || (Ext.util = {})).LRU = LRU = function(config) { var me = this, head; if (config) { Ext.apply(me, config); } // Give all entries the same object shape. me.head = head = { //<debug> id: (me.seed = 0), //</debug> key: null, value: null }; /** * @property {Object} map * The items in the list indexed by their `key`. * @readonly */ me.map = {}; head.next = head.prev = head; }; LRU.prototype = prototype = { /** * @property {Number} count * The number of items in this list. * @readonly */ count: 0, /** * Adds an item to the list with the specified `key`. Items are added at the * front (MRU) of the list. * @param {String} key * @param {Object} value */ add: function(key, value) { var me = this, map = me.map, entry = map[key]; if (entry) { me.unlink(entry); --me.count; } map[key] = entry = { //<debug> id: ++me.seed, //</debug> key: key, value: value }; me.link(entry); ++me.count; return entry; }, /** * Removes all items from this list optionally calling a function for each * remove item. * @param {Function} [fn] A function to call for each removed item. * @param {Object} fn.key The key of the removed item. * @param {Object} fn.value The removed item. * @param {Object} [scope] The `this` pointer for `fn`. */ clear: function(fn, scope) { var me = this, head = me.head, entry = head.next; head.next = head.prev = head; me.count = 0; if (fn && !fn.$nullFn) { for (; entry !== head; entry = entry.next) { fn.call(scope || me, entry.key, entry.value); } } }, /** * Calls the given function `fn` for each item in the list. The items will be * passed to `fn` from most-to-least recently added or touched. * @param {Function} fn The function to call for each cache item. * @param {String} fn.key The key for the item. * @param {Object} fn.value The item. * @param {Object} [scope] The `this` pointer to use for `fn`. */ each: function(fn, scope) { var head, ent; scope = scope || this; for (head = this.head, ent = head.next; ent !== head; ent = ent.next) { if (fn.call(scope, ent.key, ent.value)) { break; } } }, /** * Removes the item at the end (LRU) of the list. Optionally the item can be passed * to a callback function. If the list is empty, no callback is made and this * method will return `undefined`. * @param {Function} fn The function to call for the removed item. * @param {Object} fn.key The key of the removed item. * @param {Object} fn.value The removed item. * @param {Object} [scope] The `this` pointer to use for `fn`. * @return {Object} The removed item. */ prune: function(fn, scope) { var me = this, entry = me.head.prev, ret; if (me.count) { ret = entry.value; me.unlink(entry); --me.count; if (fn) { fn.call(scope || me, entry.key, ret); } } return ret; }, /** * Removes an item from the list given its key. * @param {String} key The key of the item to remove. * @return {Object} The removed item or `undefined` if the key was not found. */ remove: function(key) { var me = this, map = me.map, entry = map[key], value; if (entry) { me.unlink(entry); value = entry.value; delete map[key]; --me.count; } return value; }, /** * Moves the item with the given key to the front (MRU) of the list. * @param {String} key The key of the item to move to the front. */ touch: function(key) { var me = this, head = me.head, entry = me.map[key]; if (entry && entry.prev !== head) { // The entry is not at the front, so remove it and insert it at the front // (to make it the MRU - Most Recently Used). me.unlink(entry); me.link(entry); } }, /** * Reduces the length of the list to be no more than the specified `size`, removing * items from the end of the list as necessary. Optionally each removed item can * be passed to a callback `fn`. * @param {Number} size The number of items in the list * @param {Function} [fn] A function to call for each removed item. * @param {Object} fn.key The key of the removed item. * @param {Object} fn.value The removed item. * @param {Object} [scope] The `this` pointer for `fn`. */ trim: function(size, fn, scope) { while (this.count > size) { this.prune(fn, scope); } }, //------------------------------------------------------------------------- // Internals /** * Inserts the given entry at the front (MRU) end of the entry list. * @param {Object} entry The cache item entry. * @private */ link: function(entry) { var head = this.head, first = head.next; entry.next = first; entry.prev = head; head.next = entry; first.prev = entry; }, /** * Removes the given entry from the entry list. * @param {Object} entry The cache item entry. * @private */ unlink: function(entry) { var next = entry.next, prev = entry.prev; prev.next = next; next.prev = prev; } }; prototype.destroy = function() { this.clear.apply(this, arguments); };}());