local bit = require("bit") local ffi = require("ffi") local band = bit.band local bnot = bit.bnot local m = {} local Uint8Bound = 256 -- bound is the max uintN + 1 local Uint16Bound = 65536 local Uint32Bound = 4294967296 if not table.unpack then table.unpack = unpack end if not table.pack then table.pack = pack end m.GetAlignSize = function(k, size) return band((bnot(k) + 1), (size - 1)) end local function pack_I1(n) return string.char(n) end local function pack_i1(n) if n < 0 then n = Uint8Bound + n end return pack_I1(n) end local function unpack_I1(n, pos) return string.byte(n, pos) end local function unpack_i1(n, pos) local res = unpack_I1(n, pos) if res >= Uint8Bound / 2 then return res - Uint8Bound end return res end local b2 = ffi.new("unsigned char[2]") local function pack_I2(n) for i = 0, 1 do b2[i] = bit.band(n, 255) n = bit.rshift(n, 8) end return ffi.string(b2, 2) end local function pack_i2(n) if n < 0 then n = Uint16Bound + n end return pack_I2(n) end local function unpack_I2(n, pos) local a, b = string.byte(n, pos, pos + 1) return b * Uint8Bound + a end local function unpack_i2(n, pos) local res = unpack_I2(n, pos) if res >= Uint16Bound / 2 then return res - Uint16Bound end return res end local b4 = ffi.new("unsigned char[4]") local function pack_I4(n) for i = 0, 3 do b4[i] = bit.band(n, 255) n = bit.rshift(n, 8) end return ffi.string(b4, 4) end local function pack_i4(n) if n < 0 then n = Uint32Bound + n end return pack_I4(n) end local function unpack_I4(n, pos) local a, b, c, d = string.byte(n, pos, pos + 3) return Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a end local function unpack_i4(n, pos) local res = unpack_I4(n, pos) if res >= Uint32Bound / 2 then return res - Uint32Bound end return res end local b8 = ffi.new("unsigned char[8]") local function pack_I8(n) n = ffi.cast("unsigned long long", n) local hi = math.floor(tonumber(n / Uint32Bound)) local li = n % Uint32Bound for i = 0, 3 do b8[i] = bit.band(li, 255) li = bit.rshift(li, 8) end for i = 4, 7 do b8[i] = bit.band(hi, 255) hi = bit.rshift(hi, 8) end return ffi.string(b8, 8) end local function pack_i8(n) n = ffi.cast("signed long long", n) return pack_I8(n) end local function unpack_I8(n, pos) local a, b, c, d = string.byte(n, pos, pos + 3) local li = Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a local a, b, c, d = string.byte(n, pos + 4, pos + 7) local hi = Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a return ffi.cast("unsigned long long", hi) * Uint32Bound + li end local function unpack_i8(n, pos) local res = unpack_I8(n, pos) return ffi.cast("signed long long", res) end local bf = ffi.new("float[1]") local function pack_f(n) bf[0] = n return ffi.string(bf, 4) end local function unpack_f(n, pos) ffi.copy(bf, ffi.cast("char *", n) + pos - 1, 4) return tonumber(bf[0]) end local bd = ffi.new("double[1]") local function pack_d(n) bd[0] = n return ffi.string(bd, 8) end local function unpack_d(n, pos) ffi.copy(bd, ffi.cast("char *", n) + pos - 1, 8) return tonumber(bd[0]) end m.string_pack = function(fmt, i, ...) if fmt == "