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 Google.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. TableGoogle.FlatBuffers.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. __offsetGoogle.FlatBuffers.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 __offsetGoogle.FlatBuffers.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" __indirectGoogle.FlatBuffers.Table55 public int __indirect(int offset) 56 { 57 return offset + bb.GetInt(offset); 58 } 59 __indirectGoogle.FlatBuffers.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. __stringGoogle.FlatBuffers.Table66 public string __string(int offset) 67 { 68 int stringOffset = bb.GetInt(offset); 69 if (stringOffset == 0) 70 return null; 71 72 offset += stringOffset; 73 var len = bb.GetInt(offset); 74 var startPos = offset + sizeof(int); 75 return bb.GetStringUTF8(startPos, len); 76 } 77 78 // Get the length of a vector whose offset is stored at "offset" in this object. __vector_lenGoogle.FlatBuffers.Table79 public int __vector_len(int offset) 80 { 81 offset += bb_pos; 82 offset += bb.GetInt(offset); 83 return bb.GetInt(offset); 84 } 85 86 // Get the start of data of a vector whose offset is stored at "offset" in this object. __vectorGoogle.FlatBuffers.Table87 public int __vector(int offset) 88 { 89 offset += bb_pos; 90 return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length 91 } 92 93 #if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER 94 // Get the data of a vector whoses offset is stored at "offset" in this object as an 95 // Spant<byte>. If the vector is not present in the ByteBuffer, 96 // then an empty span will be returned. 97 public Span<T> __vector_as_span<T>(int offset, int elementSize) where T : struct 98 { 99 if (!BitConverter.IsLittleEndian) 100 { 101 throw new NotSupportedException("Getting typed span on a Big Endian " + 102 "system is not support"); 103 } 104 105 var o = this.__offset(offset); 106 if (0 == o) 107 { 108 return new Span<T>(); 109 } 110 111 var pos = this.__vector(o); 112 var len = this.__vector_len(o); 113 return MemoryMarshal.Cast<byte, T>(bb.ToSpan(pos, len * elementSize)); 114 } 115 #else 116 // Get the data of a vector whoses offset is stored at "offset" in this object as an 117 // ArraySegment<byte>. If the vector is not present in the ByteBuffer, 118 // then a null value will be returned. __vector_as_arraysegment(int offset)119 public ArraySegment<byte>? __vector_as_arraysegment(int offset) 120 { 121 var o = this.__offset(offset); 122 if (0 == o) 123 { 124 return null; 125 } 126 127 var pos = this.__vector(o); 128 var len = this.__vector_len(o); 129 return bb.ToArraySegment(pos, len); 130 } 131 #endif 132 133 // Get the data of a vector whoses offset is stored at "offset" in this object as an 134 // T[]. If the vector is not present in the ByteBuffer, then a null value will be 135 // returned. 136 public T[] __vector_as_array<T>(int offset) 137 where T : struct 138 { 139 if(!BitConverter.IsLittleEndian) 140 { 141 throw new NotSupportedException("Getting typed arrays on a Big Endian " + 142 "system is not support"); 143 } 144 145 var o = this.__offset(offset); 146 if (0 == o) 147 { 148 return null; 149 } 150 151 var pos = this.__vector(o); 152 var len = this.__vector_len(o); 153 return bb.ToArray<T>(pos, len); 154 } 155 156 // Initialize any Table-derived type to point to the union at the given offset. 157 public T __union<T>(int offset) where T : struct, IFlatbufferObject 158 { 159 T t = new T(); __indirectIFlatbufferObject160 t.__init(__indirect(offset), bb); 161 return t; 162 } 163 __has_identifier(ByteBuffer bb, string ident)164 public static bool __has_identifier(ByteBuffer bb, string ident) 165 { 166 if (ident.Length != FlatBufferConstants.FileIdentifierLength) 167 throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, "ident"); 168 169 for (var i = 0; i < FlatBufferConstants.FileIdentifierLength; i++) 170 { 171 if (ident[i] != (char)bb.Get(bb.Position + sizeof(int) + i)) return false; 172 } 173 174 return true; 175 } 176 177 // Compare strings in the ByteBuffer. CompareStrings(int offset_1, int offset_2, ByteBuffer bb)178 public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb) 179 { 180 offset_1 += bb.GetInt(offset_1); 181 offset_2 += bb.GetInt(offset_2); 182 var len_1 = bb.GetInt(offset_1); 183 var len_2 = bb.GetInt(offset_2); 184 var startPos_1 = offset_1 + sizeof(int); 185 var startPos_2 = offset_2 + sizeof(int); 186 var len = Math.Min(len_1, len_2); 187 for(int i = 0; i < len; i++) { 188 byte b1 = bb.Get(i + startPos_1); 189 byte b2 = bb.Get(i + startPos_2); 190 if (b1 != b2) 191 return b1 - b2; 192 } 193 return len_1 - len_2; 194 } 195 196 // Compare string from the ByteBuffer with the string object CompareStrings(int offset_1, byte[] key, ByteBuffer bb)197 public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb) 198 { 199 offset_1 += bb.GetInt(offset_1); 200 var len_1 = bb.GetInt(offset_1); 201 var len_2 = key.Length; 202 var startPos_1 = offset_1 + sizeof(int); 203 var len = Math.Min(len_1, len_2); 204 for (int i = 0; i < len; i++) { 205 byte b = bb.Get(i + startPos_1); 206 if (b != key[i]) 207 return b - key[i]; 208 } 209 return len_1 - len_2; 210 } 211 } 212 } 213