2 local function _remove(list
, m
)
9 if list
._tail
== m
then
12 if list
._head
== m
then
15 list
._count
= list
._count
- 1;
18 local function _insert(list
, m
)
22 m
.prev
, m
.next = nil, list
._head
;
24 if not list
._tail
then
27 list
._count
= list
._count
+ 1;
30 local cache_methods
= {};
31 local cache_mt
= { __index
= cache_methods
};
33 function cache_methods
:set(k
, v
)
34 local m
= self
._data
[k
];
38 -- Bump to head of list
53 -- Check whether we need to remove oldest k/v
54 if self
._count
== self
.size
then
55 local tail
= self
._tail
;
56 local on_evict
, evicted_key
, evicted_value
= self
._on_evict
, tail
.key
, tail
.value
;
57 if on_evict
~= nil and (on_evict
== false or on_evict(evicted_key
, evicted_value
) == false) then
58 -- Cache is full, and we're not allowed to evict
62 self
._data
[evicted_key
] = nil;
65 m
= { key
= k
, value
= v
, prev
= nil, next = nil };
71 function cache_methods
:get(k
)
72 local m
= self
._data
[k
];
79 function cache_methods
:items()
85 local k
, v
= m
.key
, m
.value
;
91 function cache_methods
:values()
103 function cache_methods
:count()
107 function cache_methods
:head()
108 local head
= self
._head
;
109 if not head
then return nil, nil; end
110 return head
.key
, head
.value
;
113 function cache_methods
:tail()
114 local tail
= self
._tail
;
115 if not tail
then return nil, nil; end
116 return tail
.key
, tail
.value
;
119 function cache_methods
:resize(new_size
)
120 new_size
= assert(tonumber(new_size
), "cache size must be a number");
121 new_size
= math
.floor(new_size
);
122 assert(new_size
> 0, "cache size must be greater than zero");
123 local on_evict
= self
._on_evict
;
124 while self
._count
> new_size
do
125 local tail
= self
._tail
;
126 local evicted_key
, evicted_value
= tail
.key
, tail
.value
;
127 if on_evict
~= nil and (on_evict
== false or on_evict(evicted_key
, evicted_value
) == false) then
128 -- Cache is full, and we're not allowed to evict
132 self
._data
[evicted_key
] = nil;
134 self
.size
= new_size
;
138 function cache_methods
:table()
139 --luacheck: ignore 212/t
140 if not self
.proxy_table
then
141 self
.proxy_table
= setmetatable({}, {
142 __index
= function (t
, k
)
145 __newindex
= function (t
, k
, v
)
146 if not self
:set(k
, v
) then
147 error("failed to insert key into cache - full");
150 __pairs
= function (t
)
158 return self
.proxy_table
;
161 function cache_methods
:clear()
168 local function new(size
, on_evict
)
169 size
= assert(tonumber(size
), "cache size must be a number");
170 size
= math
.floor(size
);
171 assert(size
> 0, "cache size must be greater than zero");
173 return setmetatable({ _data
= data
, _count
= 0, size
= size
, _head
= nil, _tail
= nil, _on_evict
= on_evict
}, cache_mt
);