avoid a crash
[QuestHelper.git] / db_get.lua
blob646e19d6e09c37ee4ce826666524019161103982
1 QuestHelper_File["db_get.lua"] = "Development Version"
2 QuestHelper_Loadtime["db_get.lua"] = GetTime()
4 -- yoink
5 --[[
6 local QHDB_temp = QHDB
7 QHDB = nil
8 local QHDB = QHDB_temp]]
9 QuestHelper: Assert(#QHDB == 4)
11 local weak_v = { __mode = 'v' }
12 local weak_k = { __mode = 'k' }
14 local cache = {}
16 local frequencies = setmetatable({}, weak_k)
18 -- guhhh just want this to work
19 local freq_group = setmetatable({}, weak_k)
20 local freq_id = setmetatable({}, weak_k)
22 local function DBC_Get(group, id)
23 if not cache[group] then return end
24 return cache[group][id]
25 end
27 local function DBC_Put(group, id, item)
28 if not cache[group] then cache[group] = setmetatable({}, weak_v) end
29 QuestHelper: Assert(not cache[group][id])
30 cache[group][id] = item
32 --DB_how_many_are_used()
33 end
35 local function mark(tab, tomark)
36 for k, v in pairs(tab) do
37 if type(v) == "table" then
38 mark(v, tomark)
39 end
40 end
41 tab.__owner = tomark
42 end
44 local function read_adaptint(data, offset)
45 local stx = 0
46 local acu = 1
47 while true do
48 local v = strbyte(data, offset)
49 QuestHelper: Assert(v, string.format("%d %d", #data, offset))
50 stx = stx + acu * math.floor(v / 2)
51 offset = offset + 1
52 acu = acu * 128
53 if mod(v, 2) == 0 then break end
54 end
55 return stx, offset
56 end
58 local function search_index(index, data, item)
59 --[[Header format:
61 Itemid (0 for endnode)
62 Offset
63 Length
64 Rightlink]]
66 local cofs = 1
67 assert(index and type(index) == "string")
68 assert(data and type(data) == "string")
70 while true do
71 local idx, ofs, len, rlink
72 idx, cofs = read_adaptint(index, cofs)
73 if idx == 0 then return end
74 ofs, cofs = read_adaptint(index, cofs)
75 len, cofs = read_adaptint(index, cofs)
76 rlink, cofs = read_adaptint(index, cofs)
78 if idx == item then
79 return strsub(data, ofs, ofs + len)
80 end
82 if idx < item then cofs = cofs + rlink end
83 end
84 end
86 local initted = false
87 function DB_Init()
88 QuestHelper: Assert(not initted)
89 for _, db in ipairs(QHDB) do
90 for _, v in pairs(db) do
91 --print("db", not not v.__dictionary, not not v.__tokens)
92 if v.__dictionary and v.__tokens then
93 local redictix = v.__dictionary
94 if not redictix:find("\"") then redictix = redictix .. "\"" end
95 if not redictix:find(",") then redictix = redictix .. "," end
96 if not redictix:find("\\") then redictix = redictix .. "\\" end
97 local tokens = loadstring("return {" .. QH_LZW_Decompress_Dicts_Arghhacky(v.__tokens, redictix) .. "}")()
98 QuestHelper: Assert(tokens)
100 local _, _, prep = QH_LZW_Prepare_Arghhacky(v.__dictionary, tokens)
101 QuestHelper: Assert(prep)
103 QuestHelper: Assert(type(prep) == "table")
105 v.__tokens = prep
109 initted = true
112 function DB_Ready()
113 return initted
116 function DB_GetItem(group, id, silent, register)
117 QuestHelper: Assert(initted)
119 QuestHelper: Assert(group, string.format("%s %s", tostring(group), tostring(id)))
120 QuestHelper: Assert(id, string.format("%s %s", tostring(group), tostring(id)))
121 local ite = DBC_Get(group, id)
122 if not ite then
123 if type(id) == "string" then QuestHelper: Assert(not id:match("__.*")) end
125 --QuestHelper:TextOut(string.format("%s %d", group, id))
127 for _, db in ipairs(QHDB) do
128 --print(db, db[group], db[group] and db[group][id], type(group), type(id))
129 if db[group] then
130 if not ite then ite = QuestHelper:CreateTable("db") end
132 local srctab
134 local dat
135 if db[group][id] then
136 dat = db[group][id]
139 --print(not dat, type(id), id, not not db[group].__serialize_index, not not db[group].__serialize_index)
140 if not dat and type(id) == "number" and id > 0 and db[group].__serialize_index and db[group].__serialize_data then
141 dat = search_index(db[group].__serialize_index, db[group].__serialize_data, id)
144 if dat then
145 if type(dat) == "string" then
146 QuestHelper: Assert(db[group].__tokens == nil or type(db[group].__tokens) == "table")
147 srctab = loadstring("return {" .. QH_LZW_Decompress_Dicts_Prepared_Arghhacky(dat, db[group].__dictionary, nil, db[group].__tokens) .. "}")()
148 elseif type(dat) == "table" then
149 srctab = dat
150 else
151 QuestHelper: Assert()
154 for k, v in pairs(srctab) do
155 QuestHelper: Assert(not ite[k])
156 ite[k] = v
161 --print("dbe", ite)
163 if ite then
164 mark(ite, ite)
166 DBC_Put(group, id, ite)
168 freq_group[ite] = group
169 freq_id[ite] = id
170 else
171 if not silent then
172 QuestHelper:TextOut(string.format("Tried to get %s/%s, failed", tostring(group), tostring(id)))
177 if ite then
178 frequencies[ite] = (frequencies[ite] or 0) + (register and 1 or 1000000000) -- effectively infinity
181 return ite
184 local function incinerate(ite, crunchy)
185 if not crunchy[ite] then
186 crunchy[ite] = true
188 for k, v in pairs(ite) do
189 if type(k) == "table" then incinerate(k, crunchy) end
190 if type(v) == "table" then incinerate(v, crunchy) end
195 function DB_ReleaseItem(ite)
196 QuestHelper: Assert(ite)
197 frequencies[ite] = frequencies[ite] - 1
199 if frequencies[ite] == 0 then
200 --print("incinerating", freq_group[ite], freq_id[ite])
201 cache[freq_group[ite]][freq_id[ite]] = nil
202 freq_group[ite] = nil
203 freq_id[ite] = nil
205 local incin = QuestHelper:CreateTable("incinerate")
206 incinerate(ite, incin)
207 for k, _ in pairs(incin) do
208 QuestHelper:ReleaseTable(k)
209 end -- burn baby burn
210 QuestHelper:ReleaseTable(incin)
214 function DB_ListItems(group)
215 local tab = {}
216 for _, db in ipairs(QHDB) do
217 if db[group] then
218 QuestHelper: Assert(not db.__serialize_index and not db.__serialize_data)
219 for k, _ in pairs(db[group]) do
220 if type(k) ~= "string" or not k:match("__.*") then
221 tab[k] = true
227 local rv = {}
228 for k, _ in pairs(tab) do
229 table.insert(rv, k)
232 return rv
235 function DB_how_many_are_used()
236 local count = 0
237 for k, v in pairs(cache) do
238 for k2, v2 in pairs(v) do
239 count = count + 1
242 print(count)
245 function DB_DumpItems()
246 local dt = {}
247 for k, v in pairs(freq_group) do
248 dt[string.format("%s/%s", freq_group[k], tostring(freq_id[k]))] = true
250 return dt