Squashed 'third_party/flatbuffers/' content from commit acc9990ab
Change-Id: I48550d40d78fea996ebe74e9723a5d1f910de491
git-subtree-dir: third_party/flatbuffers
git-subtree-split: acc9990abd2206491480291b0f85f925110102ea
diff --git a/lua/flatbuffers/builder.lua b/lua/flatbuffers/builder.lua
new file mode 100644
index 0000000..2fb2220
--- /dev/null
+++ b/lua/flatbuffers/builder.lua
@@ -0,0 +1,369 @@
+local N = require("flatbuffers.numTypes")
+local ba = require("flatbuffers.binaryarray")
+local compat = require("flatbuffers.compat")
+
+local m = {}
+
+local mt = {}
+
+-- get locals for faster access
+local VOffsetT = N.VOffsetT
+local UOffsetT = N.UOffsetT
+local SOffsetT = N.SOffsetT
+local Bool = N.Bool
+local Uint8 = N.Uint8
+local Uint16 = N.Uint16
+local Uint32 = N.Uint32
+local Uint64 = N.Uint64
+local Int8 = N.Int8
+local Int16 = N.Int16
+local Int32 = N.Int32
+local Int64 = N.Int64
+local Float32 = N.Float32
+local Float64 = N.Float64
+
+local MAX_BUFFER_SIZE = 0x80000000 -- 2 GB
+local VtableMetadataFields = 2
+
+local getAlignSize = compat.GetAlignSize
+
+local function vtableEqual(a, objectStart, b)
+ UOffsetT:EnforceNumber(objectStart)
+ if (#a * VOffsetT.bytewidth) ~= #b then
+ return false
+ end
+
+ for i, elem in ipairs(a) do
+ local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * VOffsetT.bytewidth)
+ if x ~= 0 or elem ~= 0 then
+ local y = objectStart - elem
+ if x ~= y then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+function m.New(initialSize)
+ assert(0 <= initialSize and initialSize < MAX_BUFFER_SIZE)
+ local o =
+ {
+ finished = false,
+ bytes = ba.New(initialSize),
+ nested = false,
+ head = initialSize,
+ minalign = 1,
+ vtables = {}
+ }
+ setmetatable(o, {__index = mt})
+ return o
+end
+
+function mt:Output(full)
+ assert(self.finished, "Builder Not Finished")
+ if full then
+ return self.bytes:Slice()
+ else
+ return self.bytes:Slice(self.head)
+ end
+end
+
+function mt:StartObject(numFields)
+ assert(not self.nested)
+
+ local vtable = {}
+
+ for _=1,numFields do
+ table.insert(vtable, 0)
+ end
+
+ self.currentVTable = vtable
+ self.objectEnd = self:Offset()
+ self.nested = true
+end
+
+function mt:WriteVtable()
+ self:PrependSOffsetTRelative(0)
+ local objectOffset = self:Offset()
+
+ local exisitingVTable
+ local i = #self.vtables
+ while i >= 1 do
+ if self.vtables[i] == 0 then
+ table.remove(self.vtables,i)
+ end
+ i = i - 1
+ end
+
+ i = #self.vtables
+ while i >= 1 do
+
+ 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 metadata = VtableMetadataFields * VOffsetT.bytewidth
+ local vt2End = vt2Start + vt2Len
+ local vt2 = self.bytes:Slice(vt2Start+metadata,vt2End)
+
+ if vtableEqual(self.currentVTable, objectOffset, vt2) then
+ exisitingVTable = vt2Offset
+ break
+ end
+
+ i = i - 1
+ end
+
+ if not exisitingVTable then
+ i = #self.currentVTable
+ while i >= 1 do
+ local off = 0
+ local a = self.currentVTable[i]
+ if a and a ~= 0 then
+ off = objectOffset - a
+ end
+ self:PrependVOffsetT(off)
+
+ i = i - 1
+ end
+
+ local objectSize = objectOffset - self.objectEnd
+ self:PrependVOffsetT(objectSize)
+
+ local vBytes = #self.currentVTable + VtableMetadataFields
+ vBytes = vBytes * VOffsetT.bytewidth
+ self:PrependVOffsetT(vBytes)
+
+ local objectStart = #self.bytes - objectOffset
+ self.bytes:Set(SOffsetT:Pack(self:Offset() - objectOffset),objectStart)
+
+ table.insert(self.vtables, self:Offset())
+ else
+ local objectStart = #self.bytes - objectOffset
+ self.head = objectStart
+ self.bytes:Set(SOffsetT:Pack(exisitingVTable - objectOffset),self.head)
+ end
+
+ self.currentVTable = nil
+ return objectOffset
+end
+
+function mt:EndObject()
+ assert(self.nested)
+ self.nested = false
+ return self:WriteVtable()
+end
+
+local function growByteBuffer(self, desiredSize)
+ local s = #self.bytes
+ assert(s < MAX_BUFFER_SIZE, "Flat Buffers cannot grow buffer beyond 2 gigabytes")
+ local newsize = s
+ repeat
+ newsize = math.min(newsize * 2, MAX_BUFFER_SIZE)
+ if newsize == 0 then newsize = 1 end
+ until newsize > desiredSize
+
+ self.bytes:Grow(newsize)
+end
+
+function mt:Head()
+ return self.head
+end
+
+function mt:Offset()
+ return #self.bytes - self.head
+end
+
+function mt:Pad(n)
+ if n > 0 then
+ -- pads are 8-bit, so skip the bytewidth lookup
+ local h = self.head - n -- UInt8
+ self.head = h
+ self.bytes:Pad(n, h)
+ end
+end
+
+function mt:Prep(size, additionalBytes)
+ if size > self.minalign then
+ self.minalign = size
+ end
+
+ local h = self.head
+
+ local k = #self.bytes - h + additionalBytes
+ local alignsize = ((~k) + 1) & (size - 1) -- getAlignSize(k, size)
+
+ local desiredSize = alignsize + size + additionalBytes
+
+ while self.head < desiredSize do
+ local oldBufSize = #self.bytes
+ growByteBuffer(self, desiredSize)
+ local updatedHead = self.head + #self.bytes - oldBufSize
+ self.head = updatedHead
+ end
+
+ self:Pad(alignsize)
+end
+
+function mt:PrependSOffsetTRelative(off)
+ self:Prep(SOffsetT.bytewidth, 0)
+ assert(off <= self:Offset(), "Offset arithmetic error")
+ local off2 = self:Offset() - off + SOffsetT.bytewidth
+ self:Place(off2, SOffsetT)
+end
+
+function mt:PrependUOffsetTRelative(off)
+ self:Prep(UOffsetT.bytewidth, 0)
+ local soffset = self:Offset()
+ if off <= soffset then
+ local off2 = soffset - off + UOffsetT.bytewidth
+ self:Place(off2, UOffsetT)
+ else
+ error("Offset arithmetic error")
+ end
+end
+
+function mt:StartVector(elemSize, numElements, alignment)
+ assert(not self.nested)
+ self.nested = true
+ self:Prep(Uint32.bytewidth, elemSize * numElements)
+ self:Prep(alignment, elemSize * numElements)
+ return self:Offset()
+end
+
+function mt:EndVector(vectorNumElements)
+ assert(self.nested)
+ self.nested = false
+ self:Place(vectorNumElements, UOffsetT)
+ return self:Offset()
+end
+
+function mt:CreateString(s)
+ assert(not self.nested)
+ self.nested = true
+
+ assert(type(s) == "string")
+
+ self:Prep(UOffsetT.bytewidth, (#s + 1)*Uint8.bytewidth)
+ self:Place(0, Uint8)
+
+ local l = #s
+ self.head = self.head - l
+
+ self.bytes:Set(s, self.head, self.head + l)
+
+ return self:EndVector(#s)
+end
+
+function mt:CreateByteVector(x)
+ assert(not self.nested)
+ self.nested = true
+ self:Prep(UOffsetT.bytewidth, #x*Uint8.bytewidth)
+
+ local l = #x
+ self.head = self.head - l
+
+ self.bytes:Set(x, self.head, self.head + l)
+
+ return self:EndVector(#x)
+end
+
+function mt:Slot(slotnum)
+ assert(self.nested)
+ -- n.b. slot number is 0-based
+ self.currentVTable[slotnum + 1] = self:Offset()
+end
+
+local function finish(self, rootTable, sizePrefix)
+ UOffsetT:EnforceNumber(rootTable)
+ local prepSize = UOffsetT.bytewidth
+ if sizePrefix then
+ prepSize = prepSize + Int32.bytewidth
+ end
+
+ self:Prep(self.minalign, prepSize)
+ self:PrependUOffsetTRelative(rootTable)
+ if sizePrefix then
+ local size = #self.bytes - self.head
+ Int32:EnforceNumber(size)
+ self:PrependInt32(size)
+ end
+ self.finished = true
+ return self.head
+end
+
+function mt:Finish(rootTable)
+ return finish(self, rootTable, false)
+end
+
+function mt:FinishSizePrefixed(rootTable)
+ return finish(self, rootTable, true)
+end
+
+function mt:Prepend(flags, off)
+ self:Prep(flags.bytewidth, 0)
+ self:Place(off, flags)
+end
+
+function mt:PrependSlot(flags, o, x, d)
+ flags:EnforceNumber(x)
+ flags:EnforceNumber(d)
+ if x ~= d then
+ self:Prepend(flags, x)
+ self:Slot(o)
+ end
+end
+
+function mt:PrependBoolSlot(...) self:PrependSlot(Bool, ...) end
+function mt:PrependByteSlot(...) self:PrependSlot(Uint8, ...) end
+function mt:PrependUint8Slot(...) self:PrependSlot(Uint8, ...) end
+function mt:PrependUint16Slot(...) self:PrependSlot(Uint16, ...) end
+function mt:PrependUint32Slot(...) self:PrependSlot(Uint32, ...) end
+function mt:PrependUint64Slot(...) self:PrependSlot(Uint64, ...) end
+function mt:PrependInt8Slot(...) self:PrependSlot(Int8, ...) end
+function mt:PrependInt16Slot(...) self:PrependSlot(Int16, ...) end
+function mt:PrependInt32Slot(...) self:PrependSlot(Int32, ...) end
+function mt:PrependInt64Slot(...) self:PrependSlot(Int64, ...) end
+function mt:PrependFloat32Slot(...) self:PrependSlot(Float32, ...) end
+function mt:PrependFloat64Slot(...) self:PrependSlot(Float64, ...) end
+
+function mt:PrependUOffsetTRelativeSlot(o,x,d)
+ if x~=d then
+ self:PrependUOffsetTRelative(x)
+ self:Slot(o)
+ end
+end
+
+function mt:PrependStructSlot(v,x,d)
+ UOffsetT:EnforceNumber(d)
+ if x~=d then
+ UOffsetT:EnforceNumber(x)
+ assert(x == self:Offset(), "Tried to write a Struct at an Offset that is different from the current Offset of the Builder.")
+ self:Slot(v)
+ end
+end
+
+function mt:PrependBool(x) self:Prepend(Bool, x) end
+function mt:PrependByte(x) self:Prepend(Uint8, x) end
+function mt:PrependUint8(x) self:Prepend(Uint8, x) end
+function mt:PrependUint16(x) self:Prepend(Uint16, x) end
+function mt:PrependUint32(x) self:Prepend(Uint32, x) end
+function mt:PrependUint64(x) self:Prepend(Uint64, x) end
+function mt:PrependInt8(x) self:Prepend(Int8, x) end
+function mt:PrependInt16(x) self:Prepend(Int16, x) end
+function mt:PrependInt32(x) self:Prepend(Int32, x) end
+function mt:PrependInt64(x) self:Prepend(Int64, x) end
+function mt:PrependFloat32(x) self:Prepend(Float32, x) end
+function mt:PrependFloat64(x) self:Prepend(Float64, x) end
+function mt:PrependVOffsetT(x) self:Prepend(VOffsetT, x) end
+
+function mt:Place(x, flags)
+ local d = flags:EnforceNumberAndPack(x)
+ local h = self.head - flags.bytewidth
+ self.head = h
+ self.bytes:Set(d, h)
+end
+
+return m