I am writing a program that needs to serialize small (up to 16 bit) signed integers to a binary file. As part of that, I need to write a function that can split an integer into two bytes and another function that can convert this pair of bytes back to the original integer.
The first idea that came to my mind was to solve this problem similarly to how I would solve it C:
function dump_i16(n)
assert (-0x8000 <= n and n < 0x8000) -- 16 bit
local b1 = (n >> 8) & 0xff
local b2 = (n >> 0) & 0xff
return b1, b2
end
function read_i16(b1, b2)
assert (0 <= b1 and b1 <= 0xff) -- 8 bit
assert (0 <= b2 and b2 <= 0xff) -- 8 bit
return (b1 << 8) | (b2 << 0)
end
However, these functions break on negative numbers because Lua integers actually have 64 bits and I am only preserving the lower 16 bits:
-- Positive numbers are OK
print( read_i16(dump_i16(17)) ) -- 17
print( read_i16(dump_i16(42)) ) -- 42
-- Negative numbers don't round trip.
print( read_i16(dump_i16(-1)) ) -- 65535 = 2^16 - 1
print( read_i16(dump_i16(-20)) ) -- 65516 = 2^16 - 20
What would be the cleanest way to modify my read_i16
function so it works correctly for negative numbers?
I would prefer to do this using pure Lua 5.3 if possible, without going down to writing C code.