blob: 0f783bfebb907acead86e06aa492835963124749 [file] [log] [blame]
import Foundation
public struct Table {
public private(set) var bb: ByteBuffer
public private(set) var postion: Int32
public init(bb: ByteBuffer, position: Int32 = 0) {
guard isLitteEndian else {
fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
}
self.bb = bb
self.postion = position
}
public func offset(_ o: Int32) -> Int32 {
let vtable = postion - bb.read(def: Int32.self, position: Int(postion))
return o < bb.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(def: Int16.self, position: Int(vtable + o))) : 0
}
public func indirect(_ o: Int32) -> Int32 { return o + bb.read(def: Int32.self, position: Int(o)) }
/// String reads from the buffer with respect to position of the current table.
/// - Parameter offset: Offset of the string
public func string(at offset: Int32) -> String? {
return directString(at: offset + postion)
}
/// Direct string reads from the buffer disregarding the position of the table.
/// It would be preferable to use string unless the current position of the table is not needed
/// - Parameter offset: Offset of the string
public func directString(at offset: Int32) -> String? {
var offset = offset
offset += bb.read(def: Int32.self, position: Int(offset))
let count = bb.read(def: Int32.self, position: Int(offset))
let position = offset + Int32(MemoryLayout<Int32>.size)
return bb.readString(at: position, count: count)
}
/// Reads from the buffer with respect to the position in the table.
/// - Parameters:
/// - type: Type of Scalar that needs to be read from the buffer
/// - o: Offset of the Element
public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
return directRead(of: T.self, offset: o + postion)
}
/// Reads from the buffer disregarding the position of the table.
/// It would be used when reading from an
/// ```
/// let offset = __t.offset(10)
/// //Only used when the we already know what is the
/// // position in the table since __t.vector(at:)
/// // returns the index with respect to the position
/// __t.directRead(of: Byte.self,
/// offset: __t.vector(at: offset) + index * 1)
/// ```
/// - Parameters:
/// - type: Type of Scalar that needs to be read from the buffer
/// - o: Offset of the Element
public func directRead<T: Scalar>(of type: T.Type, offset o: Int32) -> T {
let r = bb.read(def: T.self, position: Int(o))
return r
}
public func union<T: FlatBufferObject>(_ o: Int32) -> T {
let o = o + postion
return directUnion(o)
}
public func directUnion<T: FlatBufferObject>(_ o: Int32) -> T {
return T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
}
public func getVector<T>(at off: Int32) -> [T]? {
let o = offset(off)
guard o != 0 else { return nil }
return bb.readSlice(index: vector(at: o), count: vector(count: o))
}
/// Vector count gets the count of Elements within the array
/// - Parameter o: start offset of the vector
/// - returns: Count of elements
public func vector(count o: Int32) -> Int32 {
var o = o
o += postion
o += bb.read(def: Int32.self, position: Int(o))
return bb.read(def: Int32.self, position: Int(o))
}
/// Vector start index in the buffer
/// - Parameter o:start offset of the vector
/// - returns: the start index of the vector
public func vector(at o: Int32) -> Int32 {
var o = o
o += postion
return o + bb.read(def: Int32.self, position: Int(o)) + 4
}
}
extension Table {
static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { return o + fbb.read(def: Int32.self, position: Int(o)) }
static public func offset(_ o: Int32, vOffset: Int32, fbb: ByteBuffer) -> Int32 {
let vTable = Int32(fbb.capacity) - o
return vTable + Int32(fbb.read(def: Int16.self, position: Int(vTable + vOffset - fbb.read(def: Int32.self, position: Int(vTable)))))
}
static public func compare(_ off1: Int32, _ off2: Int32, fbb: ByteBuffer) -> Int32 {
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
let _off2 = off2 + fbb.read(def: Int32.self, position: Int(off2))
let len1 = fbb.read(def: Int32.self, position: Int(_off1))
let len2 = fbb.read(def: Int32.self, position: Int(_off2))
let startPos1 = _off1 + memorySize
let startPos2 = _off2 + memorySize
let minValue = min(len1, len2)
for i in 0...minValue {
let b1 = fbb.read(def: Int8.self, position: Int(i + startPos1))
let b2 = fbb.read(def: Int8.self, position: Int(i + startPos2))
if b1 != b2 {
return Int32(b2 - b1)
}
}
return len1 - len2
}
static public func compare(_ off1: Int32, _ key: [Byte], fbb: ByteBuffer) -> Int32 {
let memorySize = Int32(MemoryLayout<Int32>.size)
let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
let len1 = fbb.read(def: Int32.self, position: Int(_off1))
let len2 = Int32(key.count)
let startPos1 = _off1 + memorySize
let minValue = min(len1, len2)
for i in 0..<minValue {
let b = fbb.read(def: Int8.self, position: Int(i + startPos1))
let byte = key[Int(i)]
if b != byte {
return Int32(b - Int8(byte))
}
}
return len1 - len2
}
}