145 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Swift
		
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Swift
		
	
	
	
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
 | 
						|
    }
 | 
						|
}
 |