blob: 451398cd507946875de6cbc223b2d171dc649326 [file] [log] [blame]
Austin Schuh58b9b472020-11-25 19:12:44 -08001/*
2 * Copyright 2020 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Austin Schuh272c6132020-11-14 16:37:52 -080017import Foundation
18
19public struct Table {
Austin Schuh58b9b472020-11-25 19:12:44 -080020 public private(set) var bb: ByteBuffer
21 public private(set) var postion: Int32
Austin Schuh272c6132020-11-14 16:37:52 -080022
Austin Schuh58b9b472020-11-25 19:12:44 -080023 public init(bb: ByteBuffer, position: Int32 = 0) {
24 guard isLitteEndian else {
25 fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
Austin Schuh272c6132020-11-14 16:37:52 -080026 }
Austin Schuh58b9b472020-11-25 19:12:44 -080027 self.bb = bb
28 postion = position
29 }
Austin Schuh272c6132020-11-14 16:37:52 -080030
Austin Schuh58b9b472020-11-25 19:12:44 -080031 public func offset(_ o: Int32) -> Int32 {
32 let vtable = postion - bb.read(def: Int32.self, position: Int(postion))
33 return o < bb.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(
34 def: Int16.self,
35 position: Int(vtable + o))) : 0
36 }
37
38 public func indirect(_ o: Int32) -> Int32 { o + bb.read(def: Int32.self, position: Int(o)) }
39
40 /// String reads from the buffer with respect to position of the current table.
41 /// - Parameter offset: Offset of the string
42 public func string(at offset: Int32) -> String? {
43 directString(at: offset + postion)
44 }
45
46 /// Direct string reads from the buffer disregarding the position of the table.
47 /// It would be preferable to use string unless the current position of the table is not needed
48 /// - Parameter offset: Offset of the string
49 public func directString(at offset: Int32) -> String? {
50 var offset = offset
51 offset += bb.read(def: Int32.self, position: Int(offset))
52 let count = bb.read(def: Int32.self, position: Int(offset))
53 let position = offset + Int32(MemoryLayout<Int32>.size)
54 return bb.readString(at: position, count: count)
55 }
56
57 /// Reads from the buffer with respect to the position in the table.
58 /// - Parameters:
59 /// - type: Type of Scalar that needs to be read from the buffer
60 /// - o: Offset of the Element
61 public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
62 directRead(of: T.self, offset: o + postion)
63 }
64
65 /// Reads from the buffer disregarding the position of the table.
66 /// It would be used when reading from an
67 /// ```
68 /// let offset = __t.offset(10)
69 /// //Only used when the we already know what is the
70 /// // position in the table since __t.vector(at:)
71 /// // returns the index with respect to the position
72 /// __t.directRead(of: Byte.self,
73 /// offset: __t.vector(at: offset) + index * 1)
74 /// ```
75 /// - Parameters:
76 /// - type: Type of Scalar that needs to be read from the buffer
77 /// - o: Offset of the Element
78 public func directRead<T: Scalar>(of type: T.Type, offset o: Int32) -> T {
79 let r = bb.read(def: T.self, position: Int(o))
80 return r
81 }
82
83 public func union<T: FlatBufferObject>(_ o: Int32) -> T {
84 let o = o + postion
85 return directUnion(o)
86 }
87
88 public func directUnion<T: FlatBufferObject>(_ o: Int32) -> T {
89 T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
90 }
91
92 public func getVector<T>(at off: Int32) -> [T]? {
93 let o = offset(off)
94 guard o != 0 else { return nil }
95 return bb.readSlice(index: vector(at: o), count: vector(count: o))
96 }
97
98 /// Vector count gets the count of Elements within the array
99 /// - Parameter o: start offset of the vector
100 /// - returns: Count of elements
101 public func vector(count o: Int32) -> Int32 {
102 var o = o
103 o += postion
104 o += bb.read(def: Int32.self, position: Int(o))
105 return bb.read(def: Int32.self, position: Int(o))
106 }
107
108 /// Vector start index in the buffer
109 /// - Parameter o:start offset of the vector
110 /// - returns: the start index of the vector
111 public func vector(at o: Int32) -> Int32 {
112 var o = o
113 o += postion
114 return o + bb.read(def: Int32.self, position: Int(o)) + 4
115 }
Austin Schuh272c6132020-11-14 16:37:52 -0800116}
117
118extension Table {
Austin Schuh58b9b472020-11-25 19:12:44 -0800119
120 static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { o + fbb.read(
121 def: Int32.self,
122 position: Int(o)) }
123
124 static public func offset(_ o: Int32, vOffset: Int32, fbb: ByteBuffer) -> Int32 {
125 let vTable = Int32(fbb.capacity) - o
126 return vTable + Int32(fbb.read(
127 def: Int16.self,
128 position: Int(vTable + vOffset - fbb.read(def: Int32.self, position: Int(vTable)))))
129 }
130
131 static public func compare(_ off1: Int32, _ off2: Int32, fbb: ByteBuffer) -> Int32 {
132 let memorySize = Int32(MemoryLayout<Int32>.size)
133 let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
134 let _off2 = off2 + fbb.read(def: Int32.self, position: Int(off2))
135 let len1 = fbb.read(def: Int32.self, position: Int(_off1))
136 let len2 = fbb.read(def: Int32.self, position: Int(_off2))
137 let startPos1 = _off1 + memorySize
138 let startPos2 = _off2 + memorySize
139 let minValue = min(len1, len2)
140 for i in 0...minValue {
141 let b1 = fbb.read(def: Int8.self, position: Int(i + startPos1))
142 let b2 = fbb.read(def: Int8.self, position: Int(i + startPos2))
143 if b1 != b2 {
144 return Int32(b2 - b1)
145 }
Austin Schuh272c6132020-11-14 16:37:52 -0800146 }
Austin Schuh58b9b472020-11-25 19:12:44 -0800147 return len1 - len2
148 }
149
150 static public func compare(_ off1: Int32, _ key: [Byte], fbb: ByteBuffer) -> Int32 {
151 let memorySize = Int32(MemoryLayout<Int32>.size)
152 let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
153 let len1 = fbb.read(def: Int32.self, position: Int(_off1))
154 let len2 = Int32(key.count)
155 let startPos1 = _off1 + memorySize
156 let minValue = min(len1, len2)
157 for i in 0..<minValue {
158 let b = fbb.read(def: Int8.self, position: Int(i + startPos1))
159 let byte = key[Int(i)]
160 if b != byte {
161 return Int32(b - Int8(byte))
162 }
Austin Schuh272c6132020-11-14 16:37:52 -0800163 }
Austin Schuh58b9b472020-11-25 19:12:44 -0800164 return len1 - len2
165 }
Austin Schuh272c6132020-11-14 16:37:52 -0800166}