-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
tiny-lru.cjs.js
120 lines (118 loc) · 3.21 KB
/
tiny-lru.cjs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
'use strict';
class LRU {
constructor(max = 0, ttl = 0) {
this.first = null;
this.items = {};
this.last = null;
this.max = max;
this.size = 0;
this.ttl = ttl;
}
has(key) {
return key in this.items;
}
clear() {
this.first = null;
this.items = {};
this.last = null;
this.size = 0;
return this;
}
delete(key) {
if (this.has(key)) {
const item = this.items[key];
delete this.items[key];
this.size--;
if (item.prev !== null) {
item.prev.next = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
}
if (this.first === item) {
this.first = item.next;
}
if (this.last === item) {
this.last = item.prev;
}
}
return this;
}
evict() {
const item = this.first;
delete this.items[item.key];
this.first = item.next;
this.first.prev = null;
this.size--;
return this;
}
get(key) {
let result;
if (this.has(key)) {
const item = this.items[key];
if (this.ttl > 0 && item.expiry <= new Date().getTime()) {
this.delete(key);
}
else {
result = item.value;
this.set(key, result, true);
}
}
return result;
}
keys() {
return Object.keys(this.items);
}
set(key, value, bypass = false) {
let item;
if (bypass || this.has(key)) {
item = this.items[key];
item.value = value;
if (this.last !== item) {
const last = this.last, next = item.next, prev = item.prev;
if (this.first === item) {
this.first = item.next;
}
item.next = null;
item.prev = this.last;
last.next = item;
if (prev !== null) {
prev.next = next;
}
if (next !== null) {
next.prev = prev;
}
}
}
else {
if (this.max > 0 && this.size === this.max) {
this.evict();
}
item = this.items[key] = {
expiry: this.ttl > 0 ? new Date().getTime() + this.ttl : this.ttl,
key: key,
prev: this.last,
next: null,
value
};
if (++this.size === 1) {
this.first = item;
}
else {
this.last.next = item;
}
}
this.last = item;
return this;
}
}
function factory(max = 1000, ttl = 0) {
if (isNaN(max) || max < 0) {
throw new TypeError("Invalid max value");
}
if (isNaN(ttl) || ttl < 0) {
throw new TypeError("Invalid ttl value");
}
return new LRU(max, ttl);
}
module.exports = factory;