Commit 4f8a3f1b authored by François Perrad's avatar François Perrad
Browse files

refactor without types_map indirection

parent 8729848c
Revision history for lua-MessagePack
0.4.0
refactor without types_map indirection
0.3.7 Sun Dec 4 17:30:00 2016
better use of string.pack (Lua 5.3)
......
......@@ -28,6 +28,7 @@ local setmetatable = setmetatable
local tostring = tostring
local type = type
local char = require'string'.char
local format = require'string'.format
local floor = require'math'.floor
local tointeger = require'math'.tointeger or floor
local frexp = require'math'.frexp or require'mathx'.frexp
......@@ -35,17 +36,13 @@ local ldexp = require'math'.ldexp or require'mathx'.ldexp
local huge = require'math'.huge
local tconcat = require'table'.concat
--[[ debug only
local format = require'string'.format
local function hexadump (s)
return (s:gsub('.', function (c) return format('%02X ', c:byte()) end))
end
--]]
local _ENV = nil
local m = {}
--[[ debug only
local function hexadump (s)
return (s:gsub('.', function (c) return format('%02X ', c:byte()) end))
end
m.hexadump = hexadump
--]]
......@@ -525,77 +522,32 @@ function m.pack (data)
end
local types_map = setmetatable({
[0xC0] = 'nil',
[0xC2] = 'false',
[0xC3] = 'true',
[0xC4] = 'bin8',
[0xC5] = 'bin16',
[0xC6] = 'bin32',
[0xC7] = 'ext8',
[0xC8] = 'ext16',
[0xC9] = 'ext32',
[0xCA] = 'float',
[0xCB] = 'double',
[0xCC] = 'uint8',
[0xCD] = 'uint16',
[0xCE] = 'uint32',
[0xCF] = 'uint64',
[0xD0] = 'int8',
[0xD1] = 'int16',
[0xD2] = 'int32',
[0xD3] = 'int64',
[0xD4] = 'fixext1',
[0xD5] = 'fixext2',
[0xD6] = 'fixext4',
[0xD7] = 'fixext8',
[0xD8] = 'fixext16',
[0xD9] = 'str8',
[0xDA] = 'str16',
[0xDB] = 'str32',
[0xDC] = 'array16',
[0xDD] = 'array32',
[0xDE] = 'map16',
[0xDF] = 'map32',
}, { __index = function (t, k)
if k < 0xC0 then
if k < 0x80 then
return 'fixnum_pos'
elseif k < 0x90 then
return 'fixmap'
elseif k < 0xA0 then
return 'fixarray'
else
return 'fixstr'
end
elseif k > 0xDF then
return 'fixnum_neg'
else
return 'reserved' .. tostring(k)
end
end })
m.types_map = types_map
local unpackers -- forward declaration
local unpackers = setmetatable({}, {
__index = function (t, k) error("unpack '" .. k .. "' is unimplemented") end
})
m.unpackers = unpackers
local function _unpack (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
s, i, j = c.s, c.i, c.j
end
local val = s:sub(i, i):byte()
c.i = i+1
return unpackers[val](c, val)
end
local function unpack_array (c, n)
local t = {}
local decode = unpackers['any']
for i = 1, n do
t[i] = decode(c)
t[i] = _unpack(c)
end
return t
end
local function unpack_map (c, n)
local t = {}
local decode = unpackers['any']
for i = 1, n do
local k = decode(c)
local val = decode(c)
local k = _unpack(c)
local val = _unpack(c)
if k == nil or k ~= k then
k = m.sentinel
end
......@@ -606,30 +558,7 @@ local function unpack_map (c, n)
return t
end
unpackers['any'] = function (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
s, i, j = c.s, c.i, c.j
end
local val = s:sub(i, i):byte()
c.i = i+1
return unpackers[types_map[val]](c, val)
end
unpackers['nil'] = function ()
return nil
end
unpackers['false'] = function ()
return false
end
unpackers['true'] = function ()
return true
end
unpackers['float'] = function (c)
local function unpack_float (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -660,7 +589,7 @@ unpackers['float'] = function (c)
return n
end
unpackers['double'] = function (c)
local function unpack_double (c)
local s, i, j = c.s, c.i, c.j
if i+7 > j then
c:underflow(i+7)
......@@ -691,11 +620,7 @@ unpackers['double'] = function (c)
return n
end
unpackers['fixnum_pos'] = function (c, val)
return val
end
unpackers['uint8'] = function (c)
local function unpack_uint8 (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
......@@ -706,7 +631,7 @@ unpackers['uint8'] = function (c)
return b1
end
unpackers['uint16'] = function (c)
local function unpack_uint16 (c)
local s, i, j = c.s, c.i, c.j
if i+1 > j then
c:underflow(i+1)
......@@ -717,7 +642,7 @@ unpackers['uint16'] = function (c)
return b1 * 0x100 + b2
end
unpackers['uint32'] = function (c)
local function unpack_uint32 (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -728,7 +653,7 @@ unpackers['uint32'] = function (c)
return ((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4
end
unpackers['uint64'] = function (c)
local function unpack_uint64 (c)
local s, i, j = c.s, c.i, c.j
if i+7 > j then
c:underflow(i+7)
......@@ -739,11 +664,7 @@ unpackers['uint64'] = function (c)
return ((((((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
end
unpackers['fixnum_neg'] = function (c, val)
return val - 0x100
end
unpackers['int8'] = function (c)
local function unpack_int8 (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
......@@ -758,7 +679,7 @@ unpackers['int8'] = function (c)
end
end
unpackers['int16'] = function (c)
local function unpack_int16 (c)
local s, i, j = c.s, c.i, c.j
if i+1 > j then
c:underflow(i+1)
......@@ -773,7 +694,7 @@ unpackers['int16'] = function (c)
end
end
unpackers['int32'] = function (c)
local function unpack_int32 (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -788,7 +709,7 @@ unpackers['int32'] = function (c)
end
end
unpackers['int64'] = function (c)
local function unpack_int64 (c)
local s, i, j = c.s, c.i, c.j
if i+7 > j then
c:underflow(i+7)
......@@ -803,7 +724,7 @@ unpackers['int64'] = function (c)
end
end
unpackers['fixstr'] = function (c, val)
local function unpack_fixstr (c, val)
local s, i, j = c.s, c.i, c.j
local n = val % 0x20
local e = i+n-1
......@@ -816,7 +737,7 @@ unpackers['fixstr'] = function (c, val)
return s:sub(i, e)
end
unpackers['str8'] = function (c)
local function unpack_str8 (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
......@@ -835,7 +756,7 @@ unpackers['str8'] = function (c)
return s:sub(i, e)
end
unpackers['str16'] = function (c)
local function unpack_str16 (c)
local s, i, j = c.s, c.i, c.j
if i+1 > j then
c:underflow(i+1)
......@@ -855,7 +776,7 @@ unpackers['str16'] = function (c)
return s:sub(i, e)
end
unpackers['str32'] = function (c)
local function unpack_str32 (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -875,15 +796,7 @@ unpackers['str32'] = function (c)
return s:sub(i, e)
end
unpackers['bin8'] = unpackers['str8']
unpackers['bin16'] = unpackers['str16']
unpackers['bin32'] = unpackers['str32']
unpackers['fixarray'] = function (c, val)
return unpack_array(c, val % 0x10)
end
unpackers['array16'] = function (c)
local function unpack_array16 (c)
local s, i, j = c.s, c.i, c.j
if i+1 > j then
c:underflow(i+1)
......@@ -894,7 +807,7 @@ unpackers['array16'] = function (c)
return unpack_array(c, b1 * 0x100 + b2)
end
unpackers['array32'] = function (c)
local function unpack_array32 (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -905,11 +818,7 @@ unpackers['array32'] = function (c)
return unpack_array(c, ((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4)
end
unpackers['fixmap'] = function (c, val)
return unpack_map(c, val % 0x10)
end
unpackers['map16'] = function (c)
local function unpack_map16 (c)
local s, i, j = c.s, c.i, c.j
if i+1 > j then
c:underflow(i+1)
......@@ -920,7 +829,7 @@ unpackers['map16'] = function (c)
return unpack_map(c, b1 * 0x100 + b2)
end
unpackers['map32'] = function (c)
local function unpack_map32 (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -935,29 +844,26 @@ function m.build_ext (tag, data)
return nil
end
for k = 0, 4 do
local n = tointeger(2^k)
unpackers['fixext' .. tostring(n)] = function (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
s, i, j = c.s, c.i, c.j
end
local tag = s:sub(i, i):byte()
i = i+1
c.i = i
local e = i+n-1
if e > j then
c:underflow(e)
s, i, j = c.s, c.i, c.j
e = i+n-1
end
c.i = i+n
return m.build_ext(tag < 0x80 and tag or tag - 0x100, s:sub(i, e))
local function unpack_fixext (c, n)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
s, i, j = c.s, c.i, c.j
end
local tag = s:sub(i, i):byte()
i = i+1
c.i = i
local e = i+n-1
if e > j then
c:underflow(e)
s, i, j = c.s, c.i, c.j
e = i+n-1
end
c.i = i+n
return m.build_ext(tag, s:sub(i, e))
end
unpackers['ext8'] = function (c)
local function unpack_ext8 (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
......@@ -983,7 +889,7 @@ unpackers['ext8'] = function (c)
return m.build_ext(tag < 0x80 and tag or tag - 0x100, s:sub(i, e))
end
unpackers['ext16'] = function (c)
local function unpack_ext16 (c)
local s, i, j = c.s, c.i, c.j
if i+1 > j then
c:underflow(i+1)
......@@ -1010,7 +916,7 @@ unpackers['ext16'] = function (c)
return m.build_ext(tag < 0x80 and tag or tag - 0x100, s:sub(i, e))
end
unpackers['ext32'] = function (c)
local function unpack_ext32 (c)
local s, i, j = c.s, c.i, c.j
if i+3 > j then
c:underflow(i+3)
......@@ -1037,6 +943,58 @@ unpackers['ext32'] = function (c)
return m.build_ext(tag < 0x80 and tag or tag - 0x100, s:sub(i, e))
end
unpackers = {
[0xC0] = function () return nil end,
[0xC2] = function () return false end,
[0xC3] = function () return true end,
[0xC4] = unpack_str8, -- bin8
[0xC5] = unpack_str16, -- bin16
[0xC6] = unpack_str32, -- bin32
[0xC7] = unpack_ext8,
[0xC8] = unpack_ext16,
[0xC9] = unpack_ext32,
[0xCA] = unpack_float,
[0xCB] = unpack_double,
[0xCC] = unpack_uint8,
[0xCD] = unpack_uint16,
[0xCE] = unpack_uint32,
[0xCF] = unpack_uint64,
[0xD0] = unpack_int8,
[0xD1] = unpack_int16,
[0xD2] = unpack_int32,
[0xD3] = unpack_int64,
[0xD4] = function (c) return unpack_fixext(c, 1) end,
[0xD5] = function (c) return unpack_fixext(c, 2) end,
[0xD6] = function (c) return unpack_fixext(c, 4) end,
[0xD7] = function (c) return unpack_fixext(c, 8) end,
[0xD8] = function (c) return unpack_fixext(c, 16) end,
[0xD9] = unpack_str8,
[0xDA] = unpack_str16,
[0xDB] = unpack_str32,
[0xDC] = unpack_array16,
[0xDD] = unpack_array32,
[0xDE] = unpack_map16,
[0xDF] = unpack_map32,
}
m.unpackers = setmetatable(unpackers, {
__index = function (t, k)
if k < 0xC0 then
if k < 0x80 then
return function (c, val) return val end
elseif k < 0x90 then
return function (c, val) return unpack_map(c, val % 0x10) end
elseif k < 0xA0 then
return function (c, val) return unpack_array(c, val % 0x10) end
else
return unpack_fixstr
end
elseif k > 0xDF then
return function (c, val) return val - 0x100 end
else
return function () error("unpack '" .. format('0x%X', k) .. "' is unimplemented") end
end
end
})
local function cursor_string (str)
return {
......@@ -1074,7 +1032,7 @@ end
function m.unpack (s)
checktype('unpack', 1, s, 'string')
local cursor = cursor_string(s)
local data = unpackers['any'](cursor)
local data = _unpack(cursor)
if cursor.i < cursor.j then
error "extra bytes"
end
......@@ -1086,7 +1044,7 @@ function m.unpacker (src)
local cursor = cursor_string(src)
return function ()
if cursor.i <= cursor.j then
return cursor.i, unpackers['any'](cursor)
return cursor.i, _unpack(cursor)
end
end
elseif type(src) == 'function' then
......@@ -1096,7 +1054,7 @@ function m.unpacker (src)
pcall(cursor.underflow, cursor, cursor.i)
end
if cursor.i <= cursor.j then
return true, unpackers['any'](cursor)
return true, _unpack(cursor)
end
end
else
......@@ -1112,9 +1070,9 @@ elseif SIZEOF_NUMBER == 4 then
maxinteger = 16777215
mininteger = -maxinteger
m.small_lua = true
unpackers['double'] = nil
unpackers['uint64'] = nil
unpackers['int64'] = nil
unpackers[0xCB] = nil -- double
unpackers[0xCF] = nil -- uint64
unpackers[0xD3] = nil -- int64
set_number'float'
else
maxinteger = 9007199254740991
......@@ -1126,7 +1084,7 @@ else
end
set_array'without_hole'
m._VERSION = '0.3.7'
m._VERSION = '0.4.0'
m._DESCRIPTION = "lua-MessagePack : a pure Lua implementation"
m._COPYRIGHT = "Copyright (c) 2012-2016 Francois Perrad"
return m
......
......@@ -10,23 +10,20 @@ local setmetatable = setmetatable
local tostring = tostring
local type = type
local char = require'string'.char
local format = require'string'.format
local math_type = require'math'.type
local tointeger = require'math'.tointeger
local tconcat = require'table'.concat
local pack = require'string'.pack
local unpack = require'string'.unpack
--[[ debug only
local format = require'string'.format
local function hexadump (s)
return (s:gsub('.', function (c) return format('%02X ', c:byte()) end))
end
--]]
local _ENV = nil
local m = {}
--[[ debug only
local function hexadump (s)
return (s:gsub('.', function (c) return format('%02X ', c:byte()) end))
end
m.hexadump = hexadump
--]]
......@@ -340,77 +337,32 @@ function m.pack (data)
end
local types_map = setmetatable({
[0xC0] = 'nil',
[0xC2] = 'false',
[0xC3] = 'true',
[0xC4] = 'bin8',
[0xC5] = 'bin16',
[0xC6] = 'bin32',
[0xC7] = 'ext8',
[0xC8] = 'ext16',
[0xC9] = 'ext32',
[0xCA] = 'float',
[0xCB] = 'double',
[0xCC] = 'uint8',
[0xCD] = 'uint16',
[0xCE] = 'uint32',
[0xCF] = 'uint64',
[0xD0] = 'int8',
[0xD1] = 'int16',
[0xD2] = 'int32',
[0xD3] = 'int64',
[0xD4] = 'fixext1',
[0xD5] = 'fixext2',
[0xD6] = 'fixext4',
[0xD7] = 'fixext8',
[0xD8] = 'fixext16',
[0xD9] = 'str8',
[0xDA] = 'str16',
[0xDB] = 'str32',
[0xDC] = 'array16',
[0xDD] = 'array32',
[0xDE] = 'map16',
[0xDF] = 'map32',
}, { __index = function (t, k)
if k < 0xC0 then
if k < 0x80 then
return 'fixnum_pos'
elseif k < 0x90 then
return 'fixmap'
elseif k < 0xA0 then
return 'fixarray'
else
return 'fixstr'
end
elseif k > 0xDF then
return 'fixnum_neg'
else
return 'reserved' .. tostring(k)
end
end })
m.types_map = types_map
local unpackers -- forward declaration
local unpackers = setmetatable({}, {
__index = function (t, k) error("unpack '" .. k .. "' is unimplemented") end
})
m.unpackers = unpackers
local function _unpack (c)
local s, i, j = c.s, c.i, c.j
if i > j then
c:underflow(i)
s, i, j = c.s, c.i, c.j
end
local val = s:sub(i, i):byte()
c.i = i+1
return unpackers[val](c, val)
end
local function unpack_array (c, n)
local t = {}
local decode = unpackers['any']
for i = 1, n do
t[i] = decode(c)
t[i] = _unpack(c)
end
return t
end
local function unpack_map (c, n)
local t = {}
local decode = unpackers['any']
for i = 1, n do
local k = decode(c)
local val = decode(c)
local k = _unpack(c)
local val = _unpack(c)
if k == nil or k ~= k then
k = m.sentinel
end
......@@ -421,30 +373,7 @@ local function unpack_map (c, n)
return t