inputor

Evdev remapping utility in lua
git clone https://git.neptards.moe/u3shit/inputor.git
Log | Files | Refs

ffi_struct.lua (3117B)


      1 local base = string.match(..., "(.-)[^%.]+%.[^%.]+$")
      2 local eh = require(base.."helper.enum")
      3 local ffi = require("ffi")
      4 local mth = require(base.."helper.mt")
      5 
      6 local assert, error, pairs, select, type = assert, error, pairs, select, type
      7 local getmetatable, setmetatable = getmetatable, setmetatable
      8 local e_to_str, e_to_int = eh.to_str, eh.to_int
      9 local ffi_copy = ffi.copy
     10 
     11 local module = {}
     12 
     13 local base_funcs = {}
     14 function base_funcs:set_from_table(tbl)
     15   for k,v in pairs(tbl) do
     16     assert(k ~= "raw", "Can't set raw key")
     17     self[k] = v
     18   end
     19 end
     20 module.base_funcs = base_funcs
     21 
     22 function module.base(mt, index, ct)
     23   if type(ct) == "string" then ct = ffi.typeof(ct) end
     24   index.struct_name = tostring(ct):match("ctype<struct (.*)>")
     25 
     26   local size = ffi.sizeof(ct)
     27   index.raw_struct_size = size
     28   function index.clone(stuff)
     29     local t = type(stuff)
     30     if t == "cdata" then
     31       return setmetatable({raw = ct(stuff)}, mt)
     32     elseif t == "table" then
     33       assert(getmetatable(stuff) == mt, "Wrong type")
     34       return setmetatable({raw = ct(stuff.raw)}, mt)
     35     end
     36   end
     37 
     38   local function new(...)
     39     if select('#', ...) ~= 1 then
     40       return setmetatable({raw = ct(...)}, mt)
     41     end
     42 
     43     local stuff = ...
     44     local t = type(stuff)
     45     local res
     46     if t == "nil" then
     47       res = setmetatable({raw = ct()}, mt)
     48     elseif t == "cdata" then
     49       res = setmetatable({raw = stuff}, mt)
     50     elseif t == "table" and stuff.raw then
     51       if getmetatable(stuff) ~= mt then
     52         error("Wrong type "..tostring(stuff), 2)
     53       end
     54       res = stuff
     55     elseif t == "table" then
     56       res = setmetatable({raw = ct()}, mt)
     57       res:set_from_table(stuff)
     58     elseif t == "string" then
     59       if #stuff ~= size then
     60         error("String size mismatch (expected: "..size..", got: "..#stuff..")")
     61       end
     62       local x = ct()
     63       ffi_copy(x, stuff, size)
     64       res = setmetatable({raw = x}, mt)
     65     else
     66       error("Bad argument to ffi_struct constructor: "..t)
     67     end
     68     return res
     69   end
     70   index.new = new
     71 
     72   setmetatable(index, {
     73                  __index = base_funcs,
     74                  __call = function(_, ...) return new(...) end,
     75   })
     76   mth.add_index_methods(mt, index)
     77   return index
     78 end
     79 
     80 function module.gen_raw_accessor(index, name)
     81   index["get_"..name] = function(self) return self.raw[name] end
     82   index["set_"..name] = function(self, val) self.raw[name] = val end
     83 end
     84 
     85 function module.gen_wrap_accessor(index, name, wrap)
     86   index["get_"..name] = function(self) return wrap(self.raw[name]) end
     87   index["set_"..name] = function(self, ...) self.raw[name] = wrap(...).raw end
     88 end
     89 
     90 local function gen_enum_getter(index, enum, name)
     91   index["get_"..name] = function(self)
     92     return e_to_str(enum, self.raw[name])
     93   end
     94 end
     95 module.gen_enum_getter = gen_enum_getter
     96 
     97 local function gen_enum_setter(index, enum, name)
     98   index["set_"..name] = function(self, val)
     99     self.raw[name] = e_to_int(enum, val)
    100   end
    101 end
    102 module.gen_enum_setter = gen_enum_setter
    103 
    104 function module.gen_enum_accessor(index, enum, name)
    105   gen_enum_getter(index, enum, name)
    106   gen_enum_setter(index, enum, name)
    107 end
    108 
    109 return module