Revert "[C#] Fix truncated ArraySegment<byte> if elementSize != 1 (#6462)" (#6488)
[platform/upstream/flatbuffers.git] / net / FlatBuffers / Table.cs
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.
34         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.
42         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
48         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"
55         public int __indirect(int offset)
56         {
57             return offset + bb.GetInt(offset);
58         }
59
60         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.
66         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.
75         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.
83         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&lt;byte&gt;. 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&lt;byte&gt;. If the vector is not present in the ByteBuffer,
114         // then a null value will be returned.
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();
156             t.__init(__indirect(offset), bb);
157             return t;
158         }
159
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.
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
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 }