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