1 /* 2 * Copyright 2014 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 17 using System; 18 using System.Text; 19 using System.Runtime.InteropServices; 20 21 namespace FlatBuffers 22 { 23 /// <summary> 24 /// All tables in the generated code derive from this struct, and add their own accessors. 25 /// </summary> 26 public struct Table 27 { 28 public int bb_pos { get; private set; } 29 public ByteBuffer bb { get; private set; } 30 31 public ByteBuffer ByteBuffer { get { return bb; } } 32 33 // Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within. TableFlatBuffers.Table34 public Table(int _i, ByteBuffer _bb) : this() 35 { 36 bb = _bb; 37 bb_pos = _i; 38 } 39 40 // Look up a field in the vtable, return an offset into the object, or 0 if the field is not 41 // present. __offsetFlatBuffers.Table42 public int __offset(int vtableOffset) 43 { 44 int vtable = bb_pos - bb.GetInt(bb_pos); 45 return vtableOffset < bb.GetShort(vtable) ? (int)bb.GetShort(vtable + vtableOffset) : 0; 46 } 47 __offsetFlatBuffers.Table48 public static int __offset(int vtableOffset, int offset, ByteBuffer bb) 49 { 50 int vtable = bb.Length - offset; 51 return (int)bb.GetShort(vtable + vtableOffset - bb.GetInt(vtable)) + vtable; 52 } 53 54 // Retrieve the relative offset stored at "offset" __indirectFlatBuffers.Table55 public int __indirect(int offset) 56 { 57 return offset + bb.GetInt(offset); 58 } 59 __indirectFlatBuffers.Table60 public static int __indirect(int offset, ByteBuffer bb) 61 { 62 return offset + bb.GetInt(offset); 63 } 64 65 // Create a .NET String from UTF-8 data stored inside the flatbuffer. __stringFlatBuffers.Table66 public string __string(int offset) 67 { 68 offset += bb.GetInt(offset); 69 var len = bb.GetInt(offset); 70 var startPos = offset + sizeof(int); 71 return bb.GetStringUTF8(startPos, len); 72 } 73 74 // Get the length of a vector whose offset is stored at "offset" in this object. __vector_lenFlatBuffers.Table75 public int __vector_len(int offset) 76 { 77 offset += bb_pos; 78 offset += bb.GetInt(offset); 79 return bb.GetInt(offset); 80 } 81 82 // Get the start of data of a vector whose offset is stored at "offset" in this object. __vectorFlatBuffers.Table83 public int __vector(int offset) 84 { 85 offset += bb_pos; 86 return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length 87 } 88 89 #if ENABLE_SPAN_T && (UNSAFE_BYTEBUFFER || NETSTANDARD2_1) 90 // Get the data of a vector whoses offset is stored at "offset" in this object as an 91 // Spant<byte>. If the vector is not present in the ByteBuffer, 92 // then an empty span will be returned. 93 public Span<T> __vector_as_span<T>(int offset, int elementSize) where T : struct 94 { 95 if (!BitConverter.IsLittleEndian) 96 { 97 throw new NotSupportedException("Getting typed span on a Big Endian " + 98 "system is not support"); 99 } 100 101 var o = this.__offset(offset); 102 if (0 == o) 103 { 104 return new Span<T>(); 105 } 106 107 var pos = this.__vector(o); 108 var len = this.__vector_len(o); 109 return MemoryMarshal.Cast<byte, T>(bb.ToSpan(pos, len * elementSize)); 110 } 111 #else 112 // Get the data of a vector whoses offset is stored at "offset" in this object as an 113 // ArraySegment<byte>. If the vector is not present in the ByteBuffer, 114 // then a null value will be returned. __vector_as_arraysegment(int offset)115 public ArraySegment<byte>? __vector_as_arraysegment(int offset) 116 { 117 var o = this.__offset(offset); 118 if (0 == o) 119 { 120 return null; 121 } 122 123 var pos = this.__vector(o); 124 var len = this.__vector_len(o); 125 return bb.ToArraySegment(pos, len); 126 } 127 #endif 128 129 // Get the data of a vector whoses offset is stored at "offset" in this object as an 130 // T[]. If the vector is not present in the ByteBuffer, then a null value will be 131 // returned. 132 public T[] __vector_as_array<T>(int offset) 133 where T : struct 134 { 135 if(!BitConverter.IsLittleEndian) 136 { 137 throw new NotSupportedException("Getting typed arrays on a Big Endian " + 138 "system is not support"); 139 } 140 141 var o = this.__offset(offset); 142 if (0 == o) 143 { 144 return null; 145 } 146 147 var pos = this.__vector(o); 148 var len = this.__vector_len(o); 149 return bb.ToArray<T>(pos, len); 150 } 151 152 // Initialize any Table-derived type to point to the union at the given offset. 153 public T __union<T>(int offset) where T : struct, IFlatbufferObject 154 { 155 T t = new T(); __indirectIFlatbufferObject156 t.__init(__indirect(offset), bb); 157 return t; 158 } 159 __has_identifier(ByteBuffer bb, string ident)160 public static bool __has_identifier(ByteBuffer bb, string ident) 161 { 162 if (ident.Length != FlatBufferConstants.FileIdentifierLength) 163 throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, "ident"); 164 165 for (var i = 0; i < FlatBufferConstants.FileIdentifierLength; i++) 166 { 167 if (ident[i] != (char)bb.Get(bb.Position + sizeof(int) + i)) return false; 168 } 169 170 return true; 171 } 172 173 // Compare strings in the ByteBuffer. CompareStrings(int offset_1, int offset_2, ByteBuffer bb)174 public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb) 175 { 176 offset_1 += bb.GetInt(offset_1); 177 offset_2 += bb.GetInt(offset_2); 178 var len_1 = bb.GetInt(offset_1); 179 var len_2 = bb.GetInt(offset_2); 180 var startPos_1 = offset_1 + sizeof(int); 181 var startPos_2 = offset_2 + sizeof(int); 182 var len = Math.Min(len_1, len_2); 183 for(int i = 0; i < len; i++) { 184 byte b1 = bb.Get(i + startPos_1); 185 byte b2 = bb.Get(i + startPos_2); 186 if (b1 != b2) 187 return b1 - b2; 188 } 189 return len_1 - len_2; 190 } 191 192 // Compare string from the ByteBuffer with the string object CompareStrings(int offset_1, byte[] key, ByteBuffer bb)193 public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb) 194 { 195 offset_1 += bb.GetInt(offset_1); 196 var len_1 = bb.GetInt(offset_1); 197 var len_2 = key.Length; 198 var startPos_1 = offset_1 + sizeof(int); 199 var len = Math.Min(len_1, len_2); 200 for (int i = 0; i < len; i++) { 201 byte b = bb.Get(i + startPos_1); 202 if (b != key[i]) 203 return b - key[i]; 204 } 205 return len_1 - len_2; 206 } 207 } 208 } 209