0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-10 08:50:57 -05:00
penpot/vendor/lru.js
2016-06-11 19:48:19 +03:00

125 lines
2.6 KiB
JavaScript

/**
* lru - an LRU (least recently used) cache implementation.
*
* Implemented using double-linked list and hash-map that
* gives O(1) time complexity and O(n) in space usage.
*
* @author Andrey Antukh <niwi@niwi.nz>, 2016
* @license MIT License <https://opensource.org/licenses/MIT>
*/
"use strict";
goog.provide("lru");
goog.require("goog.asserts");
goog.scope(function() {
const assert = goog.asserts.assert;
class Node {
constructor(key, value) {
this.key = key;
this.value = value;
this.prev = null;
this.next = null;
}
}
class Cache {
constructor(limit) {
assert(goog.isNumber(limit), "`limit` should be a number")
this.limit = limit
this.clear();
}
clear() {
this.map = new Map();
this.size = 0;
this.head = null;
this.tail = null;
}
setHead(node) {
assert(node instanceof Node, "Node instance expected");
node.next = this.head;
node.prev = null;
if (this.head !== null) {
this.head.prev = node;
}
this.head = node;
if (this.tail === null) {
this.tail = node;
}
this.size++;
this.map.set(node.key, node);
return this;
}
setItem(key, value) {
const node = new Node(key, value);
if (this.map.has(key)) {
const item = this.map.get(key);
item.value = node.value;
this.removeItem(node.key);
} else {
if (this.size >= this.limit) {
this.map.delete(key);
this.size--;
this.tail = this.tail.prev;
this.tail.next = null;
}
}
this.setHead(node);
return this;
}
getItem(key) {
if (this.map.has(key)) {
const value = this.map.get(key).value;
const node = new Node(key, value);
this.removeItem(key);
this.setHead(node);
return value;
} else {
return undefined;
}
}
removeItem(key) {
if (!this.map.has(key)) {
return this;
}
const node = this.map.get(key);
if (node.prev !== null) {
node.prev.next = node.next;
} else {
this.head = node.next;
}
if (node.next !== null) {
node.next.prev = node.prev;
} else {
this.tail = node.prev;
}
this.map.delete(key);
this.size--;
return this;
}
}
function create(limit) {
limit = limit || 50;
return new Cache(limit);
}
lru.create = create;
lru.get = (c, key) => c.getItem(key);
lru.set = (c, key, val) => c.setItem(key, val);
lru.remove = (c, key) => c.removeItem(key);
});