flatbuffer_builder.h 48 KB

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