1
0
Fork 0
mirror of https://github.com/jiriks74/presence.nvim synced 2025-06-30 07:48:57 +02:00

fix(formatting): Fix formatting using stylua

This commit is contained in:
Jiří Štefka 2023-09-29 01:39:35 +02:00
parent 2d57aa297b
commit a64fc20704
Signed by: jiriks74
GPG key ID: 1D5E30D3DB2264DE
9 changed files with 2068 additions and 1902 deletions

View file

@ -9,120 +9,140 @@ local double_encode_count = 0
-- cache bitops
local band, rshift = luabit.band, luabit.brshift
if not rshift then -- luajit differ from luabit
rshift = luabit.rshift
rshift = luabit.rshift
end
local function byte_mod(x,v)
if x < 0 then
x = x + 256
end
return (x%v)
local function byte_mod(x, v)
if x < 0 then
x = x + 256
end
return (x % v)
end
-- buffer
local strbuf = "" -- for unpacking
local strary = {} -- for packing
local function strary_append_int16(n,h)
if n < 0 then
n = n + 65536
end
table.insert( strary, tostr(h, math.floor(n / 256), n % 256 ) )
local function strary_append_int16(n, h)
if n < 0 then
n = n + 65536
end
table.insert(strary, tostr(h, math.floor(n / 256), n % 256))
end
local function strary_append_int32(n,h)
if n < 0 then
n = n + 4294967296
end
table.insert(strary, tostr(h,
math.floor(n / 16777216),
math.floor(n / 65536) % 256,
math.floor(n / 256) % 256,
n % 256 ))
local function strary_append_int32(n, h)
if n < 0 then
n = n + 4294967296
end
table.insert(
strary,
tostr(h, math.floor(n / 16777216), math.floor(n / 65536) % 256, math.floor(n / 256) % 256, n % 256)
)
end
local doubleto8bytes
local strary_append_double = function(n)
-- assume double
double_encode_count = double_encode_count + 1
local b = doubleto8bytes(n)
table.insert( strary, tostr(0xcb))
table.insert( strary, string.reverse(b) ) -- reverse: make big endian double precision
-- assume double
double_encode_count = double_encode_count + 1
local b = doubleto8bytes(n)
table.insert(strary, tostr(0xcb))
table.insert(strary, string.reverse(b)) -- reverse: make big endian double precision
end
--- IEEE 754
-- out little endian
doubleto8bytes = function(x)
local function grab_byte(v)
return math.floor(v / 256), tostr(math.fmod(math.floor(v), 256))
end
local sign = 0
if x < 0 then sign = 1; x = -x end
local mantissa, exponent = math.frexp(x)
if x == 0 then -- zero
mantissa, exponent = 0, 0
elseif x == 1/0 then
mantissa, exponent = 0, 2047
else
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
exponent = exponent + 1022
end
local function grab_byte(v)
return math.floor(v / 256), tostr(math.fmod(math.floor(v), 256))
end
local sign = 0
if x < 0 then
sign = 1
x = -x
end
local mantissa, exponent = math.frexp(x)
if x == 0 then -- zero
mantissa, exponent = 0, 0
elseif x == 1 / 0 then
mantissa, exponent = 0, 2047
else
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
exponent = exponent + 1022
end
local v, byte = "" -- convert to bytes
x = mantissa
for _ = 1,6 do
_, byte = grab_byte(x); v = v..byte -- 47:0
end
x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48
x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
return v, x
local v, byte = "" -- convert to bytes
x = mantissa
for _ = 1, 6 do
_, byte = grab_byte(x)
v = v .. byte -- 47:0
end
x, byte = grab_byte(exponent * 16 + x)
v = v .. byte -- 55:48
x, byte = grab_byte(sign * 128 + x)
v = v .. byte -- 63:56
return v, x
end
local function bitstofrac(ary)
local x = 0
local cur = 0.5
for _, v in ipairs(ary) do
x = x + cur * v
cur = cur / 2
end
return x
local x = 0
local cur = 0.5
for _, v in ipairs(ary) do
x = x + cur * v
cur = cur / 2
end
return x
end
local function bytestobits(ary)
local out={}
for _, v in ipairs(ary) do
for j = 0, 7, 1 do
table.insert(out, band( rshift(v,7-j), 1 ) )
end
end
return out
local out = {}
for _, v in ipairs(ary) do
for j = 0, 7, 1 do
table.insert(out, band(rshift(v, 7 - j), 1))
end
end
return out
end
-- get little endian
local function bytestodouble(v)
-- sign:1bit
-- exp: 11bit (2048, bias=1023)
local sign = math.floor(v:byte(8) / 128)
local exp = band( v:byte(8), 127 ) * 16 + rshift( v:byte(7), 4 ) - 1023 -- bias
-- frac: 52 bit
local fracbytes = {
band( v:byte(7), 15 ), v:byte(6), v:byte(5), v:byte(4), v:byte(3), v:byte(2), v:byte(1) -- big endian
}
local bits = bytestobits(fracbytes)
-- sign:1bit
-- exp: 11bit (2048, bias=1023)
local sign = math.floor(v:byte(8) / 128)
local exp = band(v:byte(8), 127) * 16 + rshift(v:byte(7), 4) - 1023 -- bias
-- frac: 52 bit
local fracbytes = {
band(v:byte(7), 15),
v:byte(6),
v:byte(5),
v:byte(4),
v:byte(3),
v:byte(2),
v:byte(1), -- big endian
}
local bits = bytestobits(fracbytes)
for _ = 1, 4 do table.remove(bits,1) end
for _ = 1, 4 do
table.remove(bits, 1)
end
if sign == 1 then sign = -1 else sign = 1 end
if sign == 1 then
sign = -1
else
sign = 1
end
local frac = bitstofrac(bits)
if exp == -1023 and frac==0 then return 0 end
if exp == 1024 and frac==0 then return 1/0 *sign end
local frac = bitstofrac(bits)
if exp == -1023 and frac == 0 then
return 0
end
if exp == 1024 and frac == 0 then
return 1 / 0 * sign
end
local real = math.ldexp(1+frac,exp)
local real = math.ldexp(1 + frac, exp)
return real * sign
return real * sign
end
--- packers
@ -130,265 +150,285 @@ end
local packers = {}
packers.dynamic = function(data)
local t = type(data)
return packers[t](data)
local t = type(data)
return packers[t](data)
end
packers["nil"] = function()
table.insert( strary, tostr(0xc0))
table.insert(strary, tostr(0xc0))
end
packers.boolean = function(data)
if data then -- pack true
table.insert( strary, tostr(0xc3))
else -- pack false
table.insert( strary, tostr(0xc2))
end
if data then -- pack true
table.insert(strary, tostr(0xc3))
else -- pack false
table.insert(strary, tostr(0xc2))
end
end
packers.number = function(n)
if math.floor(n) == n then -- integer
if n >= 0 then -- positive integer
if n < 128 then -- positive fixnum
table.insert( strary, tostr(n))
elseif n < 256 then -- uint8
table.insert(strary, tostr(0xcc,n))
elseif n < 65536 then -- uint16
strary_append_int16(n,0xcd)
elseif n < 4294967296 then -- uint32
strary_append_int32(n,0xce)
else -- lua cannot handle uint64, so double
strary_append_double(n)
end
else -- negative integer
if n >= -32 then -- negative fixnum
table.insert( strary, tostr( 0xe0 + ((n+256)%32)) )
elseif n >= -128 then -- int8
table.insert( strary, tostr(0xd0,byte_mod(n,0x100)))
elseif n >= -32768 then -- int16
strary_append_int16(n,0xd1)
elseif n >= -2147483648 then -- int32
strary_append_int32(n,0xd2)
else -- lua cannot handle int64, so double
strary_append_double(n)
end
end
else -- floating point
strary_append_double(n)
end
if math.floor(n) == n then -- integer
if n >= 0 then -- positive integer
if n < 128 then -- positive fixnum
table.insert(strary, tostr(n))
elseif n < 256 then -- uint8
table.insert(strary, tostr(0xcc, n))
elseif n < 65536 then -- uint16
strary_append_int16(n, 0xcd)
elseif n < 4294967296 then -- uint32
strary_append_int32(n, 0xce)
else -- lua cannot handle uint64, so double
strary_append_double(n)
end
else -- negative integer
if n >= -32 then -- negative fixnum
table.insert(strary, tostr(0xe0 + ((n + 256) % 32)))
elseif n >= -128 then -- int8
table.insert(strary, tostr(0xd0, byte_mod(n, 0x100)))
elseif n >= -32768 then -- int16
strary_append_int16(n, 0xd1)
elseif n >= -2147483648 then -- int32
strary_append_int32(n, 0xd2)
else -- lua cannot handle int64, so double
strary_append_double(n)
end
end
else -- floating point
strary_append_double(n)
end
end
packers.string = function(data)
local n = #data
if n < 32 then
table.insert( strary, tostr( 0xa0+n ) )
elseif n < 65536 then
strary_append_int16(n,0xda)
elseif n < 4294967296 then
strary_append_int32(n,0xdb)
else
error("overflow")
end
table.insert( strary, data)
local n = #data
if n < 32 then
table.insert(strary, tostr(0xa0 + n))
elseif n < 65536 then
strary_append_int16(n, 0xda)
elseif n < 4294967296 then
strary_append_int32(n, 0xdb)
else
error("overflow")
end
table.insert(strary, data)
end
packers["function"] = function()
error("unimplemented:function")
error("unimplemented:function")
end
packers.userdata = function()
error("unimplemented:userdata")
error("unimplemented:userdata")
end
packers.thread = function()
error("unimplemented:thread")
error("unimplemented:thread")
end
packers.table = function(data)
local is_map,ndata,nmax = false,0,0
for k,_ in pairs(data) do
if type(k) == "number" then
if k > nmax then nmax = k end
else is_map = true end
ndata = ndata+1
end
if is_map then -- pack as map
if ndata < 16 then
table.insert( strary, tostr(0x80+ndata))
elseif ndata < 65536 then
strary_append_int16(ndata,0xde)
elseif ndata < 4294967296 then
strary_append_int32(ndata,0xdf)
else
error("overflow")
end
for k,v in pairs(data) do
packers[type(k)](k)
packers[type(v)](v)
end
else -- pack as array
if nmax < 16 then
table.insert( strary, tostr( 0x90+nmax ) )
elseif nmax < 65536 then
strary_append_int16(nmax,0xdc)
elseif nmax < 4294967296 then
strary_append_int32(nmax,0xdd)
else
error("overflow")
end
for i=1,nmax do packers[type(data[i])](data[i]) end
end
local is_map, ndata, nmax = false, 0, 0
for k, _ in pairs(data) do
if type(k) == "number" then
if k > nmax then
nmax = k
end
else
is_map = true
end
ndata = ndata + 1
end
if is_map then -- pack as map
if ndata < 16 then
table.insert(strary, tostr(0x80 + ndata))
elseif ndata < 65536 then
strary_append_int16(ndata, 0xde)
elseif ndata < 4294967296 then
strary_append_int32(ndata, 0xdf)
else
error("overflow")
end
for k, v in pairs(data) do
packers[type(k)](k)
packers[type(v)](v)
end
else -- pack as array
if nmax < 16 then
table.insert(strary, tostr(0x90 + nmax))
elseif nmax < 65536 then
strary_append_int16(nmax, 0xdc)
elseif nmax < 4294967296 then
strary_append_int32(nmax, 0xdd)
else
error("overflow")
end
for i = 1, nmax do
packers[type(data[i])](data[i])
end
end
end
-- types decoding
local types_map = {
[0xc0] = "nil",
[0xc2] = "false",
[0xc3] = "true",
[0xca] = "float",
[0xcb] = "double",
[0xcc] = "uint8",
[0xcd] = "uint16",
[0xce] = "uint32",
[0xcf] = "uint64",
[0xd0] = "int8",
[0xd1] = "int16",
[0xd2] = "int32",
[0xd3] = "int64",
[0xda] = "raw16",
[0xdb] = "raw32",
[0xdc] = "array16",
[0xdd] = "array32",
[0xde] = "map16",
[0xdf] = "map32",
[0xc0] = "nil",
[0xc2] = "false",
[0xc3] = "true",
[0xca] = "float",
[0xcb] = "double",
[0xcc] = "uint8",
[0xcd] = "uint16",
[0xce] = "uint32",
[0xcf] = "uint64",
[0xd0] = "int8",
[0xd1] = "int16",
[0xd2] = "int32",
[0xd3] = "int64",
[0xda] = "raw16",
[0xdb] = "raw32",
[0xdc] = "array16",
[0xdd] = "array32",
[0xde] = "map16",
[0xdf] = "map32",
}
local type_for = function(n)
if types_map[n] then return types_map[n]
elseif n < 0xc0 then
if n < 0x80 then return "fixnum_posi"
elseif n < 0x90 then return "fixmap"
elseif n < 0xa0 then return "fixarray"
else return "fixraw" end
elseif n > 0xdf then return "fixnum_neg"
else return "undefined" end
if types_map[n] then
return types_map[n]
elseif n < 0xc0 then
if n < 0x80 then
return "fixnum_posi"
elseif n < 0x90 then
return "fixmap"
elseif n < 0xa0 then
return "fixarray"
else
return "fixraw"
end
elseif n > 0xdf then
return "fixnum_neg"
else
return "undefined"
end
end
local types_len_map = {
uint16 = 2, uint32 = 4, uint64 = 8,
int16 = 2, int32 = 4, int64 = 8,
float = 4, double = 8,
uint16 = 2,
uint32 = 4,
uint64 = 8,
int16 = 2,
int32 = 4,
int64 = 8,
float = 4,
double = 8,
}
--- unpackers
local unpackers = {}
local unpack_number = function(offset,ntype,nlen)
local b1,b2,b3,b4,b5,b6,b7,b8
if nlen>=2 then
b1,b2 = string.byte( strbuf, offset+1, offset+2 )
end
if nlen>=4 then
b3,b4 = string.byte( strbuf, offset+3, offset+4 )
end
if nlen>=8 then
b5,b6,b7,b8 = string.byte( strbuf, offset+5, offset+8 )
end
local unpack_number = function(offset, ntype, nlen)
local b1, b2, b3, b4, b5, b6, b7, b8
if nlen >= 2 then
b1, b2 = string.byte(strbuf, offset + 1, offset + 2)
end
if nlen >= 4 then
b3, b4 = string.byte(strbuf, offset + 3, offset + 4)
end
if nlen >= 8 then
b5, b6, b7, b8 = string.byte(strbuf, offset + 5, offset + 8)
end
if ntype == "uint16_t" then
return b1 * 256 + b2
elseif ntype == "uint32_t" then
return b1*65536*256 + b2*65536 + b3 * 256 + b4
elseif ntype == "int16_t" then
local n = b1 * 256 + b2
local nn = (65536 - n)*-1
if nn == -65536 then nn = 0 end
return nn
elseif ntype == "int32_t" then
local n = b1*65536*256 + b2*65536 + b3 * 256 + b4
local nn = ( 4294967296 - n ) * -1
if nn == -4294967296 then nn = 0 end
return nn
elseif ntype == "double_t" then
local s = tostr(b8,b7,b6,b5,b4,b3,b2,b1)
double_decode_count = double_decode_count + 1
local n = bytestodouble( s )
return n
else
error("unpack_number: not impl:" .. ntype )
end
if ntype == "uint16_t" then
return b1 * 256 + b2
elseif ntype == "uint32_t" then
return b1 * 65536 * 256 + b2 * 65536 + b3 * 256 + b4
elseif ntype == "int16_t" then
local n = b1 * 256 + b2
local nn = (65536 - n) * -1
if nn == -65536 then
nn = 0
end
return nn
elseif ntype == "int32_t" then
local n = b1 * 65536 * 256 + b2 * 65536 + b3 * 256 + b4
local nn = (4294967296 - n) * -1
if nn == -4294967296 then
nn = 0
end
return nn
elseif ntype == "double_t" then
local s = tostr(b8, b7, b6, b5, b4, b3, b2, b1)
double_decode_count = double_decode_count + 1
local n = bytestodouble(s)
return n
else
error("unpack_number: not impl:" .. ntype)
end
end
local function unpacker_number(offset)
local obj_type = type_for( string.byte( strbuf, offset+1, offset+1 ) )
local nlen = types_len_map[obj_type]
local ntype
if (obj_type == "float") then
error("float is not implemented")
else
ntype = obj_type .. "_t"
end
return offset+nlen+1,unpack_number(offset+1,ntype,nlen)
local obj_type = type_for(string.byte(strbuf, offset + 1, offset + 1))
local nlen = types_len_map[obj_type]
local ntype
if obj_type == "float" then
error("float is not implemented")
else
ntype = obj_type .. "_t"
end
return offset + nlen + 1, unpack_number(offset + 1, ntype, nlen)
end
local function unpack_map(offset,n)
local r = {}
local k,v
for _ = 1, n do
offset,k = unpackers.dynamic(offset)
assert(offset)
offset,v = unpackers.dynamic(offset)
assert(offset)
r[k] = v
end
return offset,r
local function unpack_map(offset, n)
local r = {}
local k, v
for _ = 1, n do
offset, k = unpackers.dynamic(offset)
assert(offset)
offset, v = unpackers.dynamic(offset)
assert(offset)
r[k] = v
end
return offset, r
end
local function unpack_array(offset,n)
local r = {}
for i=1,n do
offset,r[i] = unpackers.dynamic(offset)
assert(offset)
end
return offset,r
local function unpack_array(offset, n)
local r = {}
for i = 1, n do
offset, r[i] = unpackers.dynamic(offset)
assert(offset)
end
return offset, r
end
function unpackers.dynamic(offset)
if offset >= #strbuf then error("need more data") end
local obj_type = type_for( string.byte( strbuf, offset+1, offset+1 ) )
return unpackers[obj_type](offset)
if offset >= #strbuf then
error("need more data")
end
local obj_type = type_for(string.byte(strbuf, offset + 1, offset + 1))
return unpackers[obj_type](offset)
end
function unpackers.undefined()
error("unimplemented:undefined")
error("unimplemented:undefined")
end
unpackers["nil"] = function(offset)
return offset+1,nil
return offset + 1, nil
end
unpackers["false"] = function(offset)
return offset+1,false
return offset + 1, false
end
unpackers["true"] = function(offset)
return offset+1,true
return offset + 1, true
end
unpackers.fixnum_posi = function(offset)
return offset+1, string.byte(strbuf, offset+1, offset+1)
return offset + 1, string.byte(strbuf, offset + 1, offset + 1)
end
unpackers.uint8 = function(offset)
return offset+2, string.byte(strbuf, offset+2, offset+2)
return offset + 2, string.byte(strbuf, offset + 2, offset + 2)
end
unpackers.uint16 = unpacker_number
@ -396,18 +436,18 @@ unpackers.uint32 = unpacker_number
unpackers.uint64 = unpacker_number
unpackers.fixnum_neg = function(offset)
-- alternative to cast below:
local n = string.byte( strbuf, offset+1, offset+1)
local nn = ( 256 - n ) * -1
return offset+1, nn
-- alternative to cast below:
local n = string.byte(strbuf, offset + 1, offset + 1)
local nn = (256 - n) * -1
return offset + 1, nn
end
unpackers.int8 = function(offset)
local i = string.byte( strbuf, offset+2, offset+2 )
if i > 127 then
i = (256 - i ) * -1
end
return offset+2, i
local i = string.byte(strbuf, offset + 2, offset + 2)
if i > 127 then
i = (256 - i) * -1
end
return offset + 2, i
end
unpackers.int16 = unpacker_number
@ -418,92 +458,96 @@ unpackers.float = unpacker_number
unpackers.double = unpacker_number
unpackers.fixraw = function(offset)
local n = byte_mod( string.byte( strbuf, offset+1, offset+1) ,0x1f+1)
-- print("unpackers.fixraw: offset:", offset, "#buf:", #buf, "n:",n )
local b
if ( #strbuf - 1 - offset ) < n then
error("require more data")
end
local n = byte_mod(string.byte(strbuf, offset + 1, offset + 1), 0x1f + 1)
-- print("unpackers.fixraw: offset:", offset, "#buf:", #buf, "n:",n )
local b
if (#strbuf - 1 - offset) < n then
error("require more data")
end
if n > 0 then
b = string.sub( strbuf, offset + 1 + 1, offset + 1 + 1 + n - 1 )
else
b = ""
end
return offset+n+1, b
if n > 0 then
b = string.sub(strbuf, offset + 1 + 1, offset + 1 + 1 + n - 1)
else
b = ""
end
return offset + n + 1, b
end
unpackers.raw16 = function(offset)
local n = unpack_number(offset+1,"uint16_t",2)
if ( #strbuf - 1 - 2 - offset ) < n then
error("require more data")
end
local b = string.sub( strbuf, offset+1+1+2, offset+1 + 1+2 + n - 1 )
return offset+n+3, b
local n = unpack_number(offset + 1, "uint16_t", 2)
if (#strbuf - 1 - 2 - offset) < n then
error("require more data")
end
local b = string.sub(strbuf, offset + 1 + 1 + 2, offset + 1 + 1 + 2 + n - 1)
return offset + n + 3, b
end
unpackers.raw32 = function(offset)
local n = unpack_number(offset+1,"uint32_t",4)
if ( #strbuf - 1 - 4 - offset ) < n then
error( "require more data (possibly bug)")
end
local b = string.sub( strbuf, offset+1+ 1+4, offset+1 + 1+4 +n -1 )
return offset+n+5,b
local n = unpack_number(offset + 1, "uint32_t", 4)
if (#strbuf - 1 - 4 - offset) < n then
error("require more data (possibly bug)")
end
local b = string.sub(strbuf, offset + 1 + 1 + 4, offset + 1 + 1 + 4 + n - 1)
return offset + n + 5, b
end
unpackers.fixarray = function(offset)
return unpack_array( offset+1,byte_mod( string.byte( strbuf, offset+1,offset+1),0x0f+1))
return unpack_array(offset + 1, byte_mod(string.byte(strbuf, offset + 1, offset + 1), 0x0f + 1))
end
unpackers.array16 = function(offset)
return unpack_array(offset+3,unpack_number(offset+1,"uint16_t",2))
return unpack_array(offset + 3, unpack_number(offset + 1, "uint16_t", 2))
end
unpackers.array32 = function(offset)
return unpack_array(offset+5,unpack_number(offset+1,"uint32_t",4))
return unpack_array(offset + 5, unpack_number(offset + 1, "uint32_t", 4))
end
unpackers.fixmap = function(offset)
return unpack_map(offset+1,byte_mod( string.byte( strbuf, offset+1,offset+1),0x0f+1))
return unpack_map(offset + 1, byte_mod(string.byte(strbuf, offset + 1, offset + 1), 0x0f + 1))
end
unpackers.map16 = function(offset)
return unpack_map(offset+3,unpack_number(offset+1,"uint16_t",2))
return unpack_map(offset + 3, unpack_number(offset + 1, "uint16_t", 2))
end
unpackers.map32 = function(offset)
return unpack_map(offset+5,unpack_number(offset+1,"uint32_t",4))
return unpack_map(offset + 5, unpack_number(offset + 1, "uint32_t", 4))
end
-- Main functions
local ljp_pack = function(data)
strary={}
packers.dynamic(data)
local s = table.concat(strary,"")
return s
strary = {}
packers.dynamic(data)
local s = table.concat(strary, "")
return s
end
local ljp_unpack = function(s,offset)
if offset == nil then offset = 0 end
if type(s) ~= "string" then return false,"invalid argument" end
local data
strbuf = s
offset,data = unpackers.dynamic(offset)
return offset,data
local ljp_unpack = function(s, offset)
if offset == nil then
offset = 0
end
if type(s) ~= "string" then
return false, "invalid argument"
end
local data
strbuf = s
offset, data = unpackers.dynamic(offset)
return offset, data
end
local function ljp_stat()
return {
double_decode_count = double_decode_count,
double_encode_count = double_encode_count
}
return {
double_decode_count = double_decode_count,
double_encode_count = double_encode_count,
}
end
local msgpack = {
pack = ljp_pack,
unpack = ljp_unpack,
stat = ljp_stat
pack = ljp_pack,
unpack = ljp_unpack,
stat = ljp_stat,
}
return msgpack

View file

@ -1,140 +1,265 @@
local n, v = "serpent", "0.302" -- (C) 2012-18 Paul Kulchenko; MIT License
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
local badtype = {thread = true, userdata = true, cdata = true}
local snum = {
[tostring(1 / 0)] = "1/0 --[[math.huge]]",
[tostring(-1 / 0)] = "-1/0 --[[-math.huge]]",
[tostring(0 / 0)] = "0/0",
}
local badtype = { thread = true, userdata = true, cdata = true }
local getmetatable = debug and debug.getmetatable or getmetatable
local pairs = function(t) return next, t end -- avoid using __pairs in Lua 5.2+
local pairs = function(t)
return next, t
end -- avoid using __pairs in Lua 5.2+
local keyword, globals, G = {}, {}, (_G or _ENV)
for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end
for k,v in pairs(G) do globals[v] = k end -- build func to name mapping
for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do
for k,v in pairs(type(G[g]) == 'table' and G[g] or {}) do globals[v] = g..'.'..k end end
for _, k in ipairs({
"and",
"break",
"do",
"else",
"elseif",
"end",
"false",
"for",
"function",
"goto",
"if",
"in",
"local",
"nil",
"not",
"or",
"repeat",
"return",
"then",
"true",
"until",
"while",
}) do
keyword[k] = true
end
for k, v in pairs(G) do
globals[v] = k
end -- build func to name mapping
for _, g in ipairs({ "coroutine", "debug", "io", "math", "string", "table", "os" }) do
for k, v in pairs(type(G[g]) == "table" and G[g] or {}) do
globals[v] = g .. "." .. k
end
end
local function s(t, opts)
local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
local maxlen, metatostring = tonumber(opts.maxlength), opts.metatostring
local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
local numformat = opts.numformat or "%.17g"
local seen, sref, syms, symn = {}, {'local '..iname..'={}'}, {}, 0
local function gensym(val) return '_'..(tostring(tostring(val)):gsub("[^%w]",""):gsub("(%d%w+)",
-- tostring(val) is needed because __tostring may return a non-string value
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return tostring(syms[s]) end)) end
local function safestr(s) return type(s) == "number" and tostring(huge and snum[tostring(s)] or numformat:format(s))
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
local function comment(s,l) return comm and (l or 0) < comm and ' --[['..select(2, pcall(tostring, s))..']]' or '' end
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
local n = name == nil and '' or name
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
local safe = plain and n or '['..safestr(n)..']'
return (path or '')..(plain and path and '.' or '')..safe, safe end
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
local function padnum(d) return ("%0"..tostring(maxn).."d"):format(tonumber(d)) end
table.sort(k, function(a,b)
-- sort numeric keys first: k[key] is not nil for numerical keys
return (k[a] ~= nil and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
< (k[b] ~= nil and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
local function val2str(t, name, indent, insref, path, plainindex, level)
local ttype, level, mt = type(t), (level or 0), getmetatable(t)
local spath, sname = safename(path, name)
local tag = plainindex and
((type(name) == "number") and '' or name..space..'='..space) or
(name ~= nil and sname..space..'='..space or '')
if seen[t] then -- already seen this element
sref[#sref+1] = spath..space..'='..space..seen[t]
return tag..'nil'..comment('ref', level) end
-- protect from those cases where __tostring may fail
if type(mt) == 'table' and metatostring ~= false then
local to, tr = pcall(function() return mt.__tostring(t) end)
local so, sr = pcall(function() return mt.__serialize(t) end)
if (to or so) then -- knows how to serialize itself
seen[t] = insref or spath
t = so and sr or tr
ttype = type(t)
end -- new value falls through to be serialized
end
if ttype == "table" then
if level >= maxl then return tag..'{}'..comment('maxlvl', level) end
seen[t] = insref or spath
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
if maxlen and maxlen < 0 then return tag..'{}'..comment('maxlen', level) end
local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
for key = 1, maxn do o[key] = key end
if not maxnum or #o < maxnum then
local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end end
if maxnum and #o > maxnum then o[maxnum+1] = nil end
if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end
local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
for n, key in ipairs(o) do
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
or opts.keyallow and not opts.keyallow[key]
or opts.keyignore and opts.keyignore[key]
or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
or sparse and value == nil then -- skipping nils; do nothing
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
if not seen[key] and not globals[key] then
sref[#sref+1] = 'placeholder'
local sname = safename(iname, gensym(key)) -- iname is table for local variables
sref[#sref] = val2str(key,sname,indent,sname,iname,true) end
sref[#sref+1] = 'placeholder'
local path = seen[t]..'['..tostring(seen[key] or globals[key] or gensym(key))..']'
sref[#sref] = path..space..'='..space..tostring(seen[value] or val2str(value,nil,indent,path))
else
out[#out+1] = val2str(value,key,indent,nil,seen[t],plainindex,level+1)
if maxlen then
maxlen = maxlen - #out[#out]
if maxlen < 0 then break end
end
end
end
local prefix = string.rep(indent or '', level)
local head = indent and '{\n'..prefix..indent or '{'
local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
local tail = indent and "\n"..prefix..'}' or '}'
return (custom and custom(tag,head,body,tail,level) or tag..head..body..tail)..comment(t, level)
elseif badtype[ttype] then
seen[t] = insref or spath
return tag..globerr(t, level)
elseif ttype == 'function' then
seen[t] = insref or spath
if opts.nocode then return tag.."function() --[[..skipped..]] end"..comment(t, level) end
local ok, res = pcall(string.dump, t)
local func = ok and "((loadstring or load)("..safestr(res)..",'@serialized'))"..comment(t, level)
return tag..(func or globerr(t, level))
else return tag..safestr(t) end -- handle all other types
end
local sepr = indent and "\n" or ";"..space
local body = val2str(t, name, indent) -- this call also populates sref
local tail = #sref>1 and table.concat(sref, sepr)..sepr or ''
local warn = opts.comment and #sref>1 and space.."--[[incomplete output with shared/self-references skipped]]" or ''
return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end"
local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
local space, maxl = (opts.compact and "" or " "), (opts.maxlevel or math.huge)
local maxlen, metatostring = tonumber(opts.maxlength), opts.metatostring
local iname, comm = "_" .. (name or ""), opts.comment and (tonumber(opts.comment) or math.huge)
local numformat = opts.numformat or "%.17g"
local seen, sref, syms, symn = {}, { "local " .. iname .. "={}" }, {}, 0
local function gensym(val)
return "_"
.. (
tostring(tostring(val)):gsub("[^%w]", ""):gsub(
"(%d%w+)",
-- tostring(val) is needed because __tostring may return a non-string value
function(s)
if not syms[s] then
symn = symn + 1
syms[s] = symn
end
return tostring(syms[s])
end
)
)
end
local function safestr(s)
return type(s) == "number" and tostring(huge and snum[tostring(s)] or numformat:format(s))
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
or ("%q"):format(s):gsub("\010", "n"):gsub("\026", "\\026")
end
local function comment(s, l)
return comm and (l or 0) < comm and " --[[" .. select(2, pcall(tostring, s)) .. "]]" or ""
end
local function globerr(s, l)
return globals[s] and globals[s] .. comment(s, l)
or not fatal and safestr(select(2, pcall(tostring, s)))
or error("Can't serialize " .. tostring(s))
end
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
local n = name == nil and "" or name
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
local safe = plain and n or "[" .. safestr(n) .. "]"
return (path or "") .. (plain and path and "." or "") .. safe, safe
end
local alphanumsort = type(opts.sortkeys) == "function" and opts.sortkeys
or function(k, o, n) -- k=keys, o=originaltable, n=padding
local maxn, to = tonumber(n) or 12, { number = "a", string = "b" }
local function padnum(d)
return ("%0" .. tostring(maxn) .. "d"):format(tonumber(d))
end
table.sort(k, function(a, b)
-- sort numeric keys first: k[key] is not nil for numerical keys
return (k[a] ~= nil and 0 or to[type(a)] or "z") .. (tostring(a):gsub("%d+", padnum))
< (k[b] ~= nil and 0 or to[type(b)] or "z") .. (tostring(b):gsub("%d+", padnum))
end)
end
local function val2str(t, name, indent, insref, path, plainindex, level)
local ttype, level, mt = type(t), (level or 0), getmetatable(t)
local spath, sname = safename(path, name)
local tag = plainindex and ((type(name) == "number") and "" or name .. space .. "=" .. space)
or (name ~= nil and sname .. space .. "=" .. space or "")
if seen[t] then -- already seen this element
sref[#sref + 1] = spath .. space .. "=" .. space .. seen[t]
return tag .. "nil" .. comment("ref", level)
end
-- protect from those cases where __tostring may fail
if type(mt) == "table" and metatostring ~= false then
local to, tr = pcall(function()
return mt.__tostring(t)
end)
local so, sr = pcall(function()
return mt.__serialize(t)
end)
if to or so then -- knows how to serialize itself
seen[t] = insref or spath
t = so and sr or tr
ttype = type(t)
end -- new value falls through to be serialized
end
if ttype == "table" then
if level >= maxl then
return tag .. "{}" .. comment("maxlvl", level)
end
seen[t] = insref or spath
if next(t) == nil then
return tag .. "{}" .. comment(t, level)
end -- table empty
if maxlen and maxlen < 0 then
return tag .. "{}" .. comment("maxlen", level)
end
local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
for key = 1, maxn do
o[key] = key
end
if not maxnum or #o < maxnum then
local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
for key in pairs(t) do
if o[key] ~= key then
n = n + 1
o[n] = key
end
end
end
if maxnum and #o > maxnum then
o[maxnum + 1] = nil
end
if opts.sortkeys and #o > maxn then
alphanumsort(o, t, opts.sortkeys)
end
local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
for n, key in ipairs(o) do
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
if
opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
or opts.keyallow and not opts.keyallow[key]
or opts.keyignore and opts.keyignore[key]
or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
or sparse and value == nil
then -- skipping nils; do nothing
elseif ktype == "table" or ktype == "function" or badtype[ktype] then
if not seen[key] and not globals[key] then
sref[#sref + 1] = "placeholder"
local sname = safename(iname, gensym(key)) -- iname is table for local variables
sref[#sref] = val2str(key, sname, indent, sname, iname, true)
end
sref[#sref + 1] = "placeholder"
local path = seen[t] .. "[" .. tostring(seen[key] or globals[key] or gensym(key)) .. "]"
sref[#sref] = path
.. space
.. "="
.. space
.. tostring(seen[value] or val2str(value, nil, indent, path))
else
out[#out + 1] = val2str(value, key, indent, nil, seen[t], plainindex, level + 1)
if maxlen then
maxlen = maxlen - #out[#out]
if maxlen < 0 then
break
end
end
end
end
local prefix = string.rep(indent or "", level)
local head = indent and "{\n" .. prefix .. indent or "{"
local body = table.concat(out, "," .. (indent and "\n" .. prefix .. indent or space))
local tail = indent and "\n" .. prefix .. "}" or "}"
return (custom and custom(tag, head, body, tail, level) or tag .. head .. body .. tail) .. comment(t, level)
elseif badtype[ttype] then
seen[t] = insref or spath
return tag .. globerr(t, level)
elseif ttype == "function" then
seen[t] = insref or spath
if opts.nocode then
return tag .. "function() --[[..skipped..]] end" .. comment(t, level)
end
local ok, res = pcall(string.dump, t)
local func = ok and "((loadstring or load)(" .. safestr(res) .. ",'@serialized'))" .. comment(t, level)
return tag .. (func or globerr(t, level))
else
return tag .. safestr(t)
end -- handle all other types
end
local sepr = indent and "\n" or ";" .. space
local body = val2str(t, name, indent) -- this call also populates sref
local tail = #sref > 1 and table.concat(sref, sepr) .. sepr or ""
local warn = opts.comment and #sref > 1 and space .. "--[[incomplete output with shared/self-references skipped]]"
or ""
return not name and body .. warn or "do local " .. body .. sepr .. tail .. "return " .. name .. sepr .. "end"
end
local function deserialize(data, opts)
local env = (opts and opts.safe == false) and G
or setmetatable({}, {
__index = function(t,k) return t end,
__call = function(t,...) error("cannot call functions") end
})
local f, res = (loadstring or load)('return '..data, nil, nil, env)
if not f then f, res = (loadstring or load)(data, nil, nil, env) end
if not f then return f, res end
if setfenv then setfenv(f, env) end
return pcall(f)
local env = (opts and opts.safe == false) and G
or setmetatable({}, {
__index = function(t, k)
return t
end,
__call = function(t, ...)
error("cannot call functions")
end,
})
local f, res = (loadstring or load)("return " .. data, nil, nil, env)
if not f then
f, res = (loadstring or load)(data, nil, nil, env)
end
if not f then
return f, res
end
if setfenv then
setfenv(f, env)
end
return pcall(f)
end
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
load = deserialize,
dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }
local function merge(a, b)
if b then
for k, v in pairs(b) do
a[k] = v
end
end
return a
end
return {
_NAME = n,
_COPYRIGHT = c,
_DESCRIPTION = d,
_VERSION = v,
serialize = s,
load = deserialize,
dump = function(a, opts)
return s(a, merge({ name = "_", compact = true, sparse = true }, opts))
end,
line = function(a, opts)
return s(a, merge({ sortkeys = true, comment = true }, opts))
end,
block = function(a, opts)
return s(a, merge({ indent = " ", sortkeys = true, comment = true }, opts))
end,
}

View file

@ -1,179 +1,178 @@
local struct = {}
function struct.pack(format, ...)
local stream = {}
local vars = {...}
local endianness = true
local stream = {}
local vars = { ... }
local endianness = true
for i = 1, format:len() do
local opt = format:sub(i, i)
for i = 1, format:len() do
local opt = format:sub(i, i)
if opt == '<' then
endianness = true
elseif opt == '>' then
endianness = false
elseif opt:find('[bBhHiIlL]') then
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
local val = tonumber(table.remove(vars, 1))
if opt == "<" then
endianness = true
elseif opt == ">" then
endianness = false
elseif opt:find("[bBhHiIlL]") then
local n = opt:find("[hH]") and 2 or opt:find("[iI]") and 4 or opt:find("[lL]") and 8 or 1
local val = tonumber(table.remove(vars, 1))
local bytes = {}
for _ = 1, n do
table.insert(bytes, string.char(val % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
local bytes = {}
for _ = 1, n do
table.insert(bytes, string.char(val % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt:find('[fd]') then
local val = tonumber(table.remove(vars, 1))
local sign = 0
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt:find("[fd]") then
local val = tonumber(table.remove(vars, 1))
local sign = 0
if val < 0 then
sign = 1
val = -val
end
if val < 0 then
sign = 1
val = -val
end
local mantissa, exponent = math.frexp(val)
if val == 0 then
mantissa = 0
exponent = 0
else
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24)
exponent = exponent + ((opt == 'd') and 1022 or 126)
end
local mantissa, exponent = math.frexp(val)
if val == 0 then
mantissa = 0
exponent = 0
else
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == "d") and 53 or 24)
exponent = exponent + ((opt == "d") and 1022 or 126)
end
local bytes = {}
if opt == 'd' then
val = mantissa
for _ = 1, 6 do
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
else
table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
val = math.floor(mantissa / (2 ^ 8))
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
local bytes = {}
if opt == "d" then
val = mantissa
for _ = 1, 6 do
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
else
table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
val = math.floor(mantissa / (2 ^ 8))
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
table.insert(bytes, string.char(math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8)))
val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8))
table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
table.insert(bytes, string.char(math.floor(exponent * ((opt == "d") and 16 or 128) + val) % (2 ^ 8)))
val = math.floor((exponent * ((opt == "d") and 16 or 128) + val) / (2 ^ 8))
table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt == 's' then
table.insert(stream, tostring(table.remove(vars, 1)))
table.insert(stream, string.char(0))
elseif opt == 'c' then
local n = format:sub(i + 1):match('%d+')
local str = tostring(table.remove(vars, 1))
local len = tonumber(n)
if len <= 0 then
len = str:len()
end
if len - str:len() > 0 then
str = str .. string.rep(' ', len - str:len())
end
table.insert(stream, str:sub(1, len))
end
end
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt == "s" then
table.insert(stream, tostring(table.remove(vars, 1)))
table.insert(stream, string.char(0))
elseif opt == "c" then
local n = format:sub(i + 1):match("%d+")
local str = tostring(table.remove(vars, 1))
local len = tonumber(n)
if len <= 0 then
len = str:len()
end
if len - str:len() > 0 then
str = str .. string.rep(" ", len - str:len())
end
table.insert(stream, str:sub(1, len))
end
end
return table.concat(stream)
return table.concat(stream)
end
function struct.unpack(format, stream, pos)
local vars = {}
local iterator = pos or 1
local endianness = true
local vars = {}
local iterator = pos or 1
local endianness = true
for i = 1, format:len() do
local opt = format:sub(i, i)
for i = 1, format:len() do
local opt = format:sub(i, i)
if opt == '<' then
endianness = true
elseif opt == '>' then
endianness = false
elseif opt:find('[bBhHiIlL]') then
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
local signed = opt:lower() == opt
if opt == "<" then
endianness = true
elseif opt == ">" then
endianness = false
elseif opt:find("[bBhHiIlL]") then
local n = opt:find("[hH]") and 2 or opt:find("[iI]") and 4 or opt:find("[lL]") and 8 or 1
local signed = opt:lower() == opt
local val = 0
for j = 1, n do
local byte = string.byte(stream:sub(iterator, iterator))
if endianness then
val = val + byte * (2 ^ ((j - 1) * 8))
else
val = val + byte * (2 ^ ((n - j) * 8))
end
iterator = iterator + 1
end
local val = 0
for j = 1, n do
local byte = string.byte(stream:sub(iterator, iterator))
if endianness then
val = val + byte * (2 ^ ((j - 1) * 8))
else
val = val + byte * (2 ^ ((n - j) * 8))
end
iterator = iterator + 1
end
if signed and val >= 2 ^ (n * 8 - 1) then
val = val - 2 ^ (n * 8)
end
if signed and val >= 2 ^ (n * 8 - 1) then
val = val - 2 ^ (n * 8)
end
table.insert(vars, math.floor(val))
elseif opt:find('[fd]') then
local n = (opt == 'd') and 8 or 4
local x = stream:sub(iterator, iterator + n - 1)
iterator = iterator + n
table.insert(vars, math.floor(val))
elseif opt:find("[fd]") then
local n = (opt == "d") and 8 or 4
local x = stream:sub(iterator, iterator + n - 1)
iterator = iterator + n
if not endianness then
x = string.reverse(x)
end
if not endianness then
x = string.reverse(x)
end
local sign = 1
local mantissa = string.byte(x, (opt == 'd') and 7 or 3) % ((opt == 'd') and 16 or 128)
for j = n - 2, 1, -1 do
mantissa = mantissa * (2 ^ 8) + string.byte(x, j)
end
local sign = 1
local mantissa = string.byte(x, (opt == "d") and 7 or 3) % ((opt == "d") and 16 or 128)
for j = n - 2, 1, -1 do
mantissa = mantissa * (2 ^ 8) + string.byte(x, j)
end
if string.byte(x, n) > 127 then
sign = -1
end
if string.byte(x, n) > 127 then
sign = -1
end
local exponent = (string.byte(x, n) % 128) * ((opt == 'd') and 16 or 2) +
math.floor(string.byte(x, n - 1) /
((opt == 'd') and 16 or 128))
if exponent == 0 then
table.insert(vars, 0.0)
else
mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign
table.insert(vars, math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127)))
end
elseif opt == 's' then
local bytes = {}
for j = iterator, stream:len() do
if stream:sub(j,j) == string.char(0) or stream:sub(j) == '' then
break
end
local exponent = (string.byte(x, n) % 128) * ((opt == "d") and 16 or 2)
+ math.floor(string.byte(x, n - 1) / ((opt == "d") and 16 or 128))
if exponent == 0 then
table.insert(vars, 0.0)
else
mantissa = (math.ldexp(mantissa, (opt == "d") and -52 or -23) + 1) * sign
table.insert(vars, math.ldexp(mantissa, exponent - ((opt == "d") and 1023 or 127)))
end
elseif opt == "s" then
local bytes = {}
for j = iterator, stream:len() do
if stream:sub(j, j) == string.char(0) or stream:sub(j) == "" then
break
end
table.insert(bytes, stream:sub(j, j))
end
table.insert(bytes, stream:sub(j, j))
end
local str = table.concat(bytes)
iterator = iterator + str:len() + 1
table.insert(vars, str)
elseif opt == 'c' then
local n = format:sub(i + 1):match('%d+')
local len = tonumber(n)
if len <= 0 then
len = table.remove(vars)
end
local str = table.concat(bytes)
iterator = iterator + str:len() + 1
table.insert(vars, str)
elseif opt == "c" then
local n = format:sub(i + 1):match("%d+")
local len = tonumber(n)
if len <= 0 then
len = table.remove(vars)
end
table.insert(vars, stream:sub(iterator, iterator + len - 1))
iterator = iterator + len
end
end
table.insert(vars, stream:sub(iterator, iterator + len - 1))
iterator = iterator + len
end
end
return unpack(vars)
return unpack(vars)
end
return struct