You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.3 KiB

Struct = {}
function Struct.pack(format, ...)
local stream = ''
local vars = {...}
local endianness = true
for i = 1, string.len(format) do
local opt = string.sub(format, i, i)
if opt == '<' or opt == '>' then
endianness = opt == '<' and true or false
elseif opt == 'b' or opt == 'B' or opt == 'h' or opt == 'H' or opt == 'i' or opt == 'I' or opt == 'l' or opt == 'L' then
local val = tonumber(table.remove(vars, 1))
local n = ((opt == 'h' or opt == 'H') and 2) or ((opt == 'i' or opt == 'I') and 4) or ((opt == 'l' or opt == 'L') and 8) or 1
if val < 0 then
val = val + 2 ^ (n * 8 - 1)
end
local binary = ''
for j = 1, n do
binary = binary .. string.char(val % (2 ^ 8))
val = math.floor(val / (2 ^ 8))
end
if not endianness then
binary = string.reverse(binary)
end
stream = stream .. binary
elseif opt == 's' then
stream = stream .. tostring(table.remove(vars, 1))
stream = stream .. string.char(0)
end
end
return stream
end
function Struct.unpack(format, stream)
local vars = {}
local endianness = true
for i = 1, string.len(format) do
local opt = string.sub(format, i, i)
if opt == '<' or opt == '>' then
endianness = opt == '<' and true or false
elseif opt == 'b' or opt == 'B' or opt == 'h' or opt == 'H' or opt == 'i' or opt == 'I' or opt == 'l' or opt == 'L' then
local n = ((opt == 'h' or opt == 'H') and 2) or ((opt == 'i' or opt == 'I') and 4) or ((opt == 'l' or opt == 'L') and 8) or 1
local signed = opt == 'b' or opt == 'h' or opt == 'i'
local val = 0
for j = 1, n do
local byte = string.byte(string.sub(stream, 1, 1))
if endianness then
val = val + byte * (2 ^ ((j - 1) * 8))
else
val = val + byte * (2 ^ ((n - j) * 8))
end
stream = string.sub(stream, 2)
end
if signed then
val = val - 2 ^ (n * 8 - 1)
end
table.insert(vars, val)
elseif opt == 's' then
local str = ''
for j = 1, string.len(stream) do
if string.sub(stream, j, j) == string.char(0) then
break
end
str = str .. string.sub(stream, j, j)
end
stream = string.sub(stream, string.len(str) + 2)
table.insert(vars, str)
end
end
return unpack(vars)
end