jerome@65
|
1 local M, bin = {}, require("casc.bin")
|
jerome@65
|
2 local assert, loadstring, smatch = assert, loadstring or load, string.match
|
jerome@65
|
3
|
jerome@65
|
4 local uint32_le, int32_le, float32_le = bin.uint32_le, bin.int32_le, bin.float32_le
|
jerome@65
|
5
|
jerome@65
|
6 local function unpacker(data, format, rows, stride, hsize, sbase, tfunc)
|
jerome@65
|
7 tfunc = type(tfunc) == "function" and tfunc or nil
|
jerome@65
|
8
|
jerome@65
|
9 local skip, p, pe = 0, [=[-- casc.dbc:iterator
|
jerome@65
|
10 local smatch, uint32_le, int32_le, float32_le, tfunc, data, rows, stride, sbase, rpos, i = ...
|
jerome@65
|
11 return function()
|
jerome@65
|
12 if i < rows then
|
jerome@65
|
13 rpos, i = rpos + stride, i + 1
|
jerome@65
|
14 return ]=] .. (tfunc and "tfunc(i" or "i"), (tfunc and ")" or "") .. '\nend\nend'
|
jerome@65
|
15
|
jerome@65
|
16 for r, t in format:gmatch("(%d*)(.)") do
|
jerome@65
|
17 r = tonumber(r) or 1
|
jerome@65
|
18 for i=1,r do
|
jerome@65
|
19 if t == '.' then
|
jerome@65
|
20 skip = skip + 4 * r
|
jerome@65
|
21 break
|
jerome@65
|
22 elseif t == 'u' then
|
jerome@65
|
23 p, skip = p .. ', uint32_le(data, rpos+' .. skip .. ')', skip + 4
|
jerome@65
|
24 elseif t == 'i' then
|
jerome@65
|
25 p, skip = p .. ', int32_le(data, rpos+' .. skip .. ')', skip + 4
|
jerome@65
|
26 elseif t == 'f' then
|
jerome@65
|
27 p, skip = p .. ', float32_le(data, rpos+' .. skip .. ')', skip + 4
|
jerome@65
|
28 elseif t == 's' then
|
jerome@65
|
29 assert(sbase, "invalid signature: 's' requires a string block")
|
jerome@65
|
30 p, skip = p .. ', smatch(data, "%Z*", sbase + uint32_le(data,rpos+' .. skip .. '))', skip + 4
|
jerome@65
|
31 else
|
jerome@65
|
32 error('Unknown signature field type "' .. t .. '"')
|
jerome@65
|
33 end
|
jerome@65
|
34 end
|
jerome@65
|
35 end
|
jerome@65
|
36
|
jerome@65
|
37 return loadstring(p .. pe)(smatch, uint32_le, int32_le, float32_le,
|
jerome@65
|
38 tfunc, data, rows, stride, sbase, hsize - stride, 0), skip
|
jerome@65
|
39 end
|
jerome@65
|
40
|
jerome@65
|
41 local header do
|
jerome@65
|
42 local function dbc(data)
|
jerome@65
|
43 assert(data:sub(1,4) == "WDBC", "DBC magic signature")
|
jerome@65
|
44 local rows, fields, stride, stringSize = uint32_le(data, 4), uint32_le(data, 8), uint32_le(data, 12), uint32_le(data, 16)
|
jerome@65
|
45 assert(20 + rows*stride + stringSize <= #data, "Data too short")
|
jerome@65
|
46
|
jerome@65
|
47 return rows, fields, stride, 20, 21 + rows * stride
|
jerome@65
|
48 end
|
jerome@65
|
49 local function db2(data)
|
jerome@65
|
50 local hsize = 48
|
jerome@65
|
51 local rows, fields, stride, stringSize = uint32_le(data, 4), uint32_le(data, 8), uint32_le(data, 12), uint32_le(data, 16)
|
jerome@65
|
52 local build, minId, maxId, locale, rid = uint32_le(data, 24), uint32_le(data, 32), uint32_le(data, 36), uint32_le(data, 40)
|
jerome@65
|
53
|
jerome@65
|
54 if maxId > 0 then
|
jerome@65
|
55 local n, p = maxId-minId + 1, hsize
|
jerome@65
|
56 rid, hsize = {}, hsize + 6 * n
|
jerome@65
|
57 for i=1,n do
|
jerome@65
|
58 rid[i], p = uint32_le(data, p), p + 6
|
jerome@65
|
59 end
|
jerome@65
|
60 end
|
jerome@65
|
61 assert(hsize + rows*stride + stringSize <= #data, "Data too short")
|
jerome@65
|
62
|
jerome@65
|
63 return rows, fields, stride, hsize, hsize + 1 + rows * stride, rid, minId, maxId, build, locale
|
jerome@65
|
64 end
|
jerome@65
|
65 header = {WDBC=dbc, WDB2=db2, WCH2=db2}
|
jerome@65
|
66 end
|
jerome@65
|
67
|
jerome@65
|
68 function M.header(data)
|
jerome@65
|
69 assert(type(data) == "string", 'Syntax: casc.dbc.header("data")')
|
jerome@65
|
70 local fourCC = data:sub(1,4)
|
jerome@65
|
71 return assert(header[fourCC], "Unsupported format")(data)
|
jerome@65
|
72 end
|
jerome@65
|
73
|
jerome@65
|
74 function M.rows(data, sig, loose)
|
jerome@65
|
75 assert(type(data) == "string" and type(sig) == "string", 'Syntax: casc.dbc.rows("data", "rowSignature"[, loose])')
|
jerome@65
|
76
|
jerome@65
|
77 local rows, _, stride, hsize, sbase, rid = M.header(data)
|
jerome@65
|
78 local iter, skip = unpacker(data, sig, rows, stride, hsize, sbase, rid and function(i, ...) return rid[i], ... end)
|
jerome@65
|
79 assert(skip <= stride, 'signature exceeds stride')
|
jerome@65
|
80 assert(loose or skip == stride, 'signature/stride mismatch')
|
jerome@65
|
81
|
jerome@65
|
82 return iter
|
jerome@65
|
83 end
|
jerome@65
|
84
|
jerome@65
|
85 return M
|