local N = require("flatbuffers.numTypes")
local ba = require("flatbuffers.binaryarray")
local compat = require("flatbuffers.compat")
+local string_unpack = compat.string_unpack
local m = {}
end
for i, elem in ipairs(a) do
- local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * 2)
+ local x = string_unpack(VOffsetT.packFmt, b, 1 + (i - 1) * 2)
if x ~= 0 or elem ~= 0 then
local y = objectStart - elem
if x ~= y then
local vt2Offset = self.vtables[i]
local vt2Start = #self.bytes - vt2Offset
local vt2lenstr = self.bytes:Slice(vt2Start, vt2Start+1)
- local vt2Len = string.unpack(VOffsetT.packFmt, vt2lenstr, 1)
+ local vt2Len = string_unpack(VOffsetT.packFmt, vt2lenstr, 1)
local metadata = VtableMetadataFields * 2
local vt2End = vt2Start + vt2Len
local h = self.head
local k = #self.bytes - h + additionalBytes
- local alignsize = ((~k) + 1) & (size - 1) -- getAlignSize(k, size)
+ local alignsize = getAlignSize(k, size)
local desiredSize = alignsize + size + additionalBytes
--- /dev/null
+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
+
+
+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 == "<I1" then
+ return pack_I1(i)
+ elseif fmt == "<I2" then
+ return pack_I2(i)
+ elseif fmt == "<I4" then
+ return pack_I4(i)
+ elseif fmt == "<I8" then
+ return pack_I8(i)
+ elseif fmt == "<i1" then
+ return pack_i1(i)
+ elseif fmt == "<i2" then
+ return pack_i2(i)
+ elseif fmt == "<i4" then
+ return pack_i4(i)
+ elseif fmt == "<i8" then
+ return pack_i8(i)
+ elseif fmt == "<f" then
+ return pack_f(i)
+ elseif fmt == "<d" then
+ return pack_d(i)
+ else
+ error(string.format("FIXME: support fmt %s", fmt))
+ end
+end
+
+
+m.string_unpack = function(fmt, s, pos)
+ if not pos then
+ pos = 1
+ end
+
+ if fmt == "<I1" then
+ return unpack_I1(s, pos)
+ elseif fmt == "<I2" then
+ return unpack_I2(s, pos)
+ elseif fmt == "<I4" then
+ return unpack_I4(s, pos)
+ elseif fmt == "<I8" then
+ return unpack_I8(s, pos)
+ elseif fmt == "<i1" then
+ return unpack_i1(s, pos)
+ elseif fmt == "<i2" then
+ return unpack_i2(s, pos)
+ elseif fmt == "<i4" then
+ return unpack_i4(s, pos)
+ elseif fmt == "<i8" then
+ return unpack_i8(s, pos)
+ elseif fmt == "<f" then
+ return unpack_f(s, pos)
+ elseif fmt == "<d" then
+ return unpack_d(s, pos)
+ else
+ error(string.format("FIXME: support fmt %s", fmt))
+ end
+end
+
+
+return m