Created
April 22, 2016 16:44
-
-
Save bigbes/c1b5b0fa7146bc2c0eed79275f6b3e11 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local ffi = require('ffi') | |
local buffer = require('buffer') | |
local builtin = ffi.C | |
ffi.cdef[[ | |
char *mp_encode_nil (char *data); | |
void mp_decode_nil (const char **data); | |
bool mp_decode_bool (const char **data); | |
char *mp_encode_bool (char *data, bool val); | |
char *mp_encode_int (const char *data, int64_t val); | |
char *mp_encode_uint (const char *data, uint64_t val); | |
uint32_t mp_sizeof_int (int64_t val); | |
uint32_t mp_sizeof_uint (uint64_t val); | |
int64_t mp_decode_int (const char **data); | |
uint64_t mp_decode_uint (const char **data); | |
char *mp_encode_str (char *data, const char *str, uint32_t len); | |
char *mp_encode_strl (char *data, uint32_t len); | |
uint32_t mp_sizeof_str (uint32_t len); | |
uint32_t mp_sizeof_strl (uint32_t len); | |
const char *mp_decode_str (char **data, uint32_t *len); | |
uint32_t mp_decode_strl (char **data); | |
char *mp_encode_float (char *data, float num); | |
char *mp_encode_double (char *data, double num); | |
float mp_decode_float (const char **data); | |
double mp_decode_double (const char **data); | |
char *mp_encode_map (char *data, uint32_t size) | |
char *mp_encode_array (char *data, uint32_t size); | |
uint32_t mp_sizeof_map (uint32_t size) | |
uint32_t mp_sizeof_array (uint32_t size) | |
uint32_t mp_decode_map (const char **data) | |
uint32_t mp_decode_array (const char **data); | |
]] | |
local type_to_state = { | |
[[nil]] = 2, | |
[[boolean]] = 3, | |
-- it must forward to appropriate type: | |
-- * double -> 8 | |
-- OR -> 9 | |
-- * - number < 0 -> 10 | |
-- OR | |
-- - number >= 0 -> 11 | |
[[number]] = 4, | |
[[string]] = 5, | |
-- it must forward to appropriate type: | |
-- * hash -> 11 | |
-- OR | |
-- * array -> 12 | |
[[table]] = 6, | |
-- it must execute needed callback from encode_ext_data | |
[[cdata]] = 7, | |
} | |
local encode_ext_cdata = {} | |
-- Set trigger that called when encoding cdata | |
local function on_encode(ctype_or_udataname, callback) | |
if type(ctype_or_udataname) ~= "cdata" or type(callback) ~= "function" then | |
error("Usage: on_encode(ffi.typeof('mytype'), function(buf, obj)") | |
end | |
local ctypeid = tonumber(ffi.typeof(ctype_or_udataname)) | |
local prev = encode_ext_cdata[ctypeid] | |
encode_ext_cdata[ctypeid] = callback | |
return prev | |
end | |
--[[ | |
on_encode(ffi.typeof('uint8_t'), encode_int) | |
on_encode(ffi.typeof('uint16_t'), encode_int) | |
on_encode(ffi.typeof('uint32_t'), encode_int) | |
on_encode(ffi.typeof('uint64_t'), encode_int) | |
on_encode(ffi.typeof('int8_t'), encode_int) | |
on_encode(ffi.typeof('int16_t'), encode_int) | |
on_encode(ffi.typeof('int32_t'), encode_int) | |
on_encode(ffi.typeof('int64_t'), encode_int) | |
on_encode(ffi.typeof('char'), encode_int) | |
on_encode(ffi.typeof('const char'), encode_int) | |
on_encode(ffi.typeof('unsigned char'), encode_int) | |
on_encode(ffi.typeof('const unsigned char'), encode_int) | |
on_encode(ffi.typeof('bool'), encode_bool_cdata) | |
on_encode(ffi.typeof('float'), encode_float) | |
on_encode(ffi.typeof('double'), encode_double) | |
]]-- | |
local function encode_r_jit(buf, obj) | |
local dyn = require('table.new')(MAXNESTING, 0) | |
local state = 1 | |
local depth = 1 | |
dyn[depth] = obj | |
for i = 1, 1000000000, 1 do | |
if state == 1 then | |
state = type_to_state[type(dyn[depth])] | |
elseif state == 2 then | |
local p = buf:alloc(1) | |
builtin.mp_encode_nil(p) | |
---- OR | |
-- encode_fix(bug, 0xc0, 0) | |
---- OR | |
-- local p = buf:alloc(1) | |
-- p[0] = 0xc0 | |
elseif state == 3 then | |
local p = buf:alloc(1) | |
builtin.mp_encode_bool(p, val and 1 or 0) | |
---- OR | |
-- encode_fix(buf, 0xc2, val and 1 or 0) | |
elseif state == 4 then | |
state = (obj % 1 == 0 and obj > -1e63 and obj < 1e64) and 8 or 9 | |
elseif state == 5 then | |
local ssz = #obj | |
local bsz = builtin.mp_sizeof_str(ssz) | |
local p = buf:alloc(bsz) | |
builtin.mp_encode_str(p, obj, ssz) | |
elseif state == 7 then | |
local | |
local | |
elseif state == 8 then | |
local | |
elseif state == 9 then | |
state = (obj >= 0) and 10 or 11 | |
elseif state == 10 then | |
local sz = builtin.mp_sizeof_int(obj) | |
local p = buf:alloc(sz) | |
builtin.mp_encode_int(p, obj) | |
elseif state == 11 then | |
local sz = builtin.mp_sizeof_uint(obj) | |
local p = buf:alloc(sz) | |
builtin.mp_encode_uint(p, obj) | |
end | |
end | |
end | |
return { | |
encode = encode_r_jit | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment