diff support/casc/dbc.lua @ 65:8b8b0bade520

Fixed support for mounts using the new MountJournal and mount IDs (no conversion of old profiles at the moment).
author Jerome Vuarand <jerome.vuarand@gmail.com>
date Thu, 23 Oct 2014 13:44:59 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/support/casc/dbc.lua	Thu Oct 23 13:44:59 2014 +0100
@@ -0,0 +1,85 @@
+local M, bin = {}, require("casc.bin")
+local assert, loadstring, smatch = assert, loadstring or load, string.match
+
+local uint32_le, int32_le, float32_le = bin.uint32_le, bin.int32_le, bin.float32_le
+
+local function unpacker(data, format, rows, stride, hsize, sbase, tfunc)
+	tfunc = type(tfunc) == "function" and tfunc or nil
+	
+	local skip, p, pe = 0, [=[-- casc.dbc:iterator
+		local smatch, uint32_le, int32_le, float32_le, tfunc, data, rows, stride, sbase, rpos, i = ...
+		return function()
+			if i < rows then
+				rpos, i = rpos + stride, i + 1
+				return ]=] .. (tfunc and "tfunc(i" or "i"), (tfunc and ")" or "") .. '\nend\nend'
+	
+	for r, t in format:gmatch("(%d*)(.)") do
+		r = tonumber(r) or 1
+		for i=1,r do
+			if t == '.' then
+				skip = skip + 4 * r
+				break
+			elseif t == 'u' then
+				p, skip = p .. ', uint32_le(data, rpos+' .. skip .. ')', skip + 4
+			elseif t == 'i' then
+				p, skip = p .. ', int32_le(data, rpos+' .. skip .. ')', skip + 4
+			elseif t == 'f' then
+				p, skip = p .. ', float32_le(data, rpos+' .. skip .. ')', skip + 4
+			elseif t == 's' then
+				assert(sbase, "invalid signature: 's' requires a string block")
+				p, skip = p .. ', smatch(data, "%Z*", sbase + uint32_le(data,rpos+' .. skip .. '))', skip + 4
+			else
+				error('Unknown signature field type "' .. t .. '"')
+			end
+		end
+	end
+
+	return loadstring(p .. pe)(smatch, uint32_le, int32_le, float32_le,
+		tfunc, data, rows, stride, sbase, hsize - stride, 0), skip
+end
+
+local header do
+	local function dbc(data)
+		assert(data:sub(1,4) == "WDBC", "DBC magic signature")
+		local rows, fields, stride, stringSize = uint32_le(data, 4), uint32_le(data, 8), uint32_le(data, 12), uint32_le(data, 16)
+		assert(20 + rows*stride + stringSize <= #data, "Data too short")
+	
+		return rows, fields, stride, 20, 21 + rows * stride
+	end
+	local function db2(data)
+		local hsize = 48
+		local rows, fields, stride, stringSize = uint32_le(data, 4), uint32_le(data, 8), uint32_le(data, 12), uint32_le(data, 16)
+		local build, minId, maxId, locale, rid = uint32_le(data, 24), uint32_le(data, 32), uint32_le(data, 36), uint32_le(data, 40)
+	
+		if maxId > 0 then
+			local n, p = maxId-minId + 1, hsize
+			rid, hsize = {}, hsize + 6 * n
+			for i=1,n do
+				rid[i], p = uint32_le(data, p), p + 6
+			end
+		end
+		assert(hsize + rows*stride + stringSize <= #data, "Data too short")
+	
+		return rows, fields, stride, hsize, hsize + 1 + rows * stride, rid, minId, maxId, build, locale
+	end
+	header = {WDBC=dbc, WDB2=db2, WCH2=db2}
+end
+
+function M.header(data)
+	assert(type(data) == "string", 'Syntax: casc.dbc.header("data")')
+	local fourCC = data:sub(1,4)
+	return assert(header[fourCC], "Unsupported format")(data)
+end
+
+function M.rows(data, sig, loose)
+	assert(type(data) == "string" and type(sig) == "string", 'Syntax: casc.dbc.rows("data", "rowSignature"[, loose])')
+	
+	local rows, _, stride, hsize, sbase, rid = M.header(data)
+	local iter, skip = unpacker(data, sig, rows, stride, hsize, sbase, rid and function(i, ...) return rid[i], ... end)
+	assert(skip <= stride, 'signature exceeds stride')
+	assert(loose or skip == stride, 'signature/stride mismatch')
+
+	return iter
+end
+
+return M