mirror of
https://github.com/penpot/penpot.git
synced 2025-01-25 07:58:49 -05:00
Add lru cache implementation.
This commit is contained in:
parent
5ce66f3c69
commit
4ab20eaef0
1 changed files with 125 additions and 0 deletions
125
vendor/lru.js
vendored
Normal file
125
vendor/lru.js
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* 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);
|
||||
});
|
Loading…
Add table
Reference in a new issue