Lua (5.0) equivalent to python struct.pack
I am trying to convert Python code to Lua. Which is the Lua equivalent:
value2 = '' key = 'cmpg' value1 = '\x00\x00\x00\x00\x00\x00\x00\x01' Value2 += '%s%s%s' % (key, struct.pack('>i', len(value1)), value1)
You said in a comment:
I may be able to get around knowing the string generated by each of the following: struct.pack ('> i', 4), struct.pack ('> i', 8) and struct.pack ('> I', 10)
Effector '> i' means bidian 32-bit integer. For non-negative input x, the simple Python equivalent would be
chr((x >> 24) & 255) + chr((x >> 16) & 255) + chr((x >> 8) & 255) + chr(x & 255)
You may be able to express this in Lua without too much difficulty.
You said in another comment:
I ... don't understand the answer (@john machin)
chr (x) is easy to find in the docs. Lua should have such a function, perhaps even with the same name.
i >> n
shifts i to the right n bits. If I'm unsigned, this is equivalent i // ( 2 ** n)
to where //
is integer division in Python.
i & 255
is bitwise and equivalent i % 256
.
Lua must have both of these.
+
in this case is string concatenation.
Look at this:
>>> import binascii
>>> def pack_be_I(x):
... return (
... chr((x >> 24) & 255) +
... chr((x >> 16) & 255) +
... chr((x >> 8) & 255) +
... chr(x & 255)
... )
...
>>> for anint in (4, 8, 10, 0x01020304, 0x04030201):
... packed = pack_be_I(anint)
... hexbytes = binascii.hexlify(packed)
... print anint, repr(packed), hexbytes
...
4 '\x00\x00\x00\x04' 00000004
8 '\x00\x00\x00\x08' 00000008
10 '\x00\x00\x00\n' 0000000a
16909060 '\x01\x02\x03\x04' 01020304
67305985 '\x04\x03\x02\x01' 04030201
>>>
You will notice that the required output for 10
is '\x00\x00\x00\n'
... note that '\x0a'
aka '\n'
aka chr(10)
needs help. If you are writing this stuff to a file on Windows, you must open the file in binary ( 'wb'
, not 'w'
) mode , otherwise the runtime library inserts a carriage return byte to comply with Windows, MS-DOS, CP / M requirements for text files.
How about using it struct.pack
for Lua (it's code based string.pack
)? It offers the same functionality you'd expect. Therefore, you can run the following code:
local key = 'cmpg'
local value1 = '\0\0\0\0\0\1'
local packed = key .. struct.pack('>i', #value1) .. value1
Or, looking at the examples in the docs, you can also do it like this:
local packed = key .. struct.pack('>ic0', #value1, value1)
To unpack this line, use the following (if you have only <length,string>
to data
):
local unpacked = struct.unpack('>ic0', data)
Take a look at string.pack ; you can find the precompiled binaries for Windows included with Lua for Windows .
value2 = ''
key = 'cmpg'
value1 = '\x00\x00\x00\x00\x00\x00\x00\x01'
value2 = string.format("%s%s%s", key, string.pack(">i", #value1, value))
If you are using LuaJIT (which I highly recommend) you can use FFI and cast the original value into a byte array and use memcpy.
The Read Write Format wiki page contains functions that provide a way to batch / unpack integer values into a binary string.
Example
-- Write an integer in MSB order using width bytes.
function numbertobytes(num, width)
local function _n2b(t, width, num, rem)
if width == 0 then return table.concat(t) end
table.insert(t, 1, string.char(rem * 256))
return _n2b(t, width-1, math.modf(num/256))
end
return _n2b({}, width, math.modf(num/256))
end
io.write("<", numbertobytes(0x61626364, 4), ">\n")
Output
<abcd>