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