forked from hero/www_hero
124 lines
2.0 KiB
JavaScript
124 lines
2.0 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
class QuickLRU {
|
||
|
constructor(options = {}) {
|
||
|
if (!(options.maxSize && options.maxSize > 0)) {
|
||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||
|
}
|
||
|
|
||
|
this.maxSize = options.maxSize;
|
||
|
this.onEviction = options.onEviction;
|
||
|
this.cache = new Map();
|
||
|
this.oldCache = new Map();
|
||
|
this._size = 0;
|
||
|
}
|
||
|
|
||
|
_set(key, value) {
|
||
|
this.cache.set(key, value);
|
||
|
this._size++;
|
||
|
|
||
|
if (this._size >= this.maxSize) {
|
||
|
this._size = 0;
|
||
|
|
||
|
if (typeof this.onEviction === 'function') {
|
||
|
for (const [key, value] of this.oldCache.entries()) {
|
||
|
this.onEviction(key, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.oldCache = this.cache;
|
||
|
this.cache = new Map();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
get(key) {
|
||
|
if (this.cache.has(key)) {
|
||
|
return this.cache.get(key);
|
||
|
}
|
||
|
|
||
|
if (this.oldCache.has(key)) {
|
||
|
const value = this.oldCache.get(key);
|
||
|
this.oldCache.delete(key);
|
||
|
this._set(key, value);
|
||
|
return value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set(key, value) {
|
||
|
if (this.cache.has(key)) {
|
||
|
this.cache.set(key, value);
|
||
|
} else {
|
||
|
this._set(key, value);
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
has(key) {
|
||
|
return this.cache.has(key) || this.oldCache.has(key);
|
||
|
}
|
||
|
|
||
|
peek(key) {
|
||
|
if (this.cache.has(key)) {
|
||
|
return this.cache.get(key);
|
||
|
}
|
||
|
|
||
|
if (this.oldCache.has(key)) {
|
||
|
return this.oldCache.get(key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete(key) {
|
||
|
const deleted = this.cache.delete(key);
|
||
|
if (deleted) {
|
||
|
this._size--;
|
||
|
}
|
||
|
|
||
|
return this.oldCache.delete(key) || deleted;
|
||
|
}
|
||
|
|
||
|
clear() {
|
||
|
this.cache.clear();
|
||
|
this.oldCache.clear();
|
||
|
this._size = 0;
|
||
|
}
|
||
|
|
||
|
* keys() {
|
||
|
for (const [key] of this) {
|
||
|
yield key;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
* values() {
|
||
|
for (const [, value] of this) {
|
||
|
yield value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
* [Symbol.iterator]() {
|
||
|
for (const item of this.cache) {
|
||
|
yield item;
|
||
|
}
|
||
|
|
||
|
for (const item of this.oldCache) {
|
||
|
const [key] = item;
|
||
|
if (!this.cache.has(key)) {
|
||
|
yield item;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
get size() {
|
||
|
let oldCacheSize = 0;
|
||
|
for (const key of this.oldCache.keys()) {
|
||
|
if (!this.cache.has(key)) {
|
||
|
oldCacheSize++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Math.min(this._size + oldCacheSize, this.maxSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = QuickLRU;
|