-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcache.lua
More file actions
114 lines (93 loc) · 2.43 KB
/
cache.lua
File metadata and controls
114 lines (93 loc) · 2.43 KB
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
local EMPTY_TABLE = {}
local support_types = {["string"] = true, ["number"] = true, ["boolean"] = true}
local function sync_cache(self, obj, field_name)
local key = assert(obj[self.key_field_name])
local value = obj[field_name]
if value == nil then
return
end
assert(support_types[type(value)])
self.cache[field_name] = self.cache[field_name] or {}
self.cache[field_name][value] = self.cache[field_name][value] or {}
self.cache[field_name][value][key] = true
end
local cache = {}
function cache:new(key_field_name, ...)
local c = {}
c.key_field_name = key_field_name
c.index_field_names = {}
for _, field_name in ipairs({...}) do
c.index_field_names[field_name] = true
end
c.objs = {}
c.cache = {}
setmetatable(c, self)
self.__index = self
return c
end
function cache:add(obj)
local key = assert(obj[self.key_field_name])
assert(self.objs[key] == nil, ("duplicate key `%s`"):format(key))
self.objs[key] = obj
for field_name in pairs(self.index_field_names) do
sync_cache(self, obj, field_name)
end
end
function cache:remove(key)
assert(self.objs[key])
self.objs[key] = nil
end
function cache:sync(obj, ...)
local key = assert(obj[self.key_field_name])
assert(self.objs[key] == obj, ("can not found key `%s`"):format(key))
local field_names = {...}
assert(#field_names >= 1)
for _, field_name in ipairs(field_names) do
assert(type(field_name) == "string")
if self.index_field_names[field_name] then
sync_cache(self, obj, field_name)
end
end
end
function cache:select(field_name, value)
assert(value ~= nil)
assert(self.index_field_names[field_name], ("must specify the field_name `%s` as index field name"):format(field_name))
if not self.cache[field_name] then
return next, EMPTY_TABLE, nil
end
if not self.cache[field_name][value] then
return next, EMPTY_TABLE, nil
end
local obj
local t = {}
for key in pairs(self.cache[field_name][value]) do
obj = self.objs[key]
if not obj then
self.cache[field_name][value][key] = nil
else
if obj[field_name] ~= value then
self.cache[field_name][value][key] = nil
else
t[key] = obj
end
end
end
return next, t, nil
end
function cache:selectkey(key)
return self.objs[key]
end
function cache:selectall()
return next, self.objs, nil
end
function cache:empty()
return not next(self.objs)
end
function cache:clear(field_name)
self.cache[field_name] = nil
end
function cache:clearall()
self.objs = {}
self.cache = {}
end
return cache