You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.0 KiB
Lua
110 lines
3.0 KiB
Lua
local base = string.match(..., "(.-)[^%.]+%.[^%.]+$")
|
|
local eh = require(base.."helper.enum")
|
|
local ffi = require("ffi")
|
|
local mth = require(base.."helper.mt")
|
|
|
|
local assert, error, pairs, select, type = assert, error, pairs, select, type
|
|
local getmetatable, setmetatable = getmetatable, setmetatable
|
|
local e_to_str, e_to_int = eh.to_str, eh.to_int
|
|
local ffi_copy = ffi.copy
|
|
|
|
local module = {}
|
|
|
|
local base_funcs = {}
|
|
function base_funcs:set_from_table(tbl)
|
|
for k,v in pairs(tbl) do
|
|
assert(k ~= "raw", "Can't set raw key")
|
|
self[k] = v
|
|
end
|
|
end
|
|
module.base_funcs = base_funcs
|
|
|
|
function module.base(mt, index, ct)
|
|
if type(ct) == "string" then ct = ffi.typeof(ct) end
|
|
index.struct_name = tostring(ct):match("ctype<struct (.*)>")
|
|
|
|
local size = ffi.sizeof(ct)
|
|
index.raw_struct_size = size
|
|
function index.clone(stuff)
|
|
local t = type(stuff)
|
|
if t == "cdata" then
|
|
return setmetatable({raw = ct(stuff)}, mt)
|
|
elseif t == "table" then
|
|
assert(getmetatable(stuff) == mt, "Wrong type")
|
|
return setmetatable({raw = ct(stuff.raw)}, mt)
|
|
end
|
|
end
|
|
|
|
local function new(...)
|
|
if select('#', ...) ~= 1 then
|
|
return setmetatable({raw = ct(...)}, mt)
|
|
end
|
|
|
|
local stuff = ...
|
|
local t = type(stuff)
|
|
local res
|
|
if t == "nil" then
|
|
res = setmetatable({raw = ct()}, mt)
|
|
elseif t == "cdata" then
|
|
res = setmetatable({raw = stuff}, mt)
|
|
elseif t == "table" and stuff.raw then
|
|
if getmetatable(stuff) ~= mt then
|
|
error("Wrong type "..tostring(stuff), 2)
|
|
end
|
|
res = stuff
|
|
elseif t == "table" then
|
|
res = setmetatable({raw = ct()}, mt)
|
|
res:set_from_table(stuff)
|
|
elseif t == "string" then
|
|
if #stuff ~= size then
|
|
error("String size mismatch (expected: "..size..", got: "..#stuff..")")
|
|
end
|
|
local x = ct()
|
|
ffi_copy(x, stuff, size)
|
|
res = setmetatable({raw = x}, mt)
|
|
else
|
|
error("Bad argument to ffi_struct constructor: "..t)
|
|
end
|
|
return res
|
|
end
|
|
index.new = new
|
|
|
|
setmetatable(index, {
|
|
__index = base_funcs,
|
|
__call = function(_, ...) return new(...) end,
|
|
})
|
|
mth.add_index_methods(mt, index)
|
|
return index
|
|
end
|
|
|
|
function module.gen_raw_accessor(index, name)
|
|
index["get_"..name] = function(self) return self.raw[name] end
|
|
index["set_"..name] = function(self, val) self.raw[name] = val end
|
|
end
|
|
|
|
function module.gen_wrap_accessor(index, name, wrap)
|
|
index["get_"..name] = function(self) return wrap(self.raw[name]) end
|
|
index["set_"..name] = function(self, ...) self.raw[name] = wrap(...).raw end
|
|
end
|
|
|
|
local function gen_enum_getter(index, enum, name)
|
|
index["get_"..name] = function(self)
|
|
return e_to_str(enum, self.raw[name])
|
|
end
|
|
end
|
|
module.gen_enum_getter = gen_enum_getter
|
|
|
|
local function gen_enum_setter(index, enum, name)
|
|
index["set_"..name] = function(self, val)
|
|
self.raw[name] = e_to_int(enum, val)
|
|
end
|
|
end
|
|
module.gen_enum_setter = gen_enum_setter
|
|
|
|
function module.gen_enum_accessor(index, enum, name)
|
|
gen_enum_getter(index, enum, name)
|
|
gen_enum_setter(index, enum, name)
|
|
end
|
|
|
|
return module
|