xref: /aosp_15_r20/external/flatbuffers/net/FlatBuffers/FlatBufferBuilder.cs (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker  * Copyright 2014 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker  *
4*890232f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker  *
8*890232f2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker  *
10*890232f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker  * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker  */
16*890232f2SAndroid Build Coastguard Worker 
17*890232f2SAndroid Build Coastguard Worker 
18*890232f2SAndroid Build Coastguard Worker using System;
19*890232f2SAndroid Build Coastguard Worker using System.Collections.Generic;
20*890232f2SAndroid Build Coastguard Worker using System.Text;
21*890232f2SAndroid Build Coastguard Worker 
22*890232f2SAndroid Build Coastguard Worker /// @file
23*890232f2SAndroid Build Coastguard Worker /// @addtogroup flatbuffers_csharp_api
24*890232f2SAndroid Build Coastguard Worker /// @{
25*890232f2SAndroid Build Coastguard Worker 
26*890232f2SAndroid Build Coastguard Worker namespace FlatBuffers
27*890232f2SAndroid Build Coastguard Worker {
28*890232f2SAndroid Build Coastguard Worker     /// <summary>
29*890232f2SAndroid Build Coastguard Worker     /// Responsible for building up and accessing a FlatBuffer formatted byte
30*890232f2SAndroid Build Coastguard Worker     /// array (via ByteBuffer).
31*890232f2SAndroid Build Coastguard Worker     /// </summary>
32*890232f2SAndroid Build Coastguard Worker     public class FlatBufferBuilder
33*890232f2SAndroid Build Coastguard Worker     {
34*890232f2SAndroid Build Coastguard Worker         private int _space;
35*890232f2SAndroid Build Coastguard Worker         private ByteBuffer _bb;
36*890232f2SAndroid Build Coastguard Worker         private int _minAlign = 1;
37*890232f2SAndroid Build Coastguard Worker 
38*890232f2SAndroid Build Coastguard Worker         // The vtable for the current table (if _vtableSize >= 0)
39*890232f2SAndroid Build Coastguard Worker         private int[] _vtable = new int[16];
40*890232f2SAndroid Build Coastguard Worker         // The size of the vtable. -1 indicates no vtable
41*890232f2SAndroid Build Coastguard Worker         private int _vtableSize = -1;
42*890232f2SAndroid Build Coastguard Worker         // Starting offset of the current struct/table.
43*890232f2SAndroid Build Coastguard Worker         private int _objectStart;
44*890232f2SAndroid Build Coastguard Worker         // List of offsets of all vtables.
45*890232f2SAndroid Build Coastguard Worker         private int[] _vtables = new int[16];
46*890232f2SAndroid Build Coastguard Worker         // Number of entries in `vtables` in use.
47*890232f2SAndroid Build Coastguard Worker         private int _numVtables = 0;
48*890232f2SAndroid Build Coastguard Worker         // For the current vector being built.
49*890232f2SAndroid Build Coastguard Worker         private int _vectorNumElems = 0;
50*890232f2SAndroid Build Coastguard Worker 
51*890232f2SAndroid Build Coastguard Worker         // For CreateSharedString
52*890232f2SAndroid Build Coastguard Worker         private Dictionary<string, StringOffset> _sharedStringMap = null;
53*890232f2SAndroid Build Coastguard Worker 
54*890232f2SAndroid Build Coastguard Worker         /// <summary>
55*890232f2SAndroid Build Coastguard Worker         /// Create a FlatBufferBuilder with a given initial size.
56*890232f2SAndroid Build Coastguard Worker         /// </summary>
57*890232f2SAndroid Build Coastguard Worker         /// <param name="initialSize">
58*890232f2SAndroid Build Coastguard Worker         /// The initial size to use for the internal buffer.
59*890232f2SAndroid Build Coastguard Worker         /// </param>
FlatBufferBuilder(int initialSize)60*890232f2SAndroid Build Coastguard Worker         public FlatBufferBuilder(int initialSize)
61*890232f2SAndroid Build Coastguard Worker         {
62*890232f2SAndroid Build Coastguard Worker             if (initialSize <= 0)
63*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentOutOfRangeException("initialSize",
64*890232f2SAndroid Build Coastguard Worker                     initialSize, "Must be greater than zero");
65*890232f2SAndroid Build Coastguard Worker             _space = initialSize;
66*890232f2SAndroid Build Coastguard Worker             _bb = new ByteBuffer(initialSize);
67*890232f2SAndroid Build Coastguard Worker         }
68*890232f2SAndroid Build Coastguard Worker 
69*890232f2SAndroid Build Coastguard Worker         /// <summary>
70*890232f2SAndroid Build Coastguard Worker         /// Create a FlatBufferBuilder backed by the pased in ByteBuffer
71*890232f2SAndroid Build Coastguard Worker         /// </summary>
72*890232f2SAndroid Build Coastguard Worker         /// <param name="buffer">The ByteBuffer to write to</param>
FlatBufferBuilder(ByteBuffer buffer)73*890232f2SAndroid Build Coastguard Worker         public FlatBufferBuilder(ByteBuffer buffer)
74*890232f2SAndroid Build Coastguard Worker         {
75*890232f2SAndroid Build Coastguard Worker             _bb = buffer;
76*890232f2SAndroid Build Coastguard Worker             _space = buffer.Length;
77*890232f2SAndroid Build Coastguard Worker             buffer.Reset();
78*890232f2SAndroid Build Coastguard Worker         }
79*890232f2SAndroid Build Coastguard Worker 
80*890232f2SAndroid Build Coastguard Worker         /// <summary>
81*890232f2SAndroid Build Coastguard Worker         /// Reset the FlatBufferBuilder by purging all data that it holds.
82*890232f2SAndroid Build Coastguard Worker         /// </summary>
Clear()83*890232f2SAndroid Build Coastguard Worker         public void Clear()
84*890232f2SAndroid Build Coastguard Worker         {
85*890232f2SAndroid Build Coastguard Worker             _space = _bb.Length;
86*890232f2SAndroid Build Coastguard Worker             _bb.Reset();
87*890232f2SAndroid Build Coastguard Worker             _minAlign = 1;
88*890232f2SAndroid Build Coastguard Worker             while (_vtableSize > 0) _vtable[--_vtableSize] = 0;
89*890232f2SAndroid Build Coastguard Worker             _vtableSize = -1;
90*890232f2SAndroid Build Coastguard Worker             _objectStart = 0;
91*890232f2SAndroid Build Coastguard Worker             _numVtables = 0;
92*890232f2SAndroid Build Coastguard Worker             _vectorNumElems = 0;
93*890232f2SAndroid Build Coastguard Worker             if (_sharedStringMap != null)
94*890232f2SAndroid Build Coastguard Worker             {
95*890232f2SAndroid Build Coastguard Worker                 _sharedStringMap.Clear();
96*890232f2SAndroid Build Coastguard Worker             }
97*890232f2SAndroid Build Coastguard Worker         }
98*890232f2SAndroid Build Coastguard Worker 
99*890232f2SAndroid Build Coastguard Worker         /// <summary>
100*890232f2SAndroid Build Coastguard Worker         /// Gets and sets a Boolean to disable the optimization when serializing
101*890232f2SAndroid Build Coastguard Worker         /// default values to a Table.
102*890232f2SAndroid Build Coastguard Worker         ///
103*890232f2SAndroid Build Coastguard Worker         /// In order to save space, fields that are set to their default value
104*890232f2SAndroid Build Coastguard Worker         /// don't get serialized into the buffer.
105*890232f2SAndroid Build Coastguard Worker         /// </summary>
106*890232f2SAndroid Build Coastguard Worker         public bool ForceDefaults { get; set; }
107*890232f2SAndroid Build Coastguard Worker 
108*890232f2SAndroid Build Coastguard Worker         /// @cond FLATBUFFERS_INTERNAL
109*890232f2SAndroid Build Coastguard Worker 
110*890232f2SAndroid Build Coastguard Worker         public int Offset { get { return _bb.Length - _space; } }
111*890232f2SAndroid Build Coastguard Worker 
Pad(int size)112*890232f2SAndroid Build Coastguard Worker         public void Pad(int size)
113*890232f2SAndroid Build Coastguard Worker         {
114*890232f2SAndroid Build Coastguard Worker              _bb.PutByte(_space -= size, 0, size);
115*890232f2SAndroid Build Coastguard Worker         }
116*890232f2SAndroid Build Coastguard Worker 
117*890232f2SAndroid Build Coastguard Worker         // Doubles the size of the ByteBuffer, and copies the old data towards
118*890232f2SAndroid Build Coastguard Worker         // the end of the new buffer (since we build the buffer backwards).
GrowBuffer()119*890232f2SAndroid Build Coastguard Worker         void GrowBuffer()
120*890232f2SAndroid Build Coastguard Worker         {
121*890232f2SAndroid Build Coastguard Worker             _bb.GrowFront(_bb.Length << 1);
122*890232f2SAndroid Build Coastguard Worker         }
123*890232f2SAndroid Build Coastguard Worker 
124*890232f2SAndroid Build Coastguard Worker         // Prepare to write an element of `size` after `additional_bytes`
125*890232f2SAndroid Build Coastguard Worker         // have been written, e.g. if you write a string, you need to align
126*890232f2SAndroid Build Coastguard Worker         // such the int length field is aligned to SIZEOF_INT, and the string
127*890232f2SAndroid Build Coastguard Worker         // data follows it directly.
128*890232f2SAndroid Build Coastguard Worker         // If all you need to do is align, `additional_bytes` will be 0.
Prep(int size, int additionalBytes)129*890232f2SAndroid Build Coastguard Worker         public void Prep(int size, int additionalBytes)
130*890232f2SAndroid Build Coastguard Worker         {
131*890232f2SAndroid Build Coastguard Worker             // Track the biggest thing we've ever aligned to.
132*890232f2SAndroid Build Coastguard Worker             if (size > _minAlign)
133*890232f2SAndroid Build Coastguard Worker                 _minAlign = size;
134*890232f2SAndroid Build Coastguard Worker             // Find the amount of alignment needed such that `size` is properly
135*890232f2SAndroid Build Coastguard Worker             // aligned after `additional_bytes`
136*890232f2SAndroid Build Coastguard Worker             var alignSize =
137*890232f2SAndroid Build Coastguard Worker                 ((~((int)_bb.Length - _space + additionalBytes)) + 1) &
138*890232f2SAndroid Build Coastguard Worker                 (size - 1);
139*890232f2SAndroid Build Coastguard Worker             // Reallocate the buffer if needed.
140*890232f2SAndroid Build Coastguard Worker             while (_space < alignSize + size + additionalBytes)
141*890232f2SAndroid Build Coastguard Worker             {
142*890232f2SAndroid Build Coastguard Worker                 var oldBufSize = (int)_bb.Length;
143*890232f2SAndroid Build Coastguard Worker                 GrowBuffer();
144*890232f2SAndroid Build Coastguard Worker                 _space += (int)_bb.Length - oldBufSize;
145*890232f2SAndroid Build Coastguard Worker 
146*890232f2SAndroid Build Coastguard Worker             }
147*890232f2SAndroid Build Coastguard Worker             if (alignSize > 0)
148*890232f2SAndroid Build Coastguard Worker                 Pad(alignSize);
149*890232f2SAndroid Build Coastguard Worker         }
150*890232f2SAndroid Build Coastguard Worker 
PutBool(bool x)151*890232f2SAndroid Build Coastguard Worker         public void PutBool(bool x)
152*890232f2SAndroid Build Coastguard Worker         {
153*890232f2SAndroid Build Coastguard Worker           _bb.PutByte(_space -= sizeof(byte), (byte)(x ? 1 : 0));
154*890232f2SAndroid Build Coastguard Worker         }
155*890232f2SAndroid Build Coastguard Worker 
PutSbyte(sbyte x)156*890232f2SAndroid Build Coastguard Worker         public void PutSbyte(sbyte x)
157*890232f2SAndroid Build Coastguard Worker         {
158*890232f2SAndroid Build Coastguard Worker           _bb.PutSbyte(_space -= sizeof(sbyte), x);
159*890232f2SAndroid Build Coastguard Worker         }
160*890232f2SAndroid Build Coastguard Worker 
PutByte(byte x)161*890232f2SAndroid Build Coastguard Worker         public void PutByte(byte x)
162*890232f2SAndroid Build Coastguard Worker         {
163*890232f2SAndroid Build Coastguard Worker             _bb.PutByte(_space -= sizeof(byte), x);
164*890232f2SAndroid Build Coastguard Worker         }
165*890232f2SAndroid Build Coastguard Worker 
PutShort(short x)166*890232f2SAndroid Build Coastguard Worker         public void PutShort(short x)
167*890232f2SAndroid Build Coastguard Worker         {
168*890232f2SAndroid Build Coastguard Worker             _bb.PutShort(_space -= sizeof(short), x);
169*890232f2SAndroid Build Coastguard Worker         }
170*890232f2SAndroid Build Coastguard Worker 
PutUshort(ushort x)171*890232f2SAndroid Build Coastguard Worker         public void PutUshort(ushort x)
172*890232f2SAndroid Build Coastguard Worker         {
173*890232f2SAndroid Build Coastguard Worker           _bb.PutUshort(_space -= sizeof(ushort), x);
174*890232f2SAndroid Build Coastguard Worker         }
175*890232f2SAndroid Build Coastguard Worker 
PutInt(int x)176*890232f2SAndroid Build Coastguard Worker         public void PutInt(int x)
177*890232f2SAndroid Build Coastguard Worker         {
178*890232f2SAndroid Build Coastguard Worker             _bb.PutInt(_space -= sizeof(int), x);
179*890232f2SAndroid Build Coastguard Worker         }
180*890232f2SAndroid Build Coastguard Worker 
PutUint(uint x)181*890232f2SAndroid Build Coastguard Worker         public void PutUint(uint x)
182*890232f2SAndroid Build Coastguard Worker         {
183*890232f2SAndroid Build Coastguard Worker           _bb.PutUint(_space -= sizeof(uint), x);
184*890232f2SAndroid Build Coastguard Worker         }
185*890232f2SAndroid Build Coastguard Worker 
PutLong(long x)186*890232f2SAndroid Build Coastguard Worker         public void PutLong(long x)
187*890232f2SAndroid Build Coastguard Worker         {
188*890232f2SAndroid Build Coastguard Worker             _bb.PutLong(_space -= sizeof(long), x);
189*890232f2SAndroid Build Coastguard Worker         }
190*890232f2SAndroid Build Coastguard Worker 
PutUlong(ulong x)191*890232f2SAndroid Build Coastguard Worker         public void PutUlong(ulong x)
192*890232f2SAndroid Build Coastguard Worker         {
193*890232f2SAndroid Build Coastguard Worker           _bb.PutUlong(_space -= sizeof(ulong), x);
194*890232f2SAndroid Build Coastguard Worker         }
195*890232f2SAndroid Build Coastguard Worker 
PutFloat(float x)196*890232f2SAndroid Build Coastguard Worker         public void PutFloat(float x)
197*890232f2SAndroid Build Coastguard Worker         {
198*890232f2SAndroid Build Coastguard Worker             _bb.PutFloat(_space -= sizeof(float), x);
199*890232f2SAndroid Build Coastguard Worker         }
200*890232f2SAndroid Build Coastguard Worker 
201*890232f2SAndroid Build Coastguard Worker         /// <summary>
202*890232f2SAndroid Build Coastguard Worker         /// Puts an array of type T into this builder at the
203*890232f2SAndroid Build Coastguard Worker         /// current offset
204*890232f2SAndroid Build Coastguard Worker         /// </summary>
205*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data </typeparam>
206*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The array to copy data from</param>
207*890232f2SAndroid Build Coastguard Worker         public void Put<T>(T[] x)
208*890232f2SAndroid Build Coastguard Worker             where T : struct
209*890232f2SAndroid Build Coastguard Worker         {
210*890232f2SAndroid Build Coastguard Worker             _space = _bb.Put(_space, x);
211*890232f2SAndroid Build Coastguard Worker         }
212*890232f2SAndroid Build Coastguard Worker 
213*890232f2SAndroid Build Coastguard Worker         /// <summary>
214*890232f2SAndroid Build Coastguard Worker         /// Puts an array of type T into this builder at the
215*890232f2SAndroid Build Coastguard Worker         /// current offset
216*890232f2SAndroid Build Coastguard Worker         /// </summary>
217*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data </typeparam>
218*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The array segment to copy data from</param>
219*890232f2SAndroid Build Coastguard Worker         public void Put<T>(ArraySegment<T> x)
220*890232f2SAndroid Build Coastguard Worker             where T : struct
221*890232f2SAndroid Build Coastguard Worker         {
222*890232f2SAndroid Build Coastguard Worker             _space = _bb.Put(_space, x);
223*890232f2SAndroid Build Coastguard Worker         }
224*890232f2SAndroid Build Coastguard Worker 
225*890232f2SAndroid Build Coastguard Worker         /// <summary>
226*890232f2SAndroid Build Coastguard Worker         /// Puts data of type T into this builder at the
227*890232f2SAndroid Build Coastguard Worker         /// current offset
228*890232f2SAndroid Build Coastguard Worker         /// </summary>
229*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data </typeparam>
230*890232f2SAndroid Build Coastguard Worker         /// <param name="ptr">The pointer to copy data from</param>
231*890232f2SAndroid Build Coastguard Worker         /// <param name="sizeInBytes">The length of the data in bytes</param>
232*890232f2SAndroid Build Coastguard Worker         public void Put<T>(IntPtr ptr, int sizeInBytes)
233*890232f2SAndroid Build Coastguard Worker             where T : struct
234*890232f2SAndroid Build Coastguard Worker         {
235*890232f2SAndroid Build Coastguard Worker             _space = _bb.Put<T>(_space, ptr, sizeInBytes);
236*890232f2SAndroid Build Coastguard Worker         }
237*890232f2SAndroid Build Coastguard Worker 
238*890232f2SAndroid Build Coastguard Worker #if ENABLE_SPAN_T && (UNSAFE_BYTEBUFFER || NETSTANDARD2_1)
239*890232f2SAndroid Build Coastguard Worker         /// <summary>
240*890232f2SAndroid Build Coastguard Worker         /// Puts a span of type T into this builder at the
241*890232f2SAndroid Build Coastguard Worker         /// current offset
242*890232f2SAndroid Build Coastguard Worker         /// </summary>
243*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data </typeparam>
244*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The span to copy data from</param>
245*890232f2SAndroid Build Coastguard Worker         public void Put<T>(Span<T> x)
246*890232f2SAndroid Build Coastguard Worker             where T : struct
247*890232f2SAndroid Build Coastguard Worker         {
248*890232f2SAndroid Build Coastguard Worker             _space = _bb.Put(_space, x);
249*890232f2SAndroid Build Coastguard Worker         }
250*890232f2SAndroid Build Coastguard Worker #endif
251*890232f2SAndroid Build Coastguard Worker 
PutDouble(double x)252*890232f2SAndroid Build Coastguard Worker         public void PutDouble(double x)
253*890232f2SAndroid Build Coastguard Worker         {
254*890232f2SAndroid Build Coastguard Worker             _bb.PutDouble(_space -= sizeof(double), x);
255*890232f2SAndroid Build Coastguard Worker         }
256*890232f2SAndroid Build Coastguard Worker         /// @endcond
257*890232f2SAndroid Build Coastguard Worker 
258*890232f2SAndroid Build Coastguard Worker         /// <summary>
259*890232f2SAndroid Build Coastguard Worker         /// Add a `bool` to the buffer (aligns the data and grows if necessary).
260*890232f2SAndroid Build Coastguard Worker         /// </summary>
261*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `bool` to add to the buffer.</param>
AddBool(bool x)262*890232f2SAndroid Build Coastguard Worker         public void AddBool(bool x) { Prep(sizeof(byte), 0); PutBool(x); }
263*890232f2SAndroid Build Coastguard Worker 
264*890232f2SAndroid Build Coastguard Worker         /// <summary>
265*890232f2SAndroid Build Coastguard Worker         /// Add a `sbyte` to the buffer (aligns the data and grows if necessary).
266*890232f2SAndroid Build Coastguard Worker         /// </summary>
267*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `sbyte` to add to the buffer.</param>
AddSbyte(sbyte x)268*890232f2SAndroid Build Coastguard Worker         public void AddSbyte(sbyte x) { Prep(sizeof(sbyte), 0); PutSbyte(x); }
269*890232f2SAndroid Build Coastguard Worker 
270*890232f2SAndroid Build Coastguard Worker         /// <summary>
271*890232f2SAndroid Build Coastguard Worker         /// Add a `byte` to the buffer (aligns the data and grows if necessary).
272*890232f2SAndroid Build Coastguard Worker         /// </summary>
273*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `byte` to add to the buffer.</param>
AddByte(byte x)274*890232f2SAndroid Build Coastguard Worker         public void AddByte(byte x) { Prep(sizeof(byte), 0); PutByte(x); }
275*890232f2SAndroid Build Coastguard Worker 
276*890232f2SAndroid Build Coastguard Worker         /// <summary>
277*890232f2SAndroid Build Coastguard Worker         /// Add a `short` to the buffer (aligns the data and grows if necessary).
278*890232f2SAndroid Build Coastguard Worker         /// </summary>
279*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `short` to add to the buffer.</param>
AddShort(short x)280*890232f2SAndroid Build Coastguard Worker         public void AddShort(short x) { Prep(sizeof(short), 0); PutShort(x); }
281*890232f2SAndroid Build Coastguard Worker 
282*890232f2SAndroid Build Coastguard Worker         /// <summary>
283*890232f2SAndroid Build Coastguard Worker         /// Add an `ushort` to the buffer (aligns the data and grows if necessary).
284*890232f2SAndroid Build Coastguard Worker         /// </summary>
285*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `ushort` to add to the buffer.</param>
AddUshort(ushort x)286*890232f2SAndroid Build Coastguard Worker         public void AddUshort(ushort x) { Prep(sizeof(ushort), 0); PutUshort(x); }
287*890232f2SAndroid Build Coastguard Worker 
288*890232f2SAndroid Build Coastguard Worker         /// <summary>
289*890232f2SAndroid Build Coastguard Worker         /// Add an `int` to the buffer (aligns the data and grows if necessary).
290*890232f2SAndroid Build Coastguard Worker         /// </summary>
291*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `int` to add to the buffer.</param>
AddInt(int x)292*890232f2SAndroid Build Coastguard Worker         public void AddInt(int x) { Prep(sizeof(int), 0); PutInt(x); }
293*890232f2SAndroid Build Coastguard Worker 
294*890232f2SAndroid Build Coastguard Worker         /// <summary>
295*890232f2SAndroid Build Coastguard Worker         /// Add an `uint` to the buffer (aligns the data and grows if necessary).
296*890232f2SAndroid Build Coastguard Worker         /// </summary>
297*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `uint` to add to the buffer.</param>
AddUint(uint x)298*890232f2SAndroid Build Coastguard Worker         public void AddUint(uint x) { Prep(sizeof(uint), 0); PutUint(x); }
299*890232f2SAndroid Build Coastguard Worker 
300*890232f2SAndroid Build Coastguard Worker         /// <summary>
301*890232f2SAndroid Build Coastguard Worker         /// Add a `long` to the buffer (aligns the data and grows if necessary).
302*890232f2SAndroid Build Coastguard Worker         /// </summary>
303*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `long` to add to the buffer.</param>
AddLong(long x)304*890232f2SAndroid Build Coastguard Worker         public void AddLong(long x) { Prep(sizeof(long), 0); PutLong(x); }
305*890232f2SAndroid Build Coastguard Worker 
306*890232f2SAndroid Build Coastguard Worker         /// <summary>
307*890232f2SAndroid Build Coastguard Worker         /// Add an `ulong` to the buffer (aligns the data and grows if necessary).
308*890232f2SAndroid Build Coastguard Worker         /// </summary>
309*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `ulong` to add to the buffer.</param>
AddUlong(ulong x)310*890232f2SAndroid Build Coastguard Worker         public void AddUlong(ulong x) { Prep(sizeof(ulong), 0); PutUlong(x); }
311*890232f2SAndroid Build Coastguard Worker 
312*890232f2SAndroid Build Coastguard Worker         /// <summary>
313*890232f2SAndroid Build Coastguard Worker         /// Add a `float` to the buffer (aligns the data and grows if necessary).
314*890232f2SAndroid Build Coastguard Worker         /// </summary>
315*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `float` to add to the buffer.</param>
AddFloat(float x)316*890232f2SAndroid Build Coastguard Worker         public void AddFloat(float x) { Prep(sizeof(float), 0); PutFloat(x); }
317*890232f2SAndroid Build Coastguard Worker 
318*890232f2SAndroid Build Coastguard Worker         /// <summary>
319*890232f2SAndroid Build Coastguard Worker         /// Add an array of type T to the buffer (aligns the data and grows if necessary).
320*890232f2SAndroid Build Coastguard Worker         /// </summary>
321*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data</typeparam>
322*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The array to copy data from</param>
323*890232f2SAndroid Build Coastguard Worker         public void Add<T>(T[] x)
324*890232f2SAndroid Build Coastguard Worker             where T : struct
325*890232f2SAndroid Build Coastguard Worker         {
AddFlatBuffers.FlatBufferBuilder.__anon5326*890232f2SAndroid Build Coastguard Worker             Add(new ArraySegment<T>(x));
327*890232f2SAndroid Build Coastguard Worker         }
328*890232f2SAndroid Build Coastguard Worker 
329*890232f2SAndroid Build Coastguard Worker         /// <summary>
330*890232f2SAndroid Build Coastguard Worker         /// Add an array of type T to the buffer (aligns the data and grows if necessary).
331*890232f2SAndroid Build Coastguard Worker         /// </summary>
332*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data</typeparam>
333*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The array segment to copy data from</param>
334*890232f2SAndroid Build Coastguard Worker         public void Add<T>(ArraySegment<T> x)
335*890232f2SAndroid Build Coastguard Worker             where T : struct
336*890232f2SAndroid Build Coastguard Worker         {
337*890232f2SAndroid Build Coastguard Worker             if (x == null)
338*890232f2SAndroid Build Coastguard Worker             {
339*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentNullException("Cannot add a null array");
340*890232f2SAndroid Build Coastguard Worker             }
341*890232f2SAndroid Build Coastguard Worker 
342*890232f2SAndroid Build Coastguard Worker             if( x.Count == 0)
343*890232f2SAndroid Build Coastguard Worker             {
344*890232f2SAndroid Build Coastguard Worker                 // don't do anything if the array is empty
345*890232f2SAndroid Build Coastguard Worker                 return;
346*890232f2SAndroid Build Coastguard Worker             }
347*890232f2SAndroid Build Coastguard Worker 
348*890232f2SAndroid Build Coastguard Worker             if(!ByteBuffer.IsSupportedType<T>())
349*890232f2SAndroid Build Coastguard Worker             {
350*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentException("Cannot add this Type array to the builder");
351*890232f2SAndroid Build Coastguard Worker             }
352*890232f2SAndroid Build Coastguard Worker 
353*890232f2SAndroid Build Coastguard Worker             int size = ByteBuffer.SizeOf<T>();
354*890232f2SAndroid Build Coastguard Worker             // Need to prep on size (for data alignment) and then we pass the
355*890232f2SAndroid Build Coastguard Worker             // rest of the length (minus 1) as additional bytes
PrepFlatBuffers.FlatBufferBuilder.__anon6356*890232f2SAndroid Build Coastguard Worker             Prep(size, size * (x.Count - 1));
PutFlatBuffers.FlatBufferBuilder.__anon6357*890232f2SAndroid Build Coastguard Worker             Put(x);
358*890232f2SAndroid Build Coastguard Worker         }
359*890232f2SAndroid Build Coastguard Worker 
360*890232f2SAndroid Build Coastguard Worker         /// <summary>
361*890232f2SAndroid Build Coastguard Worker         /// Adds the data of type T pointed to by the given pointer to the buffer (aligns the data and grows if necessary).
362*890232f2SAndroid Build Coastguard Worker         /// </summary>
363*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data</typeparam>
364*890232f2SAndroid Build Coastguard Worker         /// <param name="ptr">The pointer to copy data from</param>
365*890232f2SAndroid Build Coastguard Worker         /// <param name="sizeInBytes">The data size in bytes</param>
366*890232f2SAndroid Build Coastguard Worker         public void Add<T>(IntPtr ptr, int sizeInBytes)
367*890232f2SAndroid Build Coastguard Worker             where T : struct
368*890232f2SAndroid Build Coastguard Worker         {
369*890232f2SAndroid Build Coastguard Worker             if(sizeInBytes == 0)
370*890232f2SAndroid Build Coastguard Worker             {
371*890232f2SAndroid Build Coastguard Worker                 // don't do anything if the array is empty
372*890232f2SAndroid Build Coastguard Worker                 return;
373*890232f2SAndroid Build Coastguard Worker             }
374*890232f2SAndroid Build Coastguard Worker 
375*890232f2SAndroid Build Coastguard Worker             if (ptr == IntPtr.Zero)
376*890232f2SAndroid Build Coastguard Worker             {
377*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentNullException("Cannot add a null pointer");
378*890232f2SAndroid Build Coastguard Worker             }
379*890232f2SAndroid Build Coastguard Worker 
380*890232f2SAndroid Build Coastguard Worker             if(sizeInBytes < 0)
381*890232f2SAndroid Build Coastguard Worker             {
382*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentOutOfRangeException("sizeInBytes", "sizeInBytes cannot be negative");
383*890232f2SAndroid Build Coastguard Worker             }
384*890232f2SAndroid Build Coastguard Worker 
385*890232f2SAndroid Build Coastguard Worker             if(!ByteBuffer.IsSupportedType<T>())
386*890232f2SAndroid Build Coastguard Worker             {
387*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentException("Cannot add this Type array to the builder");
388*890232f2SAndroid Build Coastguard Worker             }
389*890232f2SAndroid Build Coastguard Worker 
390*890232f2SAndroid Build Coastguard Worker             int size = ByteBuffer.SizeOf<T>();
391*890232f2SAndroid Build Coastguard Worker             if((sizeInBytes % size) != 0)
392*890232f2SAndroid Build Coastguard Worker             {
393*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentException("The given size in bytes " + sizeInBytes + " doesn't match the element size of T ( " + size + ")", "sizeInBytes");
394*890232f2SAndroid Build Coastguard Worker             }
395*890232f2SAndroid Build Coastguard Worker 
396*890232f2SAndroid Build Coastguard Worker             // Need to prep on size (for data alignment) and then we pass the
397*890232f2SAndroid Build Coastguard Worker             // rest of the length (minus 1) as additional bytes
PrepFlatBuffers.FlatBufferBuilder.__anon7398*890232f2SAndroid Build Coastguard Worker             Prep(size, sizeInBytes - size);
PutFlatBuffers.FlatBufferBuilder.__anon7399*890232f2SAndroid Build Coastguard Worker             Put<T>(ptr, sizeInBytes);
400*890232f2SAndroid Build Coastguard Worker         }
401*890232f2SAndroid Build Coastguard Worker 
402*890232f2SAndroid Build Coastguard Worker #if ENABLE_SPAN_T && (UNSAFE_BYTEBUFFER || NETSTANDARD2_1)
403*890232f2SAndroid Build Coastguard Worker         /// <summary>
404*890232f2SAndroid Build Coastguard Worker         /// Add a span of type T to the buffer (aligns the data and grows if necessary).
405*890232f2SAndroid Build Coastguard Worker         /// </summary>
406*890232f2SAndroid Build Coastguard Worker         /// <typeparam name="T">The type of the input data</typeparam>
407*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The span to copy data from</param>
408*890232f2SAndroid Build Coastguard Worker         public void Add<T>(Span<T> x)
409*890232f2SAndroid Build Coastguard Worker             where T : struct
410*890232f2SAndroid Build Coastguard Worker         {
411*890232f2SAndroid Build Coastguard Worker             if (!ByteBuffer.IsSupportedType<T>())
412*890232f2SAndroid Build Coastguard Worker             {
413*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentException("Cannot add this Type array to the builder");
414*890232f2SAndroid Build Coastguard Worker             }
415*890232f2SAndroid Build Coastguard Worker 
416*890232f2SAndroid Build Coastguard Worker             int size = ByteBuffer.SizeOf<T>();
417*890232f2SAndroid Build Coastguard Worker             // Need to prep on size (for data alignment) and then we pass the
418*890232f2SAndroid Build Coastguard Worker             // rest of the length (minus 1) as additional bytes
PrepFlatBuffers.FlatBufferBuilder.__anon8419*890232f2SAndroid Build Coastguard Worker             Prep(size, size * (x.Length - 1));
PutFlatBuffers.FlatBufferBuilder.__anon8420*890232f2SAndroid Build Coastguard Worker             Put(x);
421*890232f2SAndroid Build Coastguard Worker         }
422*890232f2SAndroid Build Coastguard Worker #endif
423*890232f2SAndroid Build Coastguard Worker 
424*890232f2SAndroid Build Coastguard Worker         /// <summary>
425*890232f2SAndroid Build Coastguard Worker         /// Add a `double` to the buffer (aligns the data and grows if necessary).
426*890232f2SAndroid Build Coastguard Worker         /// </summary>
427*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The `double` to add to the buffer.</param>
AddDouble(double x)428*890232f2SAndroid Build Coastguard Worker         public void AddDouble(double x) { Prep(sizeof(double), 0);
429*890232f2SAndroid Build Coastguard Worker                                           PutDouble(x); }
430*890232f2SAndroid Build Coastguard Worker 
431*890232f2SAndroid Build Coastguard Worker         /// <summary>
432*890232f2SAndroid Build Coastguard Worker         /// Adds an offset, relative to where it will be written.
433*890232f2SAndroid Build Coastguard Worker         /// </summary>
434*890232f2SAndroid Build Coastguard Worker         /// <param name="off">The offset to add to the buffer.</param>
AddOffset(int off)435*890232f2SAndroid Build Coastguard Worker         public void AddOffset(int off)
436*890232f2SAndroid Build Coastguard Worker         {
437*890232f2SAndroid Build Coastguard Worker             Prep(sizeof(int), 0);  // Ensure alignment is already done.
438*890232f2SAndroid Build Coastguard Worker             if (off > Offset)
439*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentException();
440*890232f2SAndroid Build Coastguard Worker 
441*890232f2SAndroid Build Coastguard Worker             off = Offset - off + sizeof(int);
442*890232f2SAndroid Build Coastguard Worker             PutInt(off);
443*890232f2SAndroid Build Coastguard Worker         }
444*890232f2SAndroid Build Coastguard Worker 
445*890232f2SAndroid Build Coastguard Worker         /// @cond FLATBUFFERS_INTERNAL
StartVector(int elemSize, int count, int alignment)446*890232f2SAndroid Build Coastguard Worker         public void StartVector(int elemSize, int count, int alignment)
447*890232f2SAndroid Build Coastguard Worker         {
448*890232f2SAndroid Build Coastguard Worker             NotNested();
449*890232f2SAndroid Build Coastguard Worker             _vectorNumElems = count;
450*890232f2SAndroid Build Coastguard Worker             Prep(sizeof(int), elemSize * count);
451*890232f2SAndroid Build Coastguard Worker             Prep(alignment, elemSize * count); // Just in case alignment > int.
452*890232f2SAndroid Build Coastguard Worker         }
453*890232f2SAndroid Build Coastguard Worker         /// @endcond
454*890232f2SAndroid Build Coastguard Worker 
455*890232f2SAndroid Build Coastguard Worker         /// <summary>
456*890232f2SAndroid Build Coastguard Worker         /// Writes data necessary to finish a vector construction.
457*890232f2SAndroid Build Coastguard Worker         /// </summary>
EndVector()458*890232f2SAndroid Build Coastguard Worker         public VectorOffset EndVector()
459*890232f2SAndroid Build Coastguard Worker         {
460*890232f2SAndroid Build Coastguard Worker             PutInt(_vectorNumElems);
461*890232f2SAndroid Build Coastguard Worker             return new VectorOffset(Offset);
462*890232f2SAndroid Build Coastguard Worker         }
463*890232f2SAndroid Build Coastguard Worker 
464*890232f2SAndroid Build Coastguard Worker         /// <summary>
465*890232f2SAndroid Build Coastguard Worker         /// Creates a vector of tables.
466*890232f2SAndroid Build Coastguard Worker         /// </summary>
467*890232f2SAndroid Build Coastguard Worker         /// <param name="offsets">Offsets of the tables.</param>
468*890232f2SAndroid Build Coastguard Worker         public VectorOffset CreateVectorOfTables<T>(Offset<T>[] offsets) where T : struct
469*890232f2SAndroid Build Coastguard Worker         {
NotNestedFlatBuffers.FlatBufferBuilder.__anon9470*890232f2SAndroid Build Coastguard Worker             NotNested();
sizeofFlatBuffers.FlatBufferBuilder.__anon9471*890232f2SAndroid Build Coastguard Worker             StartVector(sizeof(int), offsets.Length, sizeof(int));
AddOffsetFlatBuffers.FlatBufferBuilder.__anon9472*890232f2SAndroid Build Coastguard Worker             for (int i = offsets.Length - 1; i >= 0; i--) AddOffset(offsets[i].Value);
473*890232f2SAndroid Build Coastguard Worker             return EndVector();
474*890232f2SAndroid Build Coastguard Worker         }
475*890232f2SAndroid Build Coastguard Worker 
476*890232f2SAndroid Build Coastguard Worker         /// @cond FLATBUFFERS_INTENRAL
Nested(int obj)477*890232f2SAndroid Build Coastguard Worker         public void Nested(int obj)
478*890232f2SAndroid Build Coastguard Worker         {
479*890232f2SAndroid Build Coastguard Worker             // Structs are always stored inline, so need to be created right
480*890232f2SAndroid Build Coastguard Worker             // where they are used. You'll get this assert if you created it
481*890232f2SAndroid Build Coastguard Worker             // elsewhere.
482*890232f2SAndroid Build Coastguard Worker             if (obj != Offset)
483*890232f2SAndroid Build Coastguard Worker                 throw new Exception(
484*890232f2SAndroid Build Coastguard Worker                     "FlatBuffers: struct must be serialized inline.");
485*890232f2SAndroid Build Coastguard Worker         }
486*890232f2SAndroid Build Coastguard Worker 
NotNested()487*890232f2SAndroid Build Coastguard Worker         public void NotNested()
488*890232f2SAndroid Build Coastguard Worker         {
489*890232f2SAndroid Build Coastguard Worker             // You should not be creating any other objects or strings/vectors
490*890232f2SAndroid Build Coastguard Worker             // while an object is being constructed
491*890232f2SAndroid Build Coastguard Worker             if (_vtableSize >= 0)
492*890232f2SAndroid Build Coastguard Worker                 throw new Exception(
493*890232f2SAndroid Build Coastguard Worker                     "FlatBuffers: object serialization must not be nested.");
494*890232f2SAndroid Build Coastguard Worker         }
495*890232f2SAndroid Build Coastguard Worker 
StartTable(int numfields)496*890232f2SAndroid Build Coastguard Worker         public void StartTable(int numfields)
497*890232f2SAndroid Build Coastguard Worker         {
498*890232f2SAndroid Build Coastguard Worker             if (numfields < 0)
499*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentOutOfRangeException("Flatbuffers: invalid numfields");
500*890232f2SAndroid Build Coastguard Worker 
501*890232f2SAndroid Build Coastguard Worker             NotNested();
502*890232f2SAndroid Build Coastguard Worker 
503*890232f2SAndroid Build Coastguard Worker             if (_vtable.Length < numfields)
504*890232f2SAndroid Build Coastguard Worker                 _vtable = new int[numfields];
505*890232f2SAndroid Build Coastguard Worker 
506*890232f2SAndroid Build Coastguard Worker             _vtableSize = numfields;
507*890232f2SAndroid Build Coastguard Worker             _objectStart = Offset;
508*890232f2SAndroid Build Coastguard Worker         }
509*890232f2SAndroid Build Coastguard Worker 
510*890232f2SAndroid Build Coastguard Worker 
511*890232f2SAndroid Build Coastguard Worker         // Set the current vtable at `voffset` to the current location in the
512*890232f2SAndroid Build Coastguard Worker         // buffer.
Slot(int voffset)513*890232f2SAndroid Build Coastguard Worker         public void Slot(int voffset)
514*890232f2SAndroid Build Coastguard Worker         {
515*890232f2SAndroid Build Coastguard Worker             if (voffset >= _vtableSize)
516*890232f2SAndroid Build Coastguard Worker                 throw new IndexOutOfRangeException("Flatbuffers: invalid voffset");
517*890232f2SAndroid Build Coastguard Worker 
518*890232f2SAndroid Build Coastguard Worker             _vtable[voffset] = Offset;
519*890232f2SAndroid Build Coastguard Worker         }
520*890232f2SAndroid Build Coastguard Worker 
521*890232f2SAndroid Build Coastguard Worker         /// <summary>
522*890232f2SAndroid Build Coastguard Worker         /// Adds a Boolean to the Table at index `o` in its vtable using the value `x` and default `d`
523*890232f2SAndroid Build Coastguard Worker         /// </summary>
524*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
525*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
526*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
527*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddBool(int o, bool x, bool d)528*890232f2SAndroid Build Coastguard Worker         public void AddBool(int o, bool x, bool d) { if (ForceDefaults || x != d) { AddBool(x); Slot(o); } }
529*890232f2SAndroid Build Coastguard Worker 
530*890232f2SAndroid Build Coastguard Worker         /// <summary>
531*890232f2SAndroid Build Coastguard Worker         /// Adds a Boolean to the Table at index `o` in its vtable using the nullable value `x`
532*890232f2SAndroid Build Coastguard Worker         /// </summary>
533*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
534*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable boolean value to put into the buffer. If it doesn't have a value
535*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddBool(int o, bool? x)536*890232f2SAndroid Build Coastguard Worker         public void AddBool(int o, bool? x) { if (x.HasValue) { AddBool(x.Value); Slot(o); } }
537*890232f2SAndroid Build Coastguard Worker 
538*890232f2SAndroid Build Coastguard Worker 
539*890232f2SAndroid Build Coastguard Worker         /// <summary>
540*890232f2SAndroid Build Coastguard Worker         /// Adds a SByte to the Table at index `o` in its vtable using the value `x` and default `d`
541*890232f2SAndroid Build Coastguard Worker         /// </summary>
542*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
543*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
544*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
545*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddSbyte(int o, sbyte x, sbyte d)546*890232f2SAndroid Build Coastguard Worker         public void AddSbyte(int o, sbyte x, sbyte d) { if (ForceDefaults || x != d) { AddSbyte(x); Slot(o); } }
547*890232f2SAndroid Build Coastguard Worker 
548*890232f2SAndroid Build Coastguard Worker         /// <summary>
549*890232f2SAndroid Build Coastguard Worker         /// Adds a SByte to the Table at index `o` in its vtable using the nullable value `x`
550*890232f2SAndroid Build Coastguard Worker         /// </summary>
551*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
552*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable sbyte value to put into the buffer. If it doesn't have a value
553*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddSbyte(int o, sbyte? x)554*890232f2SAndroid Build Coastguard Worker         public void AddSbyte(int o, sbyte? x) { if (x.HasValue) { AddSbyte(x.Value); Slot(o); } }
555*890232f2SAndroid Build Coastguard Worker 
556*890232f2SAndroid Build Coastguard Worker         /// <summary>
557*890232f2SAndroid Build Coastguard Worker         /// Adds a Byte to the Table at index `o` in its vtable using the value `x` and default `d`
558*890232f2SAndroid Build Coastguard Worker         /// </summary>
559*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
560*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
561*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
562*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddByte(int o, byte x, byte d)563*890232f2SAndroid Build Coastguard Worker         public void AddByte(int o, byte x, byte d) { if (ForceDefaults || x != d) { AddByte(x); Slot(o); } }
564*890232f2SAndroid Build Coastguard Worker 
565*890232f2SAndroid Build Coastguard Worker         /// <summary>
566*890232f2SAndroid Build Coastguard Worker         /// Adds a Byte to the Table at index `o` in its vtable using the nullable value `x`
567*890232f2SAndroid Build Coastguard Worker         /// </summary>
568*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
569*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable byte value to put into the buffer. If it doesn't have a value
570*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddByte(int o, byte? x)571*890232f2SAndroid Build Coastguard Worker         public void AddByte(int o, byte? x) { if (x.HasValue) { AddByte(x.Value); Slot(o); } }
572*890232f2SAndroid Build Coastguard Worker 
573*890232f2SAndroid Build Coastguard Worker         /// <summary>
574*890232f2SAndroid Build Coastguard Worker         /// Adds a Int16 to the Table at index `o` in its vtable using the value `x` and default `d`
575*890232f2SAndroid Build Coastguard Worker         /// </summary>
576*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
577*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
578*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
579*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddShort(int o, short x, int d)580*890232f2SAndroid Build Coastguard Worker         public void AddShort(int o, short x, int d) { if (ForceDefaults || x != d) { AddShort(x); Slot(o); } }
581*890232f2SAndroid Build Coastguard Worker 
582*890232f2SAndroid Build Coastguard Worker         /// <summary>
583*890232f2SAndroid Build Coastguard Worker         /// Adds a Int16 to the Table at index `o` in its vtable using the nullable value `x`
584*890232f2SAndroid Build Coastguard Worker         /// </summary>
585*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
586*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable int16 value to put into the buffer. If it doesn't have a value
587*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddShort(int o, short? x)588*890232f2SAndroid Build Coastguard Worker         public void AddShort(int o, short? x) { if (x.HasValue) { AddShort(x.Value); Slot(o); } }
589*890232f2SAndroid Build Coastguard Worker 
590*890232f2SAndroid Build Coastguard Worker         /// <summary>
591*890232f2SAndroid Build Coastguard Worker         /// Adds a UInt16 to the Table at index `o` in its vtable using the value `x` and default `d`
592*890232f2SAndroid Build Coastguard Worker         /// </summary>
593*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
594*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
595*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
596*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddUshort(int o, ushort x, ushort d)597*890232f2SAndroid Build Coastguard Worker         public void AddUshort(int o, ushort x, ushort d) { if (ForceDefaults || x != d) { AddUshort(x); Slot(o); } }
598*890232f2SAndroid Build Coastguard Worker 
599*890232f2SAndroid Build Coastguard Worker         /// <summary>
600*890232f2SAndroid Build Coastguard Worker         /// Adds a Uint16 to the Table at index `o` in its vtable using the nullable value `x`
601*890232f2SAndroid Build Coastguard Worker         /// </summary>
602*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
603*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable uint16 value to put into the buffer. If it doesn't have a value
604*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddUshort(int o, ushort? x)605*890232f2SAndroid Build Coastguard Worker         public void AddUshort(int o, ushort? x) { if (x.HasValue) { AddUshort(x.Value); Slot(o); } }
606*890232f2SAndroid Build Coastguard Worker 
607*890232f2SAndroid Build Coastguard Worker         /// <summary>
608*890232f2SAndroid Build Coastguard Worker         /// Adds an Int32 to the Table at index `o` in its vtable using the value `x` and default `d`
609*890232f2SAndroid Build Coastguard Worker         /// </summary>
610*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
611*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
612*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
613*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddInt(int o, int x, int d)614*890232f2SAndroid Build Coastguard Worker         public void AddInt(int o, int x, int d) { if (ForceDefaults || x != d) { AddInt(x); Slot(o); } }
615*890232f2SAndroid Build Coastguard Worker 
616*890232f2SAndroid Build Coastguard Worker         /// <summary>
617*890232f2SAndroid Build Coastguard Worker         /// Adds a Int32 to the Table at index `o` in its vtable using the nullable value `x`
618*890232f2SAndroid Build Coastguard Worker         /// </summary>
619*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
620*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable int32 value to put into the buffer. If it doesn't have a value
621*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddInt(int o, int? x)622*890232f2SAndroid Build Coastguard Worker         public void AddInt(int o, int? x) { if (x.HasValue) { AddInt(x.Value); Slot(o); } }
623*890232f2SAndroid Build Coastguard Worker 
624*890232f2SAndroid Build Coastguard Worker         /// <summary>
625*890232f2SAndroid Build Coastguard Worker         /// Adds a UInt32 to the Table at index `o` in its vtable using the value `x` and default `d`
626*890232f2SAndroid Build Coastguard Worker         /// </summary>
627*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
628*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
629*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
630*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddUint(int o, uint x, uint d)631*890232f2SAndroid Build Coastguard Worker         public void AddUint(int o, uint x, uint d) { if (ForceDefaults || x != d) { AddUint(x); Slot(o); } }
632*890232f2SAndroid Build Coastguard Worker 
633*890232f2SAndroid Build Coastguard Worker         /// <summary>
634*890232f2SAndroid Build Coastguard Worker         /// Adds a UInt32 to the Table at index `o` in its vtable using the nullable value `x`
635*890232f2SAndroid Build Coastguard Worker         /// </summary>
636*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
637*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable uint32 value to put into the buffer. If it doesn't have a value
638*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddUint(int o, uint? x)639*890232f2SAndroid Build Coastguard Worker         public void AddUint(int o, uint? x) { if (x.HasValue) { AddUint(x.Value); Slot(o); } }
640*890232f2SAndroid Build Coastguard Worker 
641*890232f2SAndroid Build Coastguard Worker         /// <summary>
642*890232f2SAndroid Build Coastguard Worker         /// Adds an Int64 to the Table at index `o` in its vtable using the value `x` and default `d`
643*890232f2SAndroid Build Coastguard Worker         /// </summary>
644*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
645*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
646*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
647*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddLong(int o, long x, long d)648*890232f2SAndroid Build Coastguard Worker         public void AddLong(int o, long x, long d) { if (ForceDefaults || x != d) { AddLong(x); Slot(o); } }
649*890232f2SAndroid Build Coastguard Worker 
650*890232f2SAndroid Build Coastguard Worker         /// <summary>
651*890232f2SAndroid Build Coastguard Worker         /// Adds a Int64 to the Table at index `o` in its vtable using the nullable value `x`
652*890232f2SAndroid Build Coastguard Worker         /// </summary>
653*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
654*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable int64 value to put into the buffer. If it doesn't have a value
655*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddLong(int o, long? x)656*890232f2SAndroid Build Coastguard Worker         public void AddLong(int o, long? x) { if (x.HasValue) { AddLong(x.Value); Slot(o); } }
657*890232f2SAndroid Build Coastguard Worker 
658*890232f2SAndroid Build Coastguard Worker         /// <summary>
659*890232f2SAndroid Build Coastguard Worker         /// Adds a UInt64 to the Table at index `o` in its vtable using the value `x` and default `d`
660*890232f2SAndroid Build Coastguard Worker         /// </summary>
661*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
662*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
663*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
664*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddUlong(int o, ulong x, ulong d)665*890232f2SAndroid Build Coastguard Worker         public void AddUlong(int o, ulong x, ulong d) { if (ForceDefaults || x != d) { AddUlong(x); Slot(o); } }
666*890232f2SAndroid Build Coastguard Worker 
667*890232f2SAndroid Build Coastguard Worker         /// <summary>
668*890232f2SAndroid Build Coastguard Worker         /// Adds a UInt64 to the Table at index `o` in its vtable using the nullable value `x`
669*890232f2SAndroid Build Coastguard Worker         /// </summary>
670*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
671*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable int64 value to put into the buffer. If it doesn't have a value
672*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddUlong(int o, ulong? x)673*890232f2SAndroid Build Coastguard Worker         public void AddUlong(int o, ulong? x) { if (x.HasValue) { AddUlong(x.Value); Slot(o); } }
674*890232f2SAndroid Build Coastguard Worker 
675*890232f2SAndroid Build Coastguard Worker         /// <summary>
676*890232f2SAndroid Build Coastguard Worker         /// Adds a Single to the Table at index `o` in its vtable using the value `x` and default `d`
677*890232f2SAndroid Build Coastguard Worker         /// </summary>
678*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
679*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
680*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
681*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddFloat(int o, float x, double d)682*890232f2SAndroid Build Coastguard Worker         public void AddFloat(int o, float x, double d) { if (ForceDefaults || x != d) { AddFloat(x); Slot(o); } }
683*890232f2SAndroid Build Coastguard Worker 
684*890232f2SAndroid Build Coastguard Worker         /// <summary>
685*890232f2SAndroid Build Coastguard Worker         /// Adds a Single to the Table at index `o` in its vtable using the nullable value `x`
686*890232f2SAndroid Build Coastguard Worker         /// </summary>
687*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
688*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable single value to put into the buffer. If it doesn't have a value
689*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddFloat(int o, float? x)690*890232f2SAndroid Build Coastguard Worker         public void AddFloat(int o, float? x) { if (x.HasValue) { AddFloat(x.Value); Slot(o); } }
691*890232f2SAndroid Build Coastguard Worker 
692*890232f2SAndroid Build Coastguard Worker         /// <summary>
693*890232f2SAndroid Build Coastguard Worker         /// Adds a Double to the Table at index `o` in its vtable using the value `x` and default `d`
694*890232f2SAndroid Build Coastguard Worker         /// </summary>
695*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
696*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
697*890232f2SAndroid Build Coastguard Worker         /// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
698*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddDouble(int o, double x, double d)699*890232f2SAndroid Build Coastguard Worker         public void AddDouble(int o, double x, double d) { if (ForceDefaults || x != d) { AddDouble(x); Slot(o); } }
700*890232f2SAndroid Build Coastguard Worker 
701*890232f2SAndroid Build Coastguard Worker         /// <summary>
702*890232f2SAndroid Build Coastguard Worker         /// Adds a Double to the Table at index `o` in its vtable using the nullable value `x`
703*890232f2SAndroid Build Coastguard Worker         /// </summary>
704*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
705*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The nullable double value to put into the buffer. If it doesn't have a value
706*890232f2SAndroid Build Coastguard Worker         /// it will skip writing to the buffer.</param>
AddDouble(int o, double? x)707*890232f2SAndroid Build Coastguard Worker         public void AddDouble(int o, double? x) { if (x.HasValue) { AddDouble(x.Value); Slot(o); } }
708*890232f2SAndroid Build Coastguard Worker 
709*890232f2SAndroid Build Coastguard Worker         /// <summary>
710*890232f2SAndroid Build Coastguard Worker         /// Adds a buffer offset to the Table at index `o` in its vtable using the value `x` and default `d`
711*890232f2SAndroid Build Coastguard Worker         /// </summary>
712*890232f2SAndroid Build Coastguard Worker         /// <param name="o">The index into the vtable</param>
713*890232f2SAndroid Build Coastguard Worker         /// <param name="x">The value to put into the buffer. If the value is equal to the default
714*890232f2SAndroid Build Coastguard Worker         /// the value will be skipped.</param>
715*890232f2SAndroid Build Coastguard Worker         /// <param name="d">The default value to compare the value against</param>
AddOffset(int o, int x, int d)716*890232f2SAndroid Build Coastguard Worker         public void AddOffset(int o, int x, int d) { if (x != d) { AddOffset(x); Slot(o); } }
717*890232f2SAndroid Build Coastguard Worker         /// @endcond
718*890232f2SAndroid Build Coastguard Worker 
719*890232f2SAndroid Build Coastguard Worker         /// <summary>
720*890232f2SAndroid Build Coastguard Worker         /// Encode the string `s` in the buffer using UTF-8.
721*890232f2SAndroid Build Coastguard Worker         /// </summary>
722*890232f2SAndroid Build Coastguard Worker         /// <param name="s">The string to encode.</param>
723*890232f2SAndroid Build Coastguard Worker         /// <returns>
724*890232f2SAndroid Build Coastguard Worker         /// The offset in the buffer where the encoded string starts.
725*890232f2SAndroid Build Coastguard Worker         /// </returns>
CreateString(string s)726*890232f2SAndroid Build Coastguard Worker         public StringOffset CreateString(string s)
727*890232f2SAndroid Build Coastguard Worker         {
728*890232f2SAndroid Build Coastguard Worker             if (s == null)
729*890232f2SAndroid Build Coastguard Worker             {
730*890232f2SAndroid Build Coastguard Worker                 return new StringOffset(0);
731*890232f2SAndroid Build Coastguard Worker             }
732*890232f2SAndroid Build Coastguard Worker             NotNested();
733*890232f2SAndroid Build Coastguard Worker             AddByte(0);
734*890232f2SAndroid Build Coastguard Worker             var utf8StringLen = Encoding.UTF8.GetByteCount(s);
735*890232f2SAndroid Build Coastguard Worker             StartVector(1, utf8StringLen, 1);
736*890232f2SAndroid Build Coastguard Worker             _bb.PutStringUTF8(_space -= utf8StringLen, s);
737*890232f2SAndroid Build Coastguard Worker             return new StringOffset(EndVector().Value);
738*890232f2SAndroid Build Coastguard Worker         }
739*890232f2SAndroid Build Coastguard Worker 
740*890232f2SAndroid Build Coastguard Worker 
741*890232f2SAndroid Build Coastguard Worker #if ENABLE_SPAN_T && (UNSAFE_BYTEBUFFER || NETSTANDARD2_1)
742*890232f2SAndroid Build Coastguard Worker         /// <summary>
743*890232f2SAndroid Build Coastguard Worker         /// Creates a string in the buffer from a Span containing
744*890232f2SAndroid Build Coastguard Worker         /// a UTF8 string.
745*890232f2SAndroid Build Coastguard Worker         /// </summary>
746*890232f2SAndroid Build Coastguard Worker         /// <param name="chars">the UTF8 string to add to the buffer</param>
747*890232f2SAndroid Build Coastguard Worker         /// <returns>
748*890232f2SAndroid Build Coastguard Worker         /// The offset in the buffer where the encoded string starts.
749*890232f2SAndroid Build Coastguard Worker         /// </returns>
CreateUTF8String(Span<byte> chars)750*890232f2SAndroid Build Coastguard Worker         public StringOffset CreateUTF8String(Span<byte> chars)
751*890232f2SAndroid Build Coastguard Worker         {
752*890232f2SAndroid Build Coastguard Worker             NotNested();
753*890232f2SAndroid Build Coastguard Worker             AddByte(0);
754*890232f2SAndroid Build Coastguard Worker             var utf8StringLen = chars.Length;
755*890232f2SAndroid Build Coastguard Worker             StartVector(1, utf8StringLen, 1);
756*890232f2SAndroid Build Coastguard Worker             _space = _bb.Put(_space, chars);
757*890232f2SAndroid Build Coastguard Worker             return new StringOffset(EndVector().Value);
758*890232f2SAndroid Build Coastguard Worker         }
759*890232f2SAndroid Build Coastguard Worker #endif
760*890232f2SAndroid Build Coastguard Worker 
761*890232f2SAndroid Build Coastguard Worker         /// <summary>
762*890232f2SAndroid Build Coastguard Worker         /// Store a string in the buffer, which can contain any binary data.
763*890232f2SAndroid Build Coastguard Worker         /// If a string with this exact contents has already been serialized before,
764*890232f2SAndroid Build Coastguard Worker         /// instead simply returns the offset of the existing string.
765*890232f2SAndroid Build Coastguard Worker         /// </summary>
766*890232f2SAndroid Build Coastguard Worker         /// <param name="s">The string to encode.</param>
767*890232f2SAndroid Build Coastguard Worker         /// <returns>
768*890232f2SAndroid Build Coastguard Worker         /// The offset in the buffer where the encoded string starts.
769*890232f2SAndroid Build Coastguard Worker         /// </returns>
CreateSharedString(string s)770*890232f2SAndroid Build Coastguard Worker         public StringOffset CreateSharedString(string s)
771*890232f2SAndroid Build Coastguard Worker         {
772*890232f2SAndroid Build Coastguard Worker             if (s == null)
773*890232f2SAndroid Build Coastguard Worker             {
774*890232f2SAndroid Build Coastguard Worker               return new StringOffset(0);
775*890232f2SAndroid Build Coastguard Worker             }
776*890232f2SAndroid Build Coastguard Worker 
777*890232f2SAndroid Build Coastguard Worker             if (_sharedStringMap == null)
778*890232f2SAndroid Build Coastguard Worker             {
779*890232f2SAndroid Build Coastguard Worker                 _sharedStringMap = new Dictionary<string, StringOffset>();
780*890232f2SAndroid Build Coastguard Worker             }
781*890232f2SAndroid Build Coastguard Worker 
782*890232f2SAndroid Build Coastguard Worker             if (_sharedStringMap.ContainsKey(s))
783*890232f2SAndroid Build Coastguard Worker             {
784*890232f2SAndroid Build Coastguard Worker                 return _sharedStringMap[s];
785*890232f2SAndroid Build Coastguard Worker             }
786*890232f2SAndroid Build Coastguard Worker 
787*890232f2SAndroid Build Coastguard Worker             var stringOffset = CreateString(s);
788*890232f2SAndroid Build Coastguard Worker             _sharedStringMap.Add(s, stringOffset);
789*890232f2SAndroid Build Coastguard Worker             return stringOffset;
790*890232f2SAndroid Build Coastguard Worker         }
791*890232f2SAndroid Build Coastguard Worker 
792*890232f2SAndroid Build Coastguard Worker         /// @cond FLATBUFFERS_INTERNAL
793*890232f2SAndroid Build Coastguard Worker         // Structs are stored inline, so nothing additional is being added.
794*890232f2SAndroid Build Coastguard Worker         // `d` is always 0.
AddStruct(int voffset, int x, int d)795*890232f2SAndroid Build Coastguard Worker         public void AddStruct(int voffset, int x, int d)
796*890232f2SAndroid Build Coastguard Worker         {
797*890232f2SAndroid Build Coastguard Worker             if (x != d)
798*890232f2SAndroid Build Coastguard Worker             {
799*890232f2SAndroid Build Coastguard Worker                 Nested(x);
800*890232f2SAndroid Build Coastguard Worker                 Slot(voffset);
801*890232f2SAndroid Build Coastguard Worker             }
802*890232f2SAndroid Build Coastguard Worker         }
803*890232f2SAndroid Build Coastguard Worker 
EndTable()804*890232f2SAndroid Build Coastguard Worker         public int EndTable()
805*890232f2SAndroid Build Coastguard Worker         {
806*890232f2SAndroid Build Coastguard Worker             if (_vtableSize < 0)
807*890232f2SAndroid Build Coastguard Worker                 throw new InvalidOperationException(
808*890232f2SAndroid Build Coastguard Worker                   "Flatbuffers: calling EndTable without a StartTable");
809*890232f2SAndroid Build Coastguard Worker 
810*890232f2SAndroid Build Coastguard Worker             AddInt((int)0);
811*890232f2SAndroid Build Coastguard Worker             var vtableloc = Offset;
812*890232f2SAndroid Build Coastguard Worker             // Write out the current vtable.
813*890232f2SAndroid Build Coastguard Worker             int i = _vtableSize - 1;
814*890232f2SAndroid Build Coastguard Worker             // Trim trailing zeroes.
815*890232f2SAndroid Build Coastguard Worker             for (; i >= 0 && _vtable[i] == 0; i--) {}
816*890232f2SAndroid Build Coastguard Worker             int trimmedSize = i + 1;
817*890232f2SAndroid Build Coastguard Worker             for (; i >= 0 ; i--) {
818*890232f2SAndroid Build Coastguard Worker                 // Offset relative to the start of the table.
819*890232f2SAndroid Build Coastguard Worker                 short off = (short)(_vtable[i] != 0
820*890232f2SAndroid Build Coastguard Worker                                         ? vtableloc - _vtable[i]
821*890232f2SAndroid Build Coastguard Worker                                         : 0);
822*890232f2SAndroid Build Coastguard Worker                 AddShort(off);
823*890232f2SAndroid Build Coastguard Worker 
824*890232f2SAndroid Build Coastguard Worker                 // clear out written entry
825*890232f2SAndroid Build Coastguard Worker                 _vtable[i] = 0;
826*890232f2SAndroid Build Coastguard Worker             }
827*890232f2SAndroid Build Coastguard Worker 
828*890232f2SAndroid Build Coastguard Worker             const int standardFields = 2; // The fields below:
829*890232f2SAndroid Build Coastguard Worker             AddShort((short)(vtableloc - _objectStart));
830*890232f2SAndroid Build Coastguard Worker             AddShort((short)((trimmedSize + standardFields) *
831*890232f2SAndroid Build Coastguard Worker                              sizeof(short)));
832*890232f2SAndroid Build Coastguard Worker 
833*890232f2SAndroid Build Coastguard Worker             // Search for an existing vtable that matches the current one.
834*890232f2SAndroid Build Coastguard Worker             int existingVtable = 0;
835*890232f2SAndroid Build Coastguard Worker             for (i = 0; i < _numVtables; i++) {
836*890232f2SAndroid Build Coastguard Worker                 int vt1 = _bb.Length - _vtables[i];
837*890232f2SAndroid Build Coastguard Worker                 int vt2 = _space;
838*890232f2SAndroid Build Coastguard Worker                 short len = _bb.GetShort(vt1);
839*890232f2SAndroid Build Coastguard Worker                 if (len == _bb.GetShort(vt2)) {
840*890232f2SAndroid Build Coastguard Worker                     for (int j = sizeof(short); j < len; j += sizeof(short)) {
841*890232f2SAndroid Build Coastguard Worker                         if (_bb.GetShort(vt1 + j) != _bb.GetShort(vt2 + j)) {
842*890232f2SAndroid Build Coastguard Worker                             goto endLoop;
843*890232f2SAndroid Build Coastguard Worker                         }
844*890232f2SAndroid Build Coastguard Worker                     }
845*890232f2SAndroid Build Coastguard Worker                     existingVtable = _vtables[i];
846*890232f2SAndroid Build Coastguard Worker                     break;
847*890232f2SAndroid Build Coastguard Worker                 }
848*890232f2SAndroid Build Coastguard Worker 
849*890232f2SAndroid Build Coastguard Worker                 endLoop: { }
850*890232f2SAndroid Build Coastguard Worker             }
851*890232f2SAndroid Build Coastguard Worker 
852*890232f2SAndroid Build Coastguard Worker             if (existingVtable != 0) {
853*890232f2SAndroid Build Coastguard Worker                 // Found a match:
854*890232f2SAndroid Build Coastguard Worker                 // Remove the current vtable.
855*890232f2SAndroid Build Coastguard Worker                 _space = _bb.Length - vtableloc;
856*890232f2SAndroid Build Coastguard Worker                 // Point table to existing vtable.
857*890232f2SAndroid Build Coastguard Worker                 _bb.PutInt(_space, existingVtable - vtableloc);
858*890232f2SAndroid Build Coastguard Worker             } else {
859*890232f2SAndroid Build Coastguard Worker                 // No match:
860*890232f2SAndroid Build Coastguard Worker                 // Add the location of the current vtable to the list of
861*890232f2SAndroid Build Coastguard Worker                 // vtables.
862*890232f2SAndroid Build Coastguard Worker                 if (_numVtables == _vtables.Length)
863*890232f2SAndroid Build Coastguard Worker                 {
864*890232f2SAndroid Build Coastguard Worker                     // Arrays.CopyOf(vtables num_vtables * 2);
865*890232f2SAndroid Build Coastguard Worker                     var newvtables = new int[ _numVtables * 2];
866*890232f2SAndroid Build Coastguard Worker                     Array.Copy(_vtables, newvtables, _vtables.Length);
867*890232f2SAndroid Build Coastguard Worker 
868*890232f2SAndroid Build Coastguard Worker                     _vtables = newvtables;
869*890232f2SAndroid Build Coastguard Worker                 };
870*890232f2SAndroid Build Coastguard Worker                 _vtables[_numVtables++] = Offset;
871*890232f2SAndroid Build Coastguard Worker                 // Point table to current vtable.
872*890232f2SAndroid Build Coastguard Worker                 _bb.PutInt(_bb.Length - vtableloc, Offset - vtableloc);
873*890232f2SAndroid Build Coastguard Worker             }
874*890232f2SAndroid Build Coastguard Worker 
875*890232f2SAndroid Build Coastguard Worker             _vtableSize = -1;
876*890232f2SAndroid Build Coastguard Worker             return vtableloc;
877*890232f2SAndroid Build Coastguard Worker         }
878*890232f2SAndroid Build Coastguard Worker 
879*890232f2SAndroid Build Coastguard Worker         // This checks a required field has been set in a given table that has
880*890232f2SAndroid Build Coastguard Worker         // just been constructed.
Required(int table, int field)881*890232f2SAndroid Build Coastguard Worker         public void Required(int table, int field)
882*890232f2SAndroid Build Coastguard Worker         {
883*890232f2SAndroid Build Coastguard Worker           int table_start = _bb.Length - table;
884*890232f2SAndroid Build Coastguard Worker           int vtable_start = table_start - _bb.GetInt(table_start);
885*890232f2SAndroid Build Coastguard Worker           bool ok = _bb.GetShort(vtable_start + field) != 0;
886*890232f2SAndroid Build Coastguard Worker           // If this fails, the caller will show what field needs to be set.
887*890232f2SAndroid Build Coastguard Worker           if (!ok)
888*890232f2SAndroid Build Coastguard Worker             throw new InvalidOperationException("FlatBuffers: field " + field +
889*890232f2SAndroid Build Coastguard Worker                                                 " must be set");
890*890232f2SAndroid Build Coastguard Worker         }
891*890232f2SAndroid Build Coastguard Worker         /// @endcond
892*890232f2SAndroid Build Coastguard Worker 
893*890232f2SAndroid Build Coastguard Worker         /// <summary>
894*890232f2SAndroid Build Coastguard Worker         /// Finalize a buffer, pointing to the given `root_table`.
895*890232f2SAndroid Build Coastguard Worker         /// </summary>
896*890232f2SAndroid Build Coastguard Worker         /// <param name="rootTable">
897*890232f2SAndroid Build Coastguard Worker         /// An offset to be added to the buffer.
898*890232f2SAndroid Build Coastguard Worker         /// </param>
899*890232f2SAndroid Build Coastguard Worker         /// <param name="sizePrefix">
900*890232f2SAndroid Build Coastguard Worker         /// Whether to prefix the size to the buffer.
901*890232f2SAndroid Build Coastguard Worker         /// </param>
Finish(int rootTable, bool sizePrefix)902*890232f2SAndroid Build Coastguard Worker         protected void Finish(int rootTable, bool sizePrefix)
903*890232f2SAndroid Build Coastguard Worker         {
904*890232f2SAndroid Build Coastguard Worker             Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0));
905*890232f2SAndroid Build Coastguard Worker             AddOffset(rootTable);
906*890232f2SAndroid Build Coastguard Worker             if (sizePrefix) {
907*890232f2SAndroid Build Coastguard Worker                 AddInt(_bb.Length - _space);
908*890232f2SAndroid Build Coastguard Worker             }
909*890232f2SAndroid Build Coastguard Worker             _bb.Position = _space;
910*890232f2SAndroid Build Coastguard Worker         }
911*890232f2SAndroid Build Coastguard Worker 
912*890232f2SAndroid Build Coastguard Worker         /// <summary>
913*890232f2SAndroid Build Coastguard Worker         /// Finalize a buffer, pointing to the given `root_table`.
914*890232f2SAndroid Build Coastguard Worker         /// </summary>
915*890232f2SAndroid Build Coastguard Worker         /// <param name="rootTable">
916*890232f2SAndroid Build Coastguard Worker         /// An offset to be added to the buffer.
917*890232f2SAndroid Build Coastguard Worker         /// </param>
Finish(int rootTable)918*890232f2SAndroid Build Coastguard Worker         public void Finish(int rootTable)
919*890232f2SAndroid Build Coastguard Worker         {
920*890232f2SAndroid Build Coastguard Worker             Finish(rootTable, false);
921*890232f2SAndroid Build Coastguard Worker         }
922*890232f2SAndroid Build Coastguard Worker 
923*890232f2SAndroid Build Coastguard Worker         /// <summary>
924*890232f2SAndroid Build Coastguard Worker         /// Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
925*890232f2SAndroid Build Coastguard Worker         /// </summary>
926*890232f2SAndroid Build Coastguard Worker         /// <param name="rootTable">
927*890232f2SAndroid Build Coastguard Worker         /// An offset to be added to the buffer.
928*890232f2SAndroid Build Coastguard Worker         /// </param>
FinishSizePrefixed(int rootTable)929*890232f2SAndroid Build Coastguard Worker         public void FinishSizePrefixed(int rootTable)
930*890232f2SAndroid Build Coastguard Worker         {
931*890232f2SAndroid Build Coastguard Worker             Finish(rootTable, true);
932*890232f2SAndroid Build Coastguard Worker         }
933*890232f2SAndroid Build Coastguard Worker 
934*890232f2SAndroid Build Coastguard Worker         /// <summary>
935*890232f2SAndroid Build Coastguard Worker         /// Get the ByteBuffer representing the FlatBuffer.
936*890232f2SAndroid Build Coastguard Worker         /// </summary>
937*890232f2SAndroid Build Coastguard Worker         /// <remarks>
938*890232f2SAndroid Build Coastguard Worker         /// This is typically only called after you call `Finish()`.
939*890232f2SAndroid Build Coastguard Worker         /// The actual data starts at the ByteBuffer's current position,
940*890232f2SAndroid Build Coastguard Worker         /// not necessarily at `0`.
941*890232f2SAndroid Build Coastguard Worker         /// </remarks>
942*890232f2SAndroid Build Coastguard Worker         /// <returns>
943*890232f2SAndroid Build Coastguard Worker         /// Returns the ByteBuffer for this FlatBuffer.
944*890232f2SAndroid Build Coastguard Worker         /// </returns>
945*890232f2SAndroid Build Coastguard Worker         public ByteBuffer DataBuffer { get { return _bb; } }
946*890232f2SAndroid Build Coastguard Worker 
947*890232f2SAndroid Build Coastguard Worker         /// <summary>
948*890232f2SAndroid Build Coastguard Worker         /// A utility function to copy and return the ByteBuffer data as a
949*890232f2SAndroid Build Coastguard Worker         /// `byte[]`.
950*890232f2SAndroid Build Coastguard Worker         /// </summary>
951*890232f2SAndroid Build Coastguard Worker         /// <returns>
952*890232f2SAndroid Build Coastguard Worker         /// A full copy of the FlatBuffer data.
953*890232f2SAndroid Build Coastguard Worker         /// </returns>
SizedByteArray()954*890232f2SAndroid Build Coastguard Worker         public byte[] SizedByteArray()
955*890232f2SAndroid Build Coastguard Worker         {
956*890232f2SAndroid Build Coastguard Worker             return _bb.ToSizedArray();
957*890232f2SAndroid Build Coastguard Worker         }
958*890232f2SAndroid Build Coastguard Worker 
959*890232f2SAndroid Build Coastguard Worker         /// <summary>
960*890232f2SAndroid Build Coastguard Worker         /// Finalize a buffer, pointing to the given `rootTable`.
961*890232f2SAndroid Build Coastguard Worker         /// </summary>
962*890232f2SAndroid Build Coastguard Worker         /// <param name="rootTable">
963*890232f2SAndroid Build Coastguard Worker         /// An offset to be added to the buffer.
964*890232f2SAndroid Build Coastguard Worker         /// </param>
965*890232f2SAndroid Build Coastguard Worker         /// <param name="fileIdentifier">
966*890232f2SAndroid Build Coastguard Worker         /// A FlatBuffer file identifier to be added to the buffer before
967*890232f2SAndroid Build Coastguard Worker         /// `root_table`.
968*890232f2SAndroid Build Coastguard Worker         /// </param>
969*890232f2SAndroid Build Coastguard Worker         /// <param name="sizePrefix">
970*890232f2SAndroid Build Coastguard Worker         /// Whether to prefix the size to the buffer.
971*890232f2SAndroid Build Coastguard Worker         /// </param>
Finish(int rootTable, string fileIdentifier, bool sizePrefix)972*890232f2SAndroid Build Coastguard Worker         protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix)
973*890232f2SAndroid Build Coastguard Worker         {
974*890232f2SAndroid Build Coastguard Worker             Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0) +
975*890232f2SAndroid Build Coastguard Worker                             FlatBufferConstants.FileIdentifierLength);
976*890232f2SAndroid Build Coastguard Worker             if (fileIdentifier.Length !=
977*890232f2SAndroid Build Coastguard Worker                 FlatBufferConstants.FileIdentifierLength)
978*890232f2SAndroid Build Coastguard Worker                 throw new ArgumentException(
979*890232f2SAndroid Build Coastguard Worker                     "FlatBuffers: file identifier must be length " +
980*890232f2SAndroid Build Coastguard Worker                     FlatBufferConstants.FileIdentifierLength,
981*890232f2SAndroid Build Coastguard Worker                     "fileIdentifier");
982*890232f2SAndroid Build Coastguard Worker             for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
983*890232f2SAndroid Build Coastguard Worker                  i--)
984*890232f2SAndroid Build Coastguard Worker             {
985*890232f2SAndroid Build Coastguard Worker                AddByte((byte)fileIdentifier[i]);
986*890232f2SAndroid Build Coastguard Worker             }
987*890232f2SAndroid Build Coastguard Worker             Finish(rootTable, sizePrefix);
988*890232f2SAndroid Build Coastguard Worker         }
989*890232f2SAndroid Build Coastguard Worker 
990*890232f2SAndroid Build Coastguard Worker         /// <summary>
991*890232f2SAndroid Build Coastguard Worker         /// Finalize a buffer, pointing to the given `rootTable`.
992*890232f2SAndroid Build Coastguard Worker         /// </summary>
993*890232f2SAndroid Build Coastguard Worker         /// <param name="rootTable">
994*890232f2SAndroid Build Coastguard Worker         /// An offset to be added to the buffer.
995*890232f2SAndroid Build Coastguard Worker         /// </param>
996*890232f2SAndroid Build Coastguard Worker         /// <param name="fileIdentifier">
997*890232f2SAndroid Build Coastguard Worker         /// A FlatBuffer file identifier to be added to the buffer before
998*890232f2SAndroid Build Coastguard Worker         /// `root_table`.
999*890232f2SAndroid Build Coastguard Worker         /// </param>
Finish(int rootTable, string fileIdentifier)1000*890232f2SAndroid Build Coastguard Worker         public void Finish(int rootTable, string fileIdentifier)
1001*890232f2SAndroid Build Coastguard Worker         {
1002*890232f2SAndroid Build Coastguard Worker             Finish(rootTable, fileIdentifier, false);
1003*890232f2SAndroid Build Coastguard Worker         }
1004*890232f2SAndroid Build Coastguard Worker 
1005*890232f2SAndroid Build Coastguard Worker         /// <summary>
1006*890232f2SAndroid Build Coastguard Worker         /// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed.
1007*890232f2SAndroid Build Coastguard Worker         /// </summary>
1008*890232f2SAndroid Build Coastguard Worker         /// <param name="rootTable">
1009*890232f2SAndroid Build Coastguard Worker         /// An offset to be added to the buffer.
1010*890232f2SAndroid Build Coastguard Worker         /// </param>
1011*890232f2SAndroid Build Coastguard Worker         /// <param name="fileIdentifier">
1012*890232f2SAndroid Build Coastguard Worker         /// A FlatBuffer file identifier to be added to the buffer before
1013*890232f2SAndroid Build Coastguard Worker         /// `root_table`.
1014*890232f2SAndroid Build Coastguard Worker         /// </param>
FinishSizePrefixed(int rootTable, string fileIdentifier)1015*890232f2SAndroid Build Coastguard Worker         public void FinishSizePrefixed(int rootTable, string fileIdentifier)
1016*890232f2SAndroid Build Coastguard Worker         {
1017*890232f2SAndroid Build Coastguard Worker             Finish(rootTable, fileIdentifier, true);
1018*890232f2SAndroid Build Coastguard Worker         }
1019*890232f2SAndroid Build Coastguard Worker     }
1020*890232f2SAndroid Build Coastguard Worker }
1021*890232f2SAndroid Build Coastguard Worker 
1022*890232f2SAndroid Build Coastguard Worker /// @}
1023