LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/flatgeobuf/flatbuffers - flatbuffer_builder.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 161 163 98.8 %
Date: 2024-05-15 17:37:59 Functions: 67 70 95.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2021 Google Inc. All rights reserved.
       3             :  *
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  */
      16             : 
      17             : #ifndef FLATBUFFERS_FLATBUFFER_BUILDER_H_
      18             : #define FLATBUFFERS_FLATBUFFER_BUILDER_H_
      19             : 
      20             : #include <functional>
      21             : #include <initializer_list>
      22             : 
      23             : #include "flatbuffers/allocator.h"
      24             : #include "flatbuffers/array.h"
      25             : #include "flatbuffers/base.h"
      26             : #include "flatbuffers/buffer_ref.h"
      27             : #include "flatbuffers/default_allocator.h"
      28             : #include "flatbuffers/detached_buffer.h"
      29             : #include "flatbuffers/stl_emulation.h"
      30             : #include "flatbuffers/string.h"
      31             : #include "flatbuffers/struct.h"
      32             : #include "flatbuffers/table.h"
      33             : #include "flatbuffers/vector.h"
      34             : #include "flatbuffers/vector_downward.h"
      35             : #include "flatbuffers/verifier.h"
      36             : 
      37             : namespace flatbuffers {
      38             : 
      39             : // Converts a Field ID to a virtual table offset.
      40      132220 : inline voffset_t FieldIndexToOffset(voffset_t field_id) {
      41             :   // Should correspond to what EndTable() below builds up.
      42      132220 :   const int fixed_fields = 2;  // Vtable size and Object Size.
      43      132220 :   return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
      44             : }
      45             : 
      46             : template<typename T, typename Alloc = std::allocator<T>>
      47        1149 : const T *data(const std::vector<T, Alloc> &v) {
      48             :   // Eventually the returned pointer gets passed down to memcpy, so
      49             :   // we need it to be non-null to avoid undefined behavior.
      50             :   static uint8_t t;
      51        1149 :   return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
      52             : }
      53             : template<typename T, typename Alloc = std::allocator<T>>
      54             : T *data(std::vector<T, Alloc> &v) {
      55             :   // Eventually the returned pointer gets passed down to memcpy, so
      56             :   // we need it to be non-null to avoid undefined behavior.
      57             :   static uint8_t t;
      58             :   return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
      59             : }
      60             : 
      61             : /// @addtogroup flatbuffers_cpp_api
      62             : /// @{
      63             : /// @class FlatBufferBuilder
      64             : /// @brief Helper class to hold data needed in creation of a FlatBuffer.
      65             : /// To serialize data, you typically call one of the `Create*()` functions in
      66             : /// the generated code, which in turn call a sequence of `StartTable`/
      67             : /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
      68             : /// `CreateVector` functions. Do this is depth-first order to build up a tree to
      69             : /// the root. `Finish()` wraps up the buffer ready for transport.
      70             : class FlatBufferBuilder {
      71             :  public:
      72             :   /// @brief Default constructor for FlatBufferBuilder.
      73             :   /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
      74             :   /// to `1024`.
      75             :   /// @param[in] allocator An `Allocator` to use. If null will use
      76             :   /// `DefaultAllocator`.
      77             :   /// @param[in] own_allocator Whether the builder/vector should own the
      78             :   /// allocator. Defaults to / `false`.
      79             :   /// @param[in] buffer_minalign Force the buffer to be aligned to the given
      80             :   /// minimum alignment upon reallocation. Only needed if you intend to store
      81             :   /// types with custom alignment AND you wish to read the buffer in-place
      82             :   /// directly after creation.
      83         555 :   explicit FlatBufferBuilder(
      84             :       size_t initial_size = 1024, Allocator *allocator = nullptr,
      85             :       bool own_allocator = false,
      86             :       size_t buffer_minalign = AlignOf<largest_scalar_t>())
      87         555 :       : buf_(initial_size, allocator, own_allocator, buffer_minalign),
      88             :         num_field_loc(0),
      89             :         max_voffset_(0),
      90             :         nested(false),
      91             :         finished(false),
      92             :         minalign_(1),
      93             :         force_defaults_(false),
      94             :         dedup_vtables_(true),
      95         555 :         string_pool(nullptr) {
      96         555 :     EndianCheck();
      97         555 :   }
      98             : 
      99             :   /// @brief Move constructor for FlatBufferBuilder.
     100             :   FlatBufferBuilder(FlatBufferBuilder &&other)
     101             :       : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
     102             :         num_field_loc(0),
     103             :         max_voffset_(0),
     104             :         nested(false),
     105             :         finished(false),
     106             :         minalign_(1),
     107             :         force_defaults_(false),
     108             :         dedup_vtables_(true),
     109             :         string_pool(nullptr) {
     110             :     EndianCheck();
     111             :     // Default construct and swap idiom.
     112             :     // Lack of delegating constructors in vs2010 makes it more verbose than
     113             :     // needed.
     114             :     Swap(other);
     115             :   }
     116             : 
     117             :   /// @brief Move assignment operator for FlatBufferBuilder.
     118             :   FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
     119             :     // Move construct a temporary and swap idiom
     120             :     FlatBufferBuilder temp(std::move(other));
     121             :     Swap(temp);
     122             :     return *this;
     123             :   }
     124             : 
     125             :   void Swap(FlatBufferBuilder &other) {
     126             :     using std::swap;
     127             :     buf_.swap(other.buf_);
     128             :     swap(num_field_loc, other.num_field_loc);
     129             :     swap(max_voffset_, other.max_voffset_);
     130             :     swap(nested, other.nested);
     131             :     swap(finished, other.finished);
     132             :     swap(minalign_, other.minalign_);
     133             :     swap(force_defaults_, other.force_defaults_);
     134             :     swap(dedup_vtables_, other.dedup_vtables_);
     135             :     swap(string_pool, other.string_pool);
     136             :   }
     137             : 
     138         555 :   ~FlatBufferBuilder() {
     139         555 :     if (string_pool) delete string_pool;
     140         555 :   }
     141             : 
     142             :   void Reset() {
     143             :     Clear();       // clear builder state
     144             :     buf_.reset();  // deallocate buffer
     145             :   }
     146             : 
     147             :   /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
     148             :   /// to construct another buffer.
     149             :   void Clear() {
     150             :     ClearOffsets();
     151             :     buf_.clear();
     152             :     nested = false;
     153             :     finished = false;
     154             :     minalign_ = 1;
     155             :     if (string_pool) string_pool->clear();
     156             :   }
     157             : 
     158             :   /// @brief The current size of the serialized buffer, counting from the end.
     159             :   /// @return Returns an `uoffset_t` with the current size of the buffer.
     160     1855000 :   uoffset_t GetSize() const { return buf_.size(); }
     161             : 
     162             :   /// @brief Get the serialized buffer (after you call `Finish()`).
     163             :   /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
     164             :   /// buffer.
     165         505 :   uint8_t *GetBufferPointer() const {
     166         505 :     Finished();
     167         505 :     return buf_.data();
     168             :   }
     169             : 
     170             :   /// @brief Get the serialized buffer (after you call `Finish()`) as a span.
     171             :   /// @return Returns a constructed flatbuffers::span that is a view over the
     172             :   /// FlatBuffer data inside the buffer.
     173             :   flatbuffers::span<uint8_t> GetBufferSpan() const {
     174             :     Finished();
     175             :     return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
     176             :   }
     177             : 
     178             :   /// @brief Get a pointer to an unfinished buffer.
     179             :   /// @return Returns a `uint8_t` pointer to the unfinished buffer.
     180             :   uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
     181             : 
     182             :   /// @brief Get the released pointer to the serialized buffer.
     183             :   /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
     184             :   /// @return A `FlatBuffer` that owns the buffer and its allocator and
     185             :   /// behaves similar to a `unique_ptr` with a deleter.
     186             :   FLATBUFFERS_ATTRIBUTE([[deprecated("use Release() instead")]])
     187             :   DetachedBuffer ReleaseBufferPointer() {
     188             :     Finished();
     189             :     return buf_.release();
     190             :   }
     191             : 
     192             :   /// @brief Get the released DetachedBuffer.
     193             :   /// @return A `DetachedBuffer` that owns the buffer and its allocator.
     194             :   DetachedBuffer Release() {
     195             :     Finished();
     196             :     return buf_.release();
     197             :   }
     198             : 
     199             :   /// @brief Get the released pointer to the serialized buffer.
     200             :   /// @param size The size of the memory block containing
     201             :   /// the serialized `FlatBuffer`.
     202             :   /// @param offset The offset from the released pointer where the finished
     203             :   /// `FlatBuffer` starts.
     204             :   /// @return A raw pointer to the start of the memory block containing
     205             :   /// the serialized `FlatBuffer`.
     206             :   /// @remark If the allocator is owned, it gets deleted when the destructor is
     207             :   /// called..
     208             :   uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
     209             :     Finished();
     210             :     return buf_.release_raw(size, offset);
     211             :   }
     212             : 
     213             :   /// @brief get the minimum alignment this buffer needs to be accessed
     214             :   /// properly. This is only known once all elements have been written (after
     215             :   /// you call Finish()). You can use this information if you need to embed
     216             :   /// a FlatBuffer in some other buffer, such that you can later read it
     217             :   /// without first having to copy it into its own buffer.
     218             :   size_t GetBufferMinAlignment() const {
     219             :     Finished();
     220             :     return minalign_;
     221             :   }
     222             : 
     223             :   /// @cond FLATBUFFERS_INTERNAL
     224         505 :   void Finished() const {
     225             :     // If you get this assert, you're attempting to get access a buffer
     226             :     // which hasn't been finished yet. Be sure to call
     227             :     // FlatBufferBuilder::Finish with your root table.
     228             :     // If you really need to access an unfinished buffer, call
     229             :     // GetCurrentBufferPointer instead.
     230         505 :     FLATBUFFERS_ASSERT(finished);
     231         505 :   }
     232             :   /// @endcond
     233             : 
     234             :   /// @brief In order to save space, fields that are set to their default value
     235             :   /// don't get serialized into the buffer.
     236             :   /// @param[in] fd When set to `true`, always serializes default values that
     237             :   /// are set. Optional fields which are not set explicitly, will still not be
     238             :   /// serialized.
     239             :   void ForceDefaults(bool fd) { force_defaults_ = fd; }
     240             : 
     241             :   /// @brief By default vtables are deduped in order to save space.
     242             :   /// @param[in] dedup When set to `true`, dedup vtables.
     243             :   void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
     244             : 
     245             :   /// @cond FLATBUFFERS_INTERNAL
     246             :   void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
     247             : 
     248     1194470 :   void TrackMinAlign(size_t elem_size) {
     249     1194470 :     if (elem_size > minalign_) minalign_ = elem_size;
     250     1194470 :   }
     251             : 
     252     1059790 :   void Align(size_t elem_size) {
     253     1059790 :     TrackMinAlign(elem_size);
     254     1059790 :     buf_.fill(PaddingBytes(buf_.size(), elem_size));
     255     1059790 :   }
     256             : 
     257             :   void PushFlatBuffer(const uint8_t *bytes, size_t size) {
     258             :     PushBytes(bytes, size);
     259             :     finished = true;
     260             :   }
     261             : 
     262      132537 :   void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
     263             : 
     264             :   void PopBytes(size_t amount) { buf_.pop(amount); }
     265             : 
     266      928357 :   template<typename T> void AssertScalarT() {
     267             :     // The code assumes power of 2 sizes and endian-swap-ability.
     268             :     static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
     269      928357 :   }
     270             : 
     271             :   // Write a single aligned scalar to the buffer
     272      794671 :   template<typename T> uoffset_t PushElement(T element) {
     273      794671 :     AssertScalarT<T>();
     274      794671 :     Align(sizeof(T));
     275      794671 :     buf_.push_small(EndianScalar(element));
     276      794671 :     return GetSize();
     277             :   }
     278             : 
     279      131508 :   template<typename T> uoffset_t PushElement(Offset<T> off) {
     280             :     // Special case for offsets: see ReferTo below.
     281      131508 :     return PushElement(ReferTo(off.o));
     282             :   }
     283             : 
     284             :   // When writing fields, we track where they are, so we can create correct
     285             :   // vtables later.
     286      397032 :   void TrackField(voffset_t field, uoffset_t off) {
     287      397032 :     FieldLoc fl = { off, field };
     288      397032 :     buf_.scratch_push_small(fl);
     289      397032 :     num_field_loc++;
     290      397032 :     if (field > max_voffset_) { max_voffset_ = field; }
     291      397032 :   }
     292             : 
     293             :   // Like PushElement, but additionally tracks the field this represents.
     294     1055360 :   template<typename T> void AddElement(voffset_t field, T e, T def) {
     295             :     // We don't serialize values equal to the default.
     296     1055360 :     if (IsTheSameAs(e, def) && !force_defaults_) return;
     297      397032 :     TrackField(field, PushElement(e));
     298             :   }
     299             : 
     300             :   template<typename T> void AddElement(voffset_t field, T e) {
     301             :     TrackField(field, PushElement(e));
     302             :   }
     303             : 
     304      530534 :   template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
     305      530534 :     if (off.IsNull()) return;  // Don't store.
     306      133108 :     AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
     307             :   }
     308             : 
     309             :   template<typename T> void AddStruct(voffset_t field, const T *structptr) {
     310             :     if (!structptr) return;  // Default, don't store.
     311             :     Align(AlignOf<T>());
     312             :     buf_.push_small(*structptr);
     313             :     TrackField(field, GetSize());
     314             :   }
     315             : 
     316             :   void AddStructOffset(voffset_t field, uoffset_t off) {
     317             :     TrackField(field, off);
     318             :   }
     319             : 
     320             :   // Offsets initially are relative to the end of the buffer (downwards).
     321             :   // This function converts them to be relative to the current location
     322             :   // in the buffer (when stored here), pointing upwards.
     323      265121 :   uoffset_t ReferTo(uoffset_t off) {
     324             :     // Align to ensure GetSize() below is correct.
     325      265121 :     Align(sizeof(uoffset_t));
     326             :     // Offset must refer to something already in buffer.
     327      265121 :     const uoffset_t size = GetSize();
     328      265121 :     FLATBUFFERS_ASSERT(off && off <= size);
     329      265121 :     return size - off + static_cast<uoffset_t>(sizeof(uoffset_t));
     330             :   }
     331             : 
     332      265626 :   void NotNested() {
     333             :     // If you hit this, you're trying to construct a Table/Vector/String
     334             :     // during the construction of its parent table (between the MyTableBuilder
     335             :     // and table.Finish().
     336             :     // Move the creation of these sub-objects to above the MyTableBuilder to
     337             :     // not get this assert.
     338             :     // Ignoring this assert may appear to work in simple cases, but the reason
     339             :     // it is here is that storing objects in-line may cause vtable offsets
     340             :     // to not fit anymore. It also leads to vtable duplication.
     341      265626 :     FLATBUFFERS_ASSERT(!nested);
     342             :     // If you hit this, fields were added outside the scope of a table.
     343      265626 :     FLATBUFFERS_ASSERT(!num_field_loc);
     344      265626 :   }
     345             : 
     346             :   // From generated code (or from the parser), we call StartTable/EndTable
     347             :   // with a sequence of AddElement calls in between.
     348      132220 :   uoffset_t StartTable() {
     349      132220 :     NotNested();
     350      132220 :     nested = true;
     351      132220 :     return GetSize();
     352             :   }
     353             : 
     354             :   // This finishes one serialized object by generating the vtable if it's a
     355             :   // table, comparing it against existing vtables, and writing the
     356             :   // resulting vtable offset.
     357      132220 :   uoffset_t EndTable(uoffset_t start) {
     358             :     // If you get this assert, a corresponding StartTable wasn't called.
     359      132220 :     FLATBUFFERS_ASSERT(nested);
     360             :     // Write the vtable offset, which is the start of any Table.
     361             :     // We fill it's value later.
     362      132220 :     auto vtableoffsetloc = PushElement<soffset_t>(0);
     363             :     // Write a vtable, which consists entirely of voffset_t elements.
     364             :     // It starts with the number of offsets, followed by a type id, followed
     365             :     // by the offsets themselves. In reverse:
     366             :     // Include space for the last offset and ensure empty tables have a
     367             :     // minimum size.
     368      132220 :     max_voffset_ =
     369      264440 :         (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
     370      132220 :                    FieldIndexToOffset(0));
     371      132220 :     buf_.fill_big(max_voffset_);
     372      132220 :     auto table_object_size = vtableoffsetloc - start;
     373             :     // Vtable use 16bit offsets.
     374      132220 :     FLATBUFFERS_ASSERT(table_object_size < 0x10000);
     375      132220 :     WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
     376             :                            static_cast<voffset_t>(table_object_size));
     377      132220 :     WriteScalar<voffset_t>(buf_.data(), max_voffset_);
     378             :     // Write the offsets into the table
     379      132220 :     for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
     380      529252 :          it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
     381      397032 :       auto field_location = reinterpret_cast<FieldLoc *>(it);
     382      397032 :       auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
     383             :       // If this asserts, it means you've set a field twice.
     384      397032 :       FLATBUFFERS_ASSERT(
     385             :           !ReadScalar<voffset_t>(buf_.data() + field_location->id));
     386      397032 :       WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
     387             :     }
     388      132220 :     ClearOffsets();
     389      132220 :     auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
     390      132220 :     auto vt1_size = ReadScalar<voffset_t>(vt1);
     391      132220 :     auto vt_use = GetSize();
     392             :     // See if we already have generated a vtable with this exact same
     393             :     // layout before. If so, make it point to the old one, remove this one.
     394      132220 :     if (dedup_vtables_) {
     395      132821 :       for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
     396         601 :            it += sizeof(uoffset_t)) {
     397      131891 :         auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
     398      131891 :         auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
     399      131891 :         auto vt2_size = ReadScalar<voffset_t>(vt2);
     400      131891 :         if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
     401      131290 :         vt_use = *vt_offset_ptr;
     402      131290 :         buf_.pop(GetSize() - vtableoffsetloc);
     403      131290 :         break;
     404             :       }
     405             :     }
     406             :     // If this is a new vtable, remember it.
     407      132220 :     if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
     408             :     // Fill the vtable offset we created above.
     409             :     // The offset points from the beginning of the object to where the
     410             :     // vtable is stored.
     411             :     // Offsets default direction is downward in memory for future format
     412             :     // flexibility (storing all vtables at the start of the file).
     413      132220 :     WriteScalar(buf_.data_at(vtableoffsetloc),
     414      132220 :                 static_cast<soffset_t>(vt_use) -
     415      132220 :                     static_cast<soffset_t>(vtableoffsetloc));
     416             : 
     417      132220 :     nested = false;
     418      132220 :     return vtableoffsetloc;
     419             :   }
     420             : 
     421             :   FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
     422             :   uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
     423             :     return EndTable(start);
     424             :   }
     425             : 
     426             :   // This checks a required field has been set in a given table that has
     427             :   // just been constructed.
     428             :   template<typename T> void Required(Offset<T> table, voffset_t field);
     429             : 
     430             :   uoffset_t StartStruct(size_t alignment) {
     431             :     Align(alignment);
     432             :     return GetSize();
     433             :   }
     434             : 
     435             :   uoffset_t EndStruct() { return GetSize(); }
     436             : 
     437      132220 :   void ClearOffsets() {
     438      132220 :     buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
     439      132220 :     num_field_loc = 0;
     440      132220 :     max_voffset_ = 0;
     441      132220 :   }
     442             : 
     443             :   // Aligns such that when "len" bytes are written, an object can be written
     444             :   // after it with "alignment" without padding.
     445      134555 :   void PreAlign(size_t len, size_t alignment) {
     446      134555 :     if (len == 0) return;
     447      134121 :     TrackMinAlign(alignment);
     448      134121 :     buf_.fill(PaddingBytes(GetSize() + len, alignment));
     449             :   }
     450      132901 :   template<typename T> void PreAlign(size_t len) {
     451      132901 :     AssertScalarT<T>();
     452      132901 :     PreAlign(len, sizeof(T));
     453      132901 :   }
     454             :   /// @endcond
     455             : 
     456             :   /// @brief Store a string in the buffer, which can contain any binary data.
     457             :   /// @param[in] str A const char pointer to the data to be stored as a string.
     458             :   /// @param[in] len The number of bytes that should be stored from `str`.
     459             :   /// @return Returns the offset in the buffer where the string starts.
     460      131752 :   Offset<String> CreateString(const char *str, size_t len) {
     461      131752 :     NotNested();
     462      131752 :     PreAlign<uoffset_t>(len + 1);  // Always 0-terminated.
     463      131752 :     buf_.fill(1);
     464      131752 :     PushBytes(reinterpret_cast<const uint8_t *>(str), len);
     465      131752 :     PushElement(static_cast<uoffset_t>(len));
     466      131752 :     return Offset<String>(GetSize());
     467             :   }
     468             : 
     469             :   /// @brief Store a string in the buffer, which is null-terminated.
     470             :   /// @param[in] str A const char pointer to a C-string to add to the buffer.
     471             :   /// @return Returns the offset in the buffer where the string starts.
     472      131752 :   Offset<String> CreateString(const char *str) {
     473      131752 :     return CreateString(str, strlen(str));
     474             :   }
     475             : 
     476             :   /// @brief Store a string in the buffer, which is null-terminated.
     477             :   /// @param[in] str A char pointer to a C-string to add to the buffer.
     478             :   /// @return Returns the offset in the buffer where the string starts.
     479             :   Offset<String> CreateString(char *str) {
     480             :     return CreateString(str, strlen(str));
     481             :   }
     482             : 
     483             :   /// @brief Store a string in the buffer, which can contain any binary data.
     484             :   /// @param[in] str A const reference to a std::string to store in the buffer.
     485             :   /// @return Returns the offset in the buffer where the string starts.
     486             :   Offset<String> CreateString(const std::string &str) {
     487             :     return CreateString(str.c_str(), str.length());
     488             :   }
     489             : 
     490             :   // clang-format off
     491             :   #ifdef FLATBUFFERS_HAS_STRING_VIEW
     492             :   /// @brief Store a string in the buffer, which can contain any binary data.
     493             :   /// @param[in] str A const string_view to copy in to the buffer.
     494             :   /// @return Returns the offset in the buffer where the string starts.
     495             :   Offset<String> CreateString(flatbuffers::string_view str) {
     496             :     return CreateString(str.data(), str.size());
     497             :   }
     498             :   #endif // FLATBUFFERS_HAS_STRING_VIEW
     499             :   // clang-format on
     500             : 
     501             :   /// @brief Store a string in the buffer, which can contain any binary data.
     502             :   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
     503             :   /// @return Returns the offset in the buffer where the string starts
     504             :   Offset<String> CreateString(const String *str) {
     505             :     return str ? CreateString(str->c_str(), str->size()) : 0;
     506             :   }
     507             : 
     508             :   /// @brief Store a string in the buffer, which can contain any binary data.
     509             :   /// @param[in] str A const reference to a std::string like type with support
     510             :   /// of T::c_str() and T::length() to store in the buffer.
     511             :   /// @return Returns the offset in the buffer where the string starts.
     512             :   template<typename T> Offset<String> CreateString(const T &str) {
     513             :     return CreateString(str.c_str(), str.length());
     514             :   }
     515             : 
     516             :   /// @brief Store a string in the buffer, which can contain any binary data.
     517             :   /// If a string with this exact contents has already been serialized before,
     518             :   /// instead simply returns the offset of the existing string. This uses a map
     519             :   /// stored on the heap, but only stores the numerical offsets.
     520             :   /// @param[in] str A const char pointer to the data to be stored as a string.
     521             :   /// @param[in] len The number of bytes that should be stored from `str`.
     522             :   /// @return Returns the offset in the buffer where the string starts.
     523             :   Offset<String> CreateSharedString(const char *str, size_t len) {
     524             :     FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
     525             :     if (!string_pool)
     526             :       string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
     527             :     auto size_before_string = buf_.size();
     528             :     // Must first serialize the string, since the set is all offsets into
     529             :     // buffer.
     530             :     auto off = CreateString(str, len);
     531             :     auto it = string_pool->find(off);
     532             :     // If it exists we reuse existing serialized data!
     533             :     if (it != string_pool->end()) {
     534             :       // We can remove the string we serialized.
     535             :       buf_.pop(buf_.size() - size_before_string);
     536             :       return *it;
     537             :     }
     538             :     // Record this string for future use.
     539             :     string_pool->insert(off);
     540             :     return off;
     541             :   }
     542             : 
     543             : #ifdef FLATBUFFERS_HAS_STRING_VIEW
     544             :   /// @brief Store a string in the buffer, which can contain any binary data.
     545             :   /// If a string with this exact contents has already been serialized before,
     546             :   /// instead simply returns the offset of the existing string. This uses a map
     547             :   /// stored on the heap, but only stores the numerical offsets.
     548             :   /// @param[in] str A const std::string_view to store in the buffer.
     549             :   /// @return Returns the offset in the buffer where the string starts
     550             :   Offset<String> CreateSharedString(const flatbuffers::string_view str) {
     551             :     return CreateSharedString(str.data(), str.size());
     552             :   }
     553             : #else
     554             :   /// @brief Store a string in the buffer, which null-terminated.
     555             :   /// If a string with this exact contents has already been serialized before,
     556             :   /// instead simply returns the offset of the existing string. This uses a map
     557             :   /// stored on the heap, but only stores the numerical offsets.
     558             :   /// @param[in] str A const char pointer to a C-string to add to the buffer.
     559             :   /// @return Returns the offset in the buffer where the string starts.
     560             :   Offset<String> CreateSharedString(const char *str) {
     561             :     return CreateSharedString(str, strlen(str));
     562             :   }
     563             : 
     564             :   /// @brief Store a string in the buffer, which can contain any binary data.
     565             :   /// If a string with this exact contents has already been serialized before,
     566             :   /// instead simply returns the offset of the existing string. This uses a map
     567             :   /// stored on the heap, but only stores the numerical offsets.
     568             :   /// @param[in] str A const reference to a std::string to store in the buffer.
     569             :   /// @return Returns the offset in the buffer where the string starts.
     570             :   Offset<String> CreateSharedString(const std::string &str) {
     571             :     return CreateSharedString(str.c_str(), str.length());
     572             :   }
     573             : #endif
     574             : 
     575             :   /// @brief Store a string in the buffer, which can contain any binary data.
     576             :   /// If a string with this exact contents has already been serialized before,
     577             :   /// instead simply returns the offset of the existing string. This uses a map
     578             :   /// stored on the heap, but only stores the numerical offsets.
     579             :   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
     580             :   /// @return Returns the offset in the buffer where the string starts
     581             :   Offset<String> CreateSharedString(const String *str) {
     582             :     return CreateSharedString(str->c_str(), str->size());
     583             :   }
     584             : 
     585             :   /// @cond FLATBUFFERS_INTERNAL
     586        1149 :   uoffset_t EndVector(size_t len) {
     587        1149 :     FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector.
     588        1149 :     nested = false;
     589        1149 :     return PushElement(static_cast<uoffset_t>(len));
     590             :   }
     591             : 
     592        1149 :   void StartVector(size_t len, size_t elemsize) {
     593        1149 :     NotNested();
     594        1149 :     nested = true;
     595        1149 :     PreAlign<uoffset_t>(len * elemsize);
     596        1149 :     PreAlign(len * elemsize, elemsize);  // Just in case elemsize > uoffset_t.
     597        1149 :   }
     598             : 
     599             :   // Call this right before StartVector/CreateVector if you want to force the
     600             :   // alignment to be something different than what the element size would
     601             :   // normally dictate.
     602             :   // This is useful when storing a nested_flatbuffer in a vector of bytes,
     603             :   // or when storing SIMD floats, etc.
     604             :   void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
     605             :     if (len == 0) return;
     606             :     FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
     607             :     PreAlign(len * elemsize, alignment);
     608             :   }
     609             : 
     610             :   // Similar to ForceVectorAlignment but for String fields.
     611             :   void ForceStringAlignment(size_t len, size_t alignment) {
     612             :     if (len == 0) return;
     613             :     FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
     614             :     PreAlign((len + 1) * sizeof(char), alignment);
     615             :   }
     616             : 
     617             :   /// @endcond
     618             : 
     619             :   /// @brief Serialize an array into a FlatBuffer `vector`.
     620             :   /// @tparam T The data type of the array elements.
     621             :   /// @param[in] v A pointer to the array of type `T` to serialize into the
     622             :   /// buffer as a `vector`.
     623             :   /// @param[in] len The number of elements to serialize.
     624             :   /// @return Returns a typed `Offset` into the serialized data indicating
     625             :   /// where the vector is stored.
     626         785 :   template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
     627             :     // If this assert hits, you're specifying a template argument that is
     628             :     // causing the wrong overload to be selected, remove it.
     629         785 :     AssertScalarT<T>();
     630         785 :     StartVector(len, sizeof(T));
     631         785 :     if (len == 0) { return Offset<Vector<T>>(EndVector(len)); }
     632             :     // clang-format off
     633             :     #if FLATBUFFERS_LITTLEENDIAN
     634         785 :       PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
     635             :     #else
     636             :       if (sizeof(T) == 1) {
     637             :         PushBytes(reinterpret_cast<const uint8_t *>(v), len);
     638             :       } else {
     639             :         for (auto i = len; i > 0; ) {
     640             :           PushElement(v[--i]);
     641             :         }
     642             :       }
     643             :     #endif
     644             :     // clang-format on
     645         785 :     return Offset<Vector<T>>(EndVector(len));
     646             :   }
     647             : 
     648             :   /// @brief Serialize an array like object into a FlatBuffer `vector`.
     649             :   /// @tparam T The data type of the array elements.
     650             :   /// @tparam C The type of the array.
     651             :   /// @param[in] array A reference to an array like object of type `T` to
     652             :   /// serialize into the buffer as a `vector`.
     653             :   /// @return Returns a typed `Offset` into the serialized data indicating
     654             :   /// where the vector is stored.
     655             :   template<typename T, class C> Offset<Vector<T>> CreateVector(const C &array) {
     656             :     return CreateVector(array.data(), array.size());
     657             :   }
     658             : 
     659             :   /// @brief Serialize an initializer list into a FlatBuffer `vector`.
     660             :   /// @tparam T The data type of the initializer list elements.
     661             :   /// @param[in] v The value of the initializer list.
     662             :   /// @return Returns a typed `Offset` into the serialized data indicating
     663             :   /// where the vector is stored.
     664             :   template<typename T>
     665             :   Offset<Vector<T>> CreateVector(std::initializer_list<T> v) {
     666             :     return CreateVector(v.begin(), v.size());
     667             :   }
     668             : 
     669             :   template<typename T>
     670         364 :   Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
     671         364 :     StartVector(len, sizeof(Offset<T>));
     672      131872 :     for (auto i = len; i > 0;) { PushElement(v[--i]); }
     673         364 :     return Offset<Vector<Offset<T>>>(EndVector(len));
     674             :   }
     675             : 
     676             :   /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
     677             :   /// @tparam T The data type of the `std::vector` elements.
     678             :   /// @param v A const reference to the `std::vector` to serialize into the
     679             :   /// buffer as a `vector`.
     680             :   /// @return Returns a typed `Offset` into the serialized data indicating
     681             :   /// where the vector is stored.
     682             :   template<typename T, typename Alloc = std::allocator<T>>
     683        1149 :   Offset<Vector<T>> CreateVector(const std::vector<T, Alloc> &v) {
     684        1149 :     return CreateVector(data(v), v.size());
     685             :   }
     686             : 
     687             :   // vector<bool> may be implemented using a bit-set, so we can't access it as
     688             :   // an array. Instead, read elements manually.
     689             :   // Background: https://isocpp.org/blog/2012/11/on-vectorbool
     690             :   Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
     691             :     StartVector(v.size(), sizeof(uint8_t));
     692             :     for (auto i = v.size(); i > 0;) {
     693             :       PushElement(static_cast<uint8_t>(v[--i]));
     694             :     }
     695             :     return Offset<Vector<uint8_t>>(EndVector(v.size()));
     696             :   }
     697             : 
     698             :   /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
     699             :   /// This is a convenience function that takes care of iteration for you.
     700             :   /// @tparam T The data type of the `std::vector` elements.
     701             :   /// @param f A function that takes the current iteration 0..vector_size-1 and
     702             :   /// returns any type that you can construct a FlatBuffers vector out of.
     703             :   /// @return Returns a typed `Offset` into the serialized data indicating
     704             :   /// where the vector is stored.
     705             :   template<typename T>
     706             :   Offset<Vector<T>> CreateVector(size_t vector_size,
     707             :                                  const std::function<T(size_t i)> &f) {
     708             :     FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
     709             :     std::vector<T> elems(vector_size);
     710             :     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
     711             :     return CreateVector(elems);
     712             :   }
     713             : 
     714             :   /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
     715             :   /// This is a convenience function that takes care of iteration for you. This
     716             :   /// uses a vector stored on the heap to store the intermediate results of the
     717             :   /// iteration.
     718             :   /// @tparam T The data type of the `std::vector` elements.
     719             :   /// @param f A function that takes the current iteration 0..vector_size-1,
     720             :   /// and the state parameter returning any type that you can construct a
     721             :   /// FlatBuffers vector out of.
     722             :   /// @param state State passed to f.
     723             :   /// @return Returns a typed `Offset` into the serialized data indicating
     724             :   /// where the vector is stored.
     725             :   template<typename T, typename F, typename S>
     726             :   Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
     727             :     FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
     728             :     std::vector<T> elems(vector_size);
     729             :     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
     730             :     return CreateVector(elems);
     731             :   }
     732             : 
     733             :   /// @brief Serialize a `std::vector<StringType>` into a FlatBuffer `vector`.
     734             :   /// whereas StringType is any type that is accepted by the CreateString()
     735             :   /// overloads.
     736             :   /// This is a convenience function for a common case.
     737             :   /// @param v A const reference to the `std::vector` to serialize into the
     738             :   /// buffer as a `vector`.
     739             :   /// @return Returns a typed `Offset` into the serialized data indicating
     740             :   /// where the vector is stored.
     741             :   template<typename StringType = std::string,
     742             :            typename Alloc = std::allocator<StringType>>
     743             :   Offset<Vector<Offset<String>>> CreateVectorOfStrings(
     744             :       const std::vector<StringType, Alloc> &v) {
     745             :     return CreateVectorOfStrings(v.cbegin(), v.cend());
     746             :   }
     747             : 
     748             :   /// @brief Serialize a collection of Strings into a FlatBuffer `vector`.
     749             :   /// This is a convenience function for a common case.
     750             :   /// @param begin The beginning iterator of the collection
     751             :   /// @param end The ending iterator of the collection
     752             :   /// @return Returns a typed `Offset` into the serialized data indicating
     753             :   /// where the vector is stored.
     754             :   template<class It>
     755             :   Offset<Vector<Offset<String>>> CreateVectorOfStrings(It begin, It end) {
     756             :     auto size = std::distance(begin, end);
     757             :     auto scratch_buffer_usage = size * sizeof(Offset<String>);
     758             :     // If there is not enough space to store the offsets, there definitely won't
     759             :     // be enough space to store all the strings. So ensuring space for the
     760             :     // scratch region is OK, for it it fails, it would have failed later.
     761             :     buf_.ensure_space(scratch_buffer_usage);
     762             :     for (auto it = begin; it != end; ++it) {
     763             :       buf_.scratch_push_small(CreateString(*it));
     764             :     }
     765             :     StartVector(size, sizeof(Offset<String>));
     766             :     for (auto i = 1; i <= size; i++) {
     767             :       // Note we re-evaluate the buf location each iteration to account for any
     768             :       // underlying buffer resizing that may occur.
     769             :       PushElement(*reinterpret_cast<Offset<String> *>(
     770             :           buf_.scratch_end() - i * sizeof(Offset<String>)));
     771             :     }
     772             :     buf_.scratch_pop(scratch_buffer_usage);
     773             :     return Offset<Vector<Offset<String>>>(EndVector(size));
     774             :   }
     775             : 
     776             :   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
     777             :   /// @tparam T The data type of the struct array elements.
     778             :   /// @param[in] v A pointer to the array of type `T` to serialize into the
     779             :   /// buffer as a `vector`.
     780             :   /// @param[in] len The number of elements to serialize.
     781             :   /// @return Returns a typed `Offset` into the serialized data indicating
     782             :   /// where the vector is stored.
     783             :   template<typename T>
     784             :   Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
     785             :     StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
     786             :     if (len > 0) {
     787             :       PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
     788             :     }
     789             :     return Offset<Vector<const T *>>(EndVector(len));
     790             :   }
     791             : 
     792             :   /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
     793             :   /// @tparam T The data type of the struct array elements.
     794             :   /// @tparam S The data type of the native struct array elements.
     795             :   /// @param[in] v A pointer to the array of type `S` to serialize into the
     796             :   /// buffer as a `vector`.
     797             :   /// @param[in] len The number of elements to serialize.
     798             :   /// @param[in] pack_func Pointer to a function to convert the native struct
     799             :   /// to the FlatBuffer struct.
     800             :   /// @return Returns a typed `Offset` into the serialized data indicating
     801             :   /// where the vector is stored.
     802             :   template<typename T, typename S>
     803             :   Offset<Vector<const T *>> CreateVectorOfNativeStructs(
     804             :       const S *v, size_t len, T (*const pack_func)(const S &)) {
     805             :     FLATBUFFERS_ASSERT(pack_func);
     806             :     auto structs = StartVectorOfStructs<T>(len);
     807             :     for (size_t i = 0; i < len; i++) { structs[i] = pack_func(v[i]); }
     808             :     return EndVectorOfStructs<T>(len);
     809             :   }
     810             : 
     811             :   /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
     812             :   /// @tparam T The data type of the struct array elements.
     813             :   /// @tparam S The data type of the native struct array elements.
     814             :   /// @param[in] v A pointer to the array of type `S` to serialize into the
     815             :   /// buffer as a `vector`.
     816             :   /// @param[in] len The number of elements to serialize.
     817             :   /// @return Returns a typed `Offset` into the serialized data indicating
     818             :   /// where the vector is stored.
     819             :   template<typename T, typename S>
     820             :   Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
     821             :                                                         size_t len) {
     822             :     extern T Pack(const S &);
     823             :     return CreateVectorOfNativeStructs(v, len, Pack);
     824             :   }
     825             : 
     826             :   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
     827             :   /// @tparam T The data type of the struct array elements.
     828             :   /// @param[in] filler A function that takes the current iteration
     829             :   /// 0..vector_size-1 and a pointer to the struct that must be filled.
     830             :   /// @return Returns a typed `Offset` into the serialized data indicating
     831             :   /// where the vector is stored.
     832             :   /// This is mostly useful when flatbuffers are generated with mutation
     833             :   /// accessors.
     834             :   template<typename T>
     835             :   Offset<Vector<const T *>> CreateVectorOfStructs(
     836             :       size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
     837             :     T *structs = StartVectorOfStructs<T>(vector_size);
     838             :     for (size_t i = 0; i < vector_size; i++) {
     839             :       filler(i, structs);
     840             :       structs++;
     841             :     }
     842             :     return EndVectorOfStructs<T>(vector_size);
     843             :   }
     844             : 
     845             :   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
     846             :   /// @tparam T The data type of the struct array elements.
     847             :   /// @param[in] f A function that takes the current iteration 0..vector_size-1,
     848             :   /// a pointer to the struct that must be filled and the state argument.
     849             :   /// @param[in] state Arbitrary state to pass to f.
     850             :   /// @return Returns a typed `Offset` into the serialized data indicating
     851             :   /// where the vector is stored.
     852             :   /// This is mostly useful when flatbuffers are generated with mutation
     853             :   /// accessors.
     854             :   template<typename T, typename F, typename S>
     855             :   Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
     856             :                                                   S *state) {
     857             :     T *structs = StartVectorOfStructs<T>(vector_size);
     858             :     for (size_t i = 0; i < vector_size; i++) {
     859             :       f(i, structs, state);
     860             :       structs++;
     861             :     }
     862             :     return EndVectorOfStructs<T>(vector_size);
     863             :   }
     864             : 
     865             :   /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
     866             :   /// @tparam T The data type of the `std::vector` struct elements.
     867             :   /// @param[in] v A const reference to the `std::vector` of structs to
     868             :   /// serialize into the buffer as a `vector`.
     869             :   /// @return Returns a typed `Offset` into the serialized data indicating
     870             :   /// where the vector is stored.
     871             :   template<typename T, typename Alloc = std::allocator<T>>
     872             :   Offset<Vector<const T *>> CreateVectorOfStructs(
     873             :       const std::vector<T, Alloc> &v) {
     874             :     return CreateVectorOfStructs(data(v), v.size());
     875             :   }
     876             : 
     877             :   /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
     878             :   /// `vector`.
     879             :   /// @tparam T The data type of the `std::vector` struct elements.
     880             :   /// @tparam S The data type of the `std::vector` native struct elements.
     881             :   /// @param[in] v A const reference to the `std::vector` of structs to
     882             :   /// serialize into the buffer as a `vector`.
     883             :   /// @param[in] pack_func Pointer to a function to convert the native struct
     884             :   /// to the FlatBuffer struct.
     885             :   /// @return Returns a typed `Offset` into the serialized data indicating
     886             :   /// where the vector is stored.
     887             :   template<typename T, typename S, typename Alloc = std::allocator<T>>
     888             :   Offset<Vector<const T *>> CreateVectorOfNativeStructs(
     889             :       const std::vector<S, Alloc> &v, T (*const pack_func)(const S &)) {
     890             :     return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
     891             :   }
     892             : 
     893             :   /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
     894             :   /// `vector`.
     895             :   /// @tparam T The data type of the `std::vector` struct elements.
     896             :   /// @tparam S The data type of the `std::vector` native struct elements.
     897             :   /// @param[in] v A const reference to the `std::vector` of structs to
     898             :   /// serialize into the buffer as a `vector`.
     899             :   /// @return Returns a typed `Offset` into the serialized data indicating
     900             :   /// where the vector is stored.
     901             :   template<typename T, typename S, typename Alloc = std::allocator<S>>
     902             :   Offset<Vector<const T *>> CreateVectorOfNativeStructs(
     903             :       const std::vector<S, Alloc> &v) {
     904             :     return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
     905             :   }
     906             : 
     907             :   /// @cond FLATBUFFERS_INTERNAL
     908             :   template<typename T> struct StructKeyComparator {
     909             :     bool operator()(const T &a, const T &b) const {
     910             :       return a.KeyCompareLessThan(&b);
     911             :     }
     912             :   };
     913             :   /// @endcond
     914             : 
     915             :   /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
     916             :   /// in sorted order.
     917             :   /// @tparam T The data type of the `std::vector` struct elements.
     918             :   /// @param[in] v A const reference to the `std::vector` of structs to
     919             :   /// serialize into the buffer as a `vector`.
     920             :   /// @return Returns a typed `Offset` into the serialized data indicating
     921             :   /// where the vector is stored.
     922             :   template<typename T, typename Alloc = std::allocator<T>>
     923             :   Offset<Vector<const T *>> CreateVectorOfSortedStructs(
     924             :       std::vector<T, Alloc> *v) {
     925             :     return CreateVectorOfSortedStructs(data(*v), v->size());
     926             :   }
     927             : 
     928             :   /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
     929             :   /// `vector` in sorted order.
     930             :   /// @tparam T The data type of the `std::vector` struct elements.
     931             :   /// @tparam S The data type of the `std::vector` native struct elements.
     932             :   /// @param[in] v A const reference to the `std::vector` of structs to
     933             :   /// serialize into the buffer as a `vector`.
     934             :   /// @return Returns a typed `Offset` into the serialized data indicating
     935             :   /// where the vector is stored.
     936             :   template<typename T, typename S, typename Alloc = std::allocator<T>>
     937             :   Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
     938             :       std::vector<S, Alloc> *v) {
     939             :     return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
     940             :   }
     941             : 
     942             :   /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
     943             :   /// order.
     944             :   /// @tparam T The data type of the struct array elements.
     945             :   /// @param[in] v A pointer to the array of type `T` to serialize into the
     946             :   /// buffer as a `vector`.
     947             :   /// @param[in] len The number of elements to serialize.
     948             :   /// @return Returns a typed `Offset` into the serialized data indicating
     949             :   /// where the vector is stored.
     950             :   template<typename T>
     951             :   Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
     952             :     std::stable_sort(v, v + len, StructKeyComparator<T>());
     953             :     return CreateVectorOfStructs(v, len);
     954             :   }
     955             : 
     956             :   /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
     957             :   /// sorted order.
     958             :   /// @tparam T The data type of the struct array elements.
     959             :   /// @tparam S The data type of the native struct array elements.
     960             :   /// @param[in] v A pointer to the array of type `S` to serialize into the
     961             :   /// buffer as a `vector`.
     962             :   /// @param[in] len The number of elements to serialize.
     963             :   /// @return Returns a typed `Offset` into the serialized data indicating
     964             :   /// where the vector is stored.
     965             :   template<typename T, typename S>
     966             :   Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
     967             :                                                               size_t len) {
     968             :     extern T Pack(const S &);
     969             :     auto structs = StartVectorOfStructs<T>(len);
     970             :     for (size_t i = 0; i < len; i++) { structs[i] = Pack(v[i]); }
     971             :     std::stable_sort(structs, structs + len, StructKeyComparator<T>());
     972             :     return EndVectorOfStructs<T>(len);
     973             :   }
     974             : 
     975             :   /// @cond FLATBUFFERS_INTERNAL
     976             :   template<typename T> struct TableKeyComparator {
     977             :     TableKeyComparator(vector_downward &buf) : buf_(buf) {}
     978             :     TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
     979             :     bool operator()(const Offset<T> &a, const Offset<T> &b) const {
     980             :       auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
     981             :       auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
     982             :       return table_a->KeyCompareLessThan(table_b);
     983             :     }
     984             :     vector_downward &buf_;
     985             : 
     986             :    private:
     987             :     FLATBUFFERS_DELETE_FUNC(
     988             :         TableKeyComparator &operator=(const TableKeyComparator &other));
     989             :   };
     990             :   /// @endcond
     991             : 
     992             :   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
     993             :   /// in sorted order.
     994             :   /// @tparam T The data type that the offset refers to.
     995             :   /// @param[in] v An array of type `Offset<T>` that contains the `table`
     996             :   /// offsets to store in the buffer in sorted order.
     997             :   /// @param[in] len The number of elements to store in the `vector`.
     998             :   /// @return Returns a typed `Offset` into the serialized data indicating
     999             :   /// where the vector is stored.
    1000             :   template<typename T>
    1001             :   Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
    1002             :                                                        size_t len) {
    1003             :     std::stable_sort(v, v + len, TableKeyComparator<T>(buf_));
    1004             :     return CreateVector(v, len);
    1005             :   }
    1006             : 
    1007             :   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
    1008             :   /// in sorted order.
    1009             :   /// @tparam T The data type that the offset refers to.
    1010             :   /// @param[in] v An array of type `Offset<T>` that contains the `table`
    1011             :   /// offsets to store in the buffer in sorted order.
    1012             :   /// @return Returns a typed `Offset` into the serialized data indicating
    1013             :   /// where the vector is stored.
    1014             :   template<typename T, typename Alloc = std::allocator<T>>
    1015             :   Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
    1016             :       std::vector<Offset<T>, Alloc> *v) {
    1017             :     return CreateVectorOfSortedTables(data(*v), v->size());
    1018             :   }
    1019             : 
    1020             :   /// @brief Specialized version of `CreateVector` for non-copying use cases.
    1021             :   /// Write the data any time later to the returned buffer pointer `buf`.
    1022             :   /// @param[in] len The number of elements to store in the `vector`.
    1023             :   /// @param[in] elemsize The size of each element in the `vector`.
    1024             :   /// @param[out] buf A pointer to a `uint8_t` pointer that can be
    1025             :   /// written to at a later time to serialize the data into a `vector`
    1026             :   /// in the buffer.
    1027             :   uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
    1028             :                                       uint8_t **buf) {
    1029             :     NotNested();
    1030             :     StartVector(len, elemsize);
    1031             :     buf_.make_space(len * elemsize);
    1032             :     auto vec_start = GetSize();
    1033             :     auto vec_end = EndVector(len);
    1034             :     *buf = buf_.data_at(vec_start);
    1035             :     return vec_end;
    1036             :   }
    1037             : 
    1038             :   /// @brief Specialized version of `CreateVector` for non-copying use cases.
    1039             :   /// Write the data any time later to the returned buffer pointer `buf`.
    1040             :   /// @tparam T The data type of the data that will be stored in the buffer
    1041             :   /// as a `vector`.
    1042             :   /// @param[in] len The number of elements to store in the `vector`.
    1043             :   /// @param[out] buf A pointer to a pointer of type `T` that can be
    1044             :   /// written to at a later time to serialize the data into a `vector`
    1045             :   /// in the buffer.
    1046             :   template<typename T>
    1047             :   Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
    1048             :     AssertScalarT<T>();
    1049             :     return CreateUninitializedVector(len, sizeof(T),
    1050             :                                      reinterpret_cast<uint8_t **>(buf));
    1051             :   }
    1052             : 
    1053             :   template<typename T>
    1054             :   Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
    1055             :                                                                T **buf) {
    1056             :     return CreateUninitializedVector(len, sizeof(T),
    1057             :                                      reinterpret_cast<uint8_t **>(buf));
    1058             :   }
    1059             : 
    1060             :   // @brief Create a vector of scalar type T given as input a vector of scalar
    1061             :   // type U, useful with e.g. pre "enum class" enums, or any existing scalar
    1062             :   // data of the wrong type.
    1063             :   template<typename T, typename U>
    1064             :   Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
    1065             :     AssertScalarT<T>();
    1066             :     AssertScalarT<U>();
    1067             :     StartVector(len, sizeof(T));
    1068             :     for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
    1069             :     return Offset<Vector<T>>(EndVector(len));
    1070             :   }
    1071             : 
    1072             :   /// @brief Write a struct by itself, typically to be part of a union.
    1073             :   template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
    1074             :     NotNested();
    1075             :     Align(AlignOf<T>());
    1076             :     buf_.push_small(structobj);
    1077             :     return Offset<const T *>(GetSize());
    1078             :   }
    1079             : 
    1080             :   /// @brief Finish serializing a buffer by writing the root offset.
    1081             :   /// @param[in] file_identifier If a `file_identifier` is given, the buffer
    1082             :   /// will be prefixed with a standard FlatBuffers file header.
    1083             :   template<typename T>
    1084             :   void Finish(Offset<T> root, const char *file_identifier = nullptr) {
    1085             :     Finish(root.o, file_identifier, false);
    1086             :   }
    1087             : 
    1088             :   /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
    1089             :   /// buffer following the size field). These buffers are NOT compatible
    1090             :   /// with standard buffers created by Finish, i.e. you can't call GetRoot
    1091             :   /// on them, you have to use GetSizePrefixedRoot instead.
    1092             :   /// All >32 bit quantities in this buffer will be aligned when the whole
    1093             :   /// size pre-fixed buffer is aligned.
    1094             :   /// These kinds of buffers are useful for creating a stream of FlatBuffers.
    1095             :   template<typename T>
    1096         505 :   void FinishSizePrefixed(Offset<T> root,
    1097             :                           const char *file_identifier = nullptr) {
    1098         505 :     Finish(root.o, file_identifier, true);
    1099         505 :   }
    1100             : 
    1101             :   void SwapBufAllocator(FlatBufferBuilder &other) {
    1102             :     buf_.swap_allocator(other.buf_);
    1103             :   }
    1104             : 
    1105             :   /// @brief The length of a FlatBuffer file header.
    1106             :   static const size_t kFileIdentifierLength =
    1107             :       ::flatbuffers::kFileIdentifierLength;
    1108             : 
    1109             :  protected:
    1110             :   // You shouldn't really be copying instances of this class.
    1111             :   FlatBufferBuilder(const FlatBufferBuilder &);
    1112             :   FlatBufferBuilder &operator=(const FlatBufferBuilder &);
    1113             : 
    1114         505 :   void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
    1115         505 :     NotNested();
    1116         505 :     buf_.clear_scratch();
    1117             :     // This will cause the whole buffer to be aligned.
    1118        1010 :     PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
    1119         505 :                  (file_identifier ? kFileIdentifierLength : 0),
    1120             :              minalign_);
    1121         505 :     if (file_identifier) {
    1122           0 :       FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
    1123           0 :       PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
    1124             :                 kFileIdentifierLength);
    1125             :     }
    1126         505 :     PushElement(ReferTo(root));  // Location of root.
    1127         505 :     if (size_prefix) { PushElement(GetSize()); }
    1128         505 :     finished = true;
    1129         505 :   }
    1130             : 
    1131             :   struct FieldLoc {
    1132             :     uoffset_t off;
    1133             :     voffset_t id;
    1134             :   };
    1135             : 
    1136             :   vector_downward buf_;
    1137             : 
    1138             :   // Accumulating offsets of table members while it is being built.
    1139             :   // We store these in the scratch pad of buf_, after the vtable offsets.
    1140             :   uoffset_t num_field_loc;
    1141             :   // Track how much of the vtable is in use, so we can output the most compact
    1142             :   // possible vtable.
    1143             :   voffset_t max_voffset_;
    1144             : 
    1145             :   // Ensure objects are not nested.
    1146             :   bool nested;
    1147             : 
    1148             :   // Ensure the buffer is finished before it is being accessed.
    1149             :   bool finished;
    1150             : 
    1151             :   size_t minalign_;
    1152             : 
    1153             :   bool force_defaults_;  // Serialize values equal to their defaults anyway.
    1154             : 
    1155             :   bool dedup_vtables_;
    1156             : 
    1157             :   struct StringOffsetCompare {
    1158             :     StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
    1159             :     bool operator()(const Offset<String> &a, const Offset<String> &b) const {
    1160             :       auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
    1161             :       auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
    1162             :       return StringLessThan(stra->data(), stra->size(), strb->data(),
    1163             :                             strb->size());
    1164             :     }
    1165             :     const vector_downward *buf_;
    1166             :   };
    1167             : 
    1168             :   // For use with CreateSharedString. Instantiated on first use only.
    1169             :   typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
    1170             :   StringOffsetMap *string_pool;
    1171             : 
    1172             :  private:
    1173             :   // Allocates space for a vector of structures.
    1174             :   // Must be completed with EndVectorOfStructs().
    1175             :   template<typename T> T *StartVectorOfStructs(size_t vector_size) {
    1176             :     StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
    1177             :     return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
    1178             :   }
    1179             : 
    1180             :   // End the vector of structures in the flatbuffers.
    1181             :   // Vector should have previously be started with StartVectorOfStructs().
    1182             :   template<typename T>
    1183             :   Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
    1184             :     return Offset<Vector<const T *>>(EndVector(vector_size));
    1185             :   }
    1186             : };
    1187             : /// @}
    1188             : 
    1189             : /// Helpers to get a typed pointer to objects that are currently being built.
    1190             : /// @warning Creating new objects will lead to reallocations and invalidates
    1191             : /// the pointer!
    1192             : template<typename T>
    1193             : T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
    1194             :   return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
    1195             :                                offset.o);
    1196             : }
    1197             : 
    1198             : template<typename T>
    1199             : const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
    1200             :   return GetMutableTemporaryPointer<T>(fbb, offset);
    1201             : }
    1202             : 
    1203             : template<typename T>
    1204      131398 : void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
    1205      131398 :   auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
    1206      131398 :   bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
    1207             :   // If this fails, the caller will show what field needs to be set.
    1208      131398 :   FLATBUFFERS_ASSERT(ok);
    1209             :   (void)ok;
    1210      131398 : }
    1211             : 
    1212             : }  // namespace flatbuffers
    1213             : 
    1214             : #endif  // FLATBUFFERS_VECTOR_DOWNWARD_H_

Generated by: LCOV version 1.14