Experimentations with pointer types.
This commit is contained in:
parent
ffbbfef499
commit
0a79a8a77a
62
cdata.lua
62
cdata.lua
|
@ -2,6 +2,7 @@
|
||||||
-- Import
|
-- Import
|
||||||
|
|
||||||
local ffi = require 'ffi'
|
local ffi = require 'ffi'
|
||||||
|
local bit = require 'bit'
|
||||||
|
|
||||||
-- Constants
|
-- Constants
|
||||||
|
|
||||||
|
@ -14,18 +15,22 @@ local NUMBER_TO_HEX = {
|
||||||
[12] = 'C', [13] = 'D', [14] = 'E', [15] = 'F',
|
[12] = 'C', [13] = 'D', [14] = 'E', [15] = 'F',
|
||||||
}
|
}
|
||||||
|
|
||||||
local function to_hex (str)
|
local function to_hex (val, nr_elements, element_size)
|
||||||
local l = {}
|
local l = {}
|
||||||
for i = 1, #str do
|
for i = 0, nr_elements - 1 do
|
||||||
local v = str:byte(i)
|
local v = val[i]
|
||||||
l[#l+1] = NUMBER_TO_HEX[math.floor(v / 16)]
|
l[#l+1] = bit.tohex(v, -2*element_size)
|
||||||
l[#l+1] = NUMBER_TO_HEX[v % 16]
|
|
||||||
l[#l+1] = ' '
|
l[#l+1] = ' '
|
||||||
end
|
end
|
||||||
l[#l] = nil
|
l[#l] = nil
|
||||||
return table.concat(l, '')
|
return table.concat(l, '')
|
||||||
end
|
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)
|
local function is_nice_ascii_string (str)
|
||||||
for i = 1, #str do
|
for i = 1, #str do
|
||||||
local byte = str:byte(i)
|
local byte = str:byte(i)
|
||||||
|
@ -35,24 +40,45 @@ local function is_nice_ascii_string (str)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_type_and_size_of_singular ( ctype )
|
local function get_type_and_size_of_singular ( ctype )
|
||||||
local nr_elements = 1
|
local nr_elements, layers = 1, 0
|
||||||
while true do
|
while true do
|
||||||
local etype, elements = ctype:match('(.+)%[(%d*)%]$')
|
local etype, elements = ctype:match('(.+)%[(%d*)%]$')
|
||||||
if not elements then break end
|
if not elements then break end
|
||||||
ctype, nr_elements = etype, nr_elements * elements
|
ctype, nr_elements = etype, nr_elements * elements
|
||||||
|
layers = layers + 1
|
||||||
end
|
end
|
||||||
return ctype, nr_elements
|
return ctype, nr_elements, layers
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local CDATA_REPR_MATCHER = 'cdata<(.+)>: (0x%w+)'
|
local CDATA_REPR_MATCHER = 'cdata<(.+)>: (0x%w+)'
|
||||||
|
|
||||||
return function (value, options, depth, l)
|
local function format_cdata (value, options, depth, l, format_value)
|
||||||
|
|
||||||
local native_repr = tostring(value)
|
local native_repr = tostring(value)
|
||||||
local data_length = ffi.sizeof(value)
|
local data_length = ffi.sizeof(value)
|
||||||
local ctype, addr = native_repr:match(CDATA_REPR_MATCHER)
|
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] = 'cdata {'
|
||||||
--l[#l+1] = '\n\tnative = \'' .. native_repr .. '\','
|
--l[#l+1] = '\n\tnative = \'' .. native_repr .. '\','
|
||||||
l[#l+1] = '\n\ttype = ' .. ctype .. ','
|
l[#l+1] = '\n\ttype = ' .. ctype .. ','
|
||||||
|
@ -63,21 +89,25 @@ return function (value, options, depth, l)
|
||||||
l[#l+1] = '\n\tsize = ' .. data_length .. ','
|
l[#l+1] = '\n\tsize = ' .. data_length .. ','
|
||||||
|
|
||||||
-- Element size and type
|
-- Element size and type
|
||||||
local element_type, nr_elements = get_type_and_size_of_singular(ctype)
|
local element_type, nr_elements, nr_layers = get_type_and_size_of_singular(ctype)
|
||||||
local element_size = data_length / nr_elements
|
local element_size = data_length / nr_elements
|
||||||
l[#l+1] = '\n\tnr_e = ' .. nr_elements .. ','
|
l[#l+1] = '\n\tnr_e = ' .. nr_elements .. ','
|
||||||
l[#l+1] = '\n\ttype_e = ' .. element_type .. ','
|
l[#l+1] = '\n\ttype_e = ' .. element_type .. ','
|
||||||
l[#l+1] = '\n\tsize_e = ' .. element_size .. ','
|
l[#l+1] = '\n\tsize_e = ' .. element_size .. ','
|
||||||
|
|
||||||
--
|
-- If can be expressed as string, express it as string.
|
||||||
if is_nice_ascii_string(str) then
|
if is_nice_ascii_string(str) or is_nice_unicode_string(str) then
|
||||||
l[#l+1] = '\n\tstr = ' .. str .. ','
|
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\tbin = ' .. to_hex(str) .. ','
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
l[#l+1] = '\n}'
|
l[#l+1] = '\n}'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return format_cdata
|
||||||
|
|
|
@ -19,15 +19,12 @@ local function format_test (t)
|
||||||
if t.longterm then return end
|
if t.longterm then return end
|
||||||
if t.adv_getlocal and not HAS_ADV_GETLOCAL then return end
|
if t.adv_getlocal and not HAS_ADV_GETLOCAL then return end
|
||||||
SUITE:addTest(t.expect, function ()
|
SUITE:addTest(t.expect, function ()
|
||||||
local input_value = t.input
|
local actual_result = format(t.input, t.options)
|
||||||
local input_options = t.options
|
|
||||||
local expected_result = t.expect
|
|
||||||
local actual_result = format(input_value, input_options)
|
|
||||||
if not t.approx or type(actual_result) ~= 'string' then
|
if not t.approx or type(actual_result) ~= 'string' then
|
||||||
assert_equal(expected_result, actual_result)
|
assert_equal(t.expect, actual_result)
|
||||||
else
|
else
|
||||||
if not actual_result:match(expected_result) then
|
if not actual_result:match(t.expect) then
|
||||||
error(ASSERT_ERROR_APPROX:format(expected_result, actual_result))
|
error(ASSERT_ERROR_APPROX:format(t.expect, actual_result))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -372,6 +369,10 @@ if type(jit) == 'table' then
|
||||||
|
|
||||||
local ffi = require('ffi')
|
local ffi = require('ffi')
|
||||||
ffi.cdef[[
|
ffi.cdef[[
|
||||||
|
typedef struct foo { int a, b; } foo_t;
|
||||||
|
|
||||||
|
void free(void *ptr);
|
||||||
|
void *malloc(size_t size);
|
||||||
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
|
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
@ -389,6 +390,15 @@ if type(jit) == 'table' then
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local list = ffi.new('int [17]')
|
||||||
|
for i = 0, 16 do list[i] = i end
|
||||||
|
format_test {
|
||||||
|
input = list,
|
||||||
|
expect = 'cdata<.+>: 0x%x+',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
local list = ffi.new('char [10]')
|
local list = ffi.new('char [10]')
|
||||||
for i = 0, 10-1 do list[i] = i + 65 end
|
for i = 0, 10-1 do list[i] = i + 65 end
|
||||||
|
@ -406,6 +416,31 @@ if type(jit) == 'table' then
|
||||||
expect = 'cdata<.+>: 0x%x+',
|
expect = 'cdata<.+>: 0x%x+',
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local p = ffi.gc(ffi.C.malloc(1), ffi.C.free)
|
||||||
|
format_test {
|
||||||
|
input = p,
|
||||||
|
expect = 'cdata<.+>: 0x%x+',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
SUITE:addTest('a_very_small_part_of_math', function ()
|
||||||
|
local p = ffi.new('char[1]')
|
||||||
|
p[0] = 27
|
||||||
|
local actual_result = format(p + 0, {})
|
||||||
|
assert_equal('Derp', actual_result)
|
||||||
|
end)
|
||||||
|
|
||||||
|
do
|
||||||
|
local p = ffi.new('foo_t[1]')
|
||||||
|
p[0].a = 27
|
||||||
|
p[0].b = 27
|
||||||
|
format_test {
|
||||||
|
input = p + 0,
|
||||||
|
expect = 'cdata<.+>: 0x%x+',
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user