-- Import local ffi = require 'ffi' local bit = require 'bit' -- Constants -------------------------------------------------------------------------------- -- Util local NUMBER_TO_HEX = { [00] = '0', [01] = '1', [02] = '2', [03] = '3', [04] = '4', [05] = '5', [06] = '6', [07] = '7', [08] = '8', [09] = '9', [10] = 'A', [11] = 'B', [12] = 'C', [13] = 'D', [14] = 'E', [15] = 'F', } local function to_hex (val, nr_elements, element_size) local l = {} for i = 0, nr_elements - 1 do local v = val[i] l[#l+1] = bit.tohex(v, -2*element_size) l[#l+1] = ' ' end l[#l] = nil return table.concat(l, '') end local function is_nice_unicode_string (str) -- TODO... Maybe also look into a purely binary oriented representation. return false end local function is_nice_ascii_string (str) for i = 1, #str do local byte = str:byte(i) if not (32 <= byte and byte <= 126) then return false end end return true end local function get_type_and_size_of_singular ( ctype ) local nr_elements, layers = 1, 0 while true do local etype, elements = ctype:match('(.+)%[(%d*)%]$') if not elements then break end ctype, nr_elements = etype, nr_elements * elements layers = layers + 1 end return ctype, nr_elements, layers end -------------------------------------------------------------------------------- local CDATA_REPR_MATCHER = 'cdata<(.+)>: (0x%w+)' local function format_cdata (value, options, depth, l, format_value) local native_repr = tostring(value) local data_length = ffi.sizeof(value) local ctype, addr = native_repr:match(CDATA_REPR_MATCHER) -- Is void pointer? if ctype == 'void *' then local address_pointing_at = tonumber(ffi.cast('int', value)) l[#l+1] = 'void pointer to ' .. addr return ; end -- Is normal pointer? if ctype:match('%*$') then if type(value[0]) ~= 'cdata' then -- Data presentable in Lua, refered to by pointers? l[#l+1] = 'pointer to ' return format_value(value[0], options, depth, l) else l[#l+1] = '* ' return format_cdata(value[0], options, depth, l, format_value) end end l[#l+1] = 'cdata {' --l[#l+1] = '\n\tnative = \'' .. native_repr .. '\',' l[#l+1] = '\n\ttype = ' .. ctype .. ',' l[#l+1] = '\n\taddr = ' .. addr .. ',' if data_length then -- Size local str = ffi.string(value, data_length) l[#l+1] = '\n\tsize = ' .. data_length .. ',' -- Element size and type local element_type, nr_elements, nr_layers = get_type_and_size_of_singular(ctype) local element_size = data_length / nr_elements l[#l+1] = '\n\tnr_e = ' .. nr_elements .. ',' l[#l+1] = '\n\ttype_e = ' .. element_type .. ',' l[#l+1] = '\n\tsize_e = ' .. element_size .. ',' -- If can be expressed as string, express it as string. if is_nice_ascii_string(str) or is_nice_unicode_string(str) then local string_or_unicode = is_nice_ascii_string(str) and 'ascii' or 'utf8 ' l[#l+1] = '\n\t'..string_or_unicode..' = ' .. str .. ',' end -- if nr_layers == 1 then -- Only a single level of arrays l[#l+1] = '\n\thex = ' .. to_hex(value, nr_elements, element_size) .. ',' end end l[#l+1] = '\n}' end return format_cdata