1
0
pretty/cdata.lua

114 lines
3.1 KiB
Lua

-- 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