xref: /aosp_15_r20/prebuilts/android-emulator/linux-x86_64/include/flatbuffers/reflection.h (revision d870e0501505f2fc9999364ffe386a6b6151adc1)
1 /*
2  * Copyright 2015 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_REFLECTION_H_
18 #define FLATBUFFERS_REFLECTION_H_
19 
20 // This is somewhat of a circular dependency because flatc (and thus this
21 // file) is needed to generate this header in the first place.
22 // Should normally not be a problem since it can be generated by the
23 // previous version of flatc whenever this code needs to change.
24 // See scripts/generate_code.py for generation.
25 #include "flatbuffers/reflection_generated.h"
26 
27 // Helper functionality for reflection.
28 
29 namespace flatbuffers {
30 
31 // ------------------------- GETTERS -------------------------
32 
IsScalar(reflection::BaseType t)33 inline bool IsScalar(reflection::BaseType t) {
34   return t >= reflection::UType && t <= reflection::Double;
35 }
IsInteger(reflection::BaseType t)36 inline bool IsInteger(reflection::BaseType t) {
37   return t >= reflection::UType && t <= reflection::ULong;
38 }
IsFloat(reflection::BaseType t)39 inline bool IsFloat(reflection::BaseType t) {
40   return t == reflection::Float || t == reflection::Double;
41 }
IsLong(reflection::BaseType t)42 inline bool IsLong(reflection::BaseType t) {
43   return t == reflection::Long || t == reflection::ULong;
44 }
45 
46 // Size of a basic type, don't use with structs.
GetTypeSize(reflection::BaseType base_type)47 inline size_t GetTypeSize(reflection::BaseType base_type) {
48   // This needs to correspond to the BaseType enum.
49   static size_t sizes[] = {
50     0,  // None
51     1,  // UType
52     1,  // Bool
53     1,  // Byte
54     1,  // UByte
55     2,  // Short
56     2,  // UShort
57     4,  // Int
58     4,  // UInt
59     8,  // Long
60     8,  // ULong
61     4,  // Float
62     8,  // Double
63     4,  // String
64     4,  // Vector
65     4,  // Obj
66     4,  // Union
67     0,  // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
68         // errors.
69 
70     0  // MaxBaseType. This must be kept the last entry in this array.
71   };
72   static_assert(sizeof(sizes) / sizeof(size_t) == reflection::MaxBaseType + 1,
73                 "Size of sizes[] array does not match the count of BaseType "
74                 "enum values.");
75   return sizes[base_type];
76 }
77 
78 // Same as above, but now correctly returns the size of a struct if
79 // the field (or vector element) is a struct.
GetTypeSizeInline(reflection::BaseType base_type,int type_index,const reflection::Schema & schema)80 inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
81                                 const reflection::Schema &schema) {
82   if (base_type == reflection::Obj &&
83       schema.objects()->Get(type_index)->is_struct()) {
84     return schema.objects()->Get(type_index)->bytesize();
85   } else {
86     return GetTypeSize(base_type);
87   }
88 }
89 
90 // Get the root, regardless of what type it is.
GetAnyRoot(uint8_t * const flatbuf)91 inline Table *GetAnyRoot(uint8_t *const flatbuf) {
92   return GetMutableRoot<Table>(flatbuf);
93 }
94 
GetAnyRoot(const uint8_t * const flatbuf)95 inline const Table *GetAnyRoot(const uint8_t *const flatbuf) {
96   return GetRoot<Table>(flatbuf);
97 }
98 
GetAnySizePrefixedRoot(uint8_t * const flatbuf)99 inline Table *GetAnySizePrefixedRoot(uint8_t *const flatbuf) {
100   return GetMutableSizePrefixedRoot<Table>(flatbuf);
101 }
102 
GetAnySizePrefixedRoot(const uint8_t * const flatbuf)103 inline const Table *GetAnySizePrefixedRoot(const uint8_t *const flatbuf) {
104   return GetSizePrefixedRoot<Table>(flatbuf);
105 }
106 
107 // Get a field's default, if you know it's an integer, and its exact type.
GetFieldDefaultI(const reflection::Field & field)108 template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
109   FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
110   return static_cast<T>(field.default_integer());
111 }
112 
113 // Get a field's default, if you know it's floating point and its exact type.
GetFieldDefaultF(const reflection::Field & field)114 template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
115   FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
116   return static_cast<T>(field.default_real());
117 }
118 
119 // Get a field, if you know it's an integer, and its exact type.
120 template<typename T>
GetFieldI(const Table & table,const reflection::Field & field)121 T GetFieldI(const Table &table, const reflection::Field &field) {
122   FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
123   return table.GetField<T>(field.offset(),
124                            static_cast<T>(field.default_integer()));
125 }
126 
127 // Get a field, if you know it's floating point and its exact type.
128 template<typename T>
GetFieldF(const Table & table,const reflection::Field & field)129 T GetFieldF(const Table &table, const reflection::Field &field) {
130   FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
131   return table.GetField<T>(field.offset(),
132                            static_cast<T>(field.default_real()));
133 }
134 
135 // Get a field, if you know it's a string.
GetFieldS(const Table & table,const reflection::Field & field)136 inline const String *GetFieldS(const Table &table,
137                                const reflection::Field &field) {
138   FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
139   return table.GetPointer<const String *>(field.offset());
140 }
141 
142 // Get a field, if you know it's a vector.
143 template<typename T>
GetFieldV(const Table & table,const reflection::Field & field)144 Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
145   FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector &&
146                      sizeof(T) == GetTypeSize(field.type()->element()));
147   return table.GetPointer<Vector<T> *>(field.offset());
148 }
149 
150 // Get a field, if you know it's a vector, generically.
151 // To actually access elements, use the return value together with
152 // field.type()->element() in any of GetAnyVectorElemI below etc.
GetFieldAnyV(const Table & table,const reflection::Field & field)153 inline VectorOfAny *GetFieldAnyV(const Table &table,
154                                  const reflection::Field &field) {
155   return table.GetPointer<VectorOfAny *>(field.offset());
156 }
157 
158 // Get a field, if you know it's a table.
GetFieldT(const Table & table,const reflection::Field & field)159 inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
160   FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj ||
161                      field.type()->base_type() == reflection::Union);
162   return table.GetPointer<Table *>(field.offset());
163 }
164 
165 // Get a field, if you know it's a struct.
GetFieldStruct(const Table & table,const reflection::Field & field)166 inline const Struct *GetFieldStruct(const Table &table,
167                                     const reflection::Field &field) {
168   // TODO: This does NOT check if the field is a table or struct, but we'd need
169   // access to the schema to check the is_struct flag.
170   FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
171   return table.GetStruct<const Struct *>(field.offset());
172 }
173 
174 // Get a structure's field, if you know it's a struct.
GetFieldStruct(const Struct & structure,const reflection::Field & field)175 inline const Struct *GetFieldStruct(const Struct &structure,
176                                     const reflection::Field &field) {
177   FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
178   return structure.GetStruct<const Struct *>(field.offset());
179 }
180 
181 // Raw helper functions used below: get any value in memory as a 64bit int, a
182 // double or a string.
183 // All scalars get static_cast to an int64_t, strings use strtoull, every other
184 // data type returns 0.
185 int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data);
186 // All scalars static cast to double, strings use strtod, every other data
187 // type is 0.0.
188 double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
189 // All scalars converted using stringstream, strings as-is, and all other
190 // data types provide some level of debug-pretty-printing.
191 std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
192                          const reflection::Schema *schema, int type_index);
193 
194 // Get any table field as a 64bit int, regardless of what type it is.
GetAnyFieldI(const Table & table,const reflection::Field & field)195 inline int64_t GetAnyFieldI(const Table &table,
196                             const reflection::Field &field) {
197   auto field_ptr = table.GetAddressOf(field.offset());
198   return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr)
199                    : field.default_integer();
200 }
201 
202 // Get any table field as a double, regardless of what type it is.
GetAnyFieldF(const Table & table,const reflection::Field & field)203 inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
204   auto field_ptr = table.GetAddressOf(field.offset());
205   return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
206                    : field.default_real();
207 }
208 
209 // Get any table field as a string, regardless of what type it is.
210 // You may pass nullptr for the schema if you don't care to have fields that
211 // are of table type pretty-printed.
GetAnyFieldS(const Table & table,const reflection::Field & field,const reflection::Schema * schema)212 inline std::string GetAnyFieldS(const Table &table,
213                                 const reflection::Field &field,
214                                 const reflection::Schema *schema) {
215   auto field_ptr = table.GetAddressOf(field.offset());
216   return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema,
217                                   field.type()->index())
218                    : "";
219 }
220 
221 // Get any struct field as a 64bit int, regardless of what type it is.
GetAnyFieldI(const Struct & st,const reflection::Field & field)222 inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
223   return GetAnyValueI(field.type()->base_type(),
224                       st.GetAddressOf(field.offset()));
225 }
226 
227 // Get any struct field as a double, regardless of what type it is.
GetAnyFieldF(const Struct & st,const reflection::Field & field)228 inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
229   return GetAnyValueF(field.type()->base_type(),
230                       st.GetAddressOf(field.offset()));
231 }
232 
233 // Get any struct field as a string, regardless of what type it is.
GetAnyFieldS(const Struct & st,const reflection::Field & field)234 inline std::string GetAnyFieldS(const Struct &st,
235                                 const reflection::Field &field) {
236   return GetAnyValueS(field.type()->base_type(),
237                       st.GetAddressOf(field.offset()), nullptr, -1);
238 }
239 
240 // Get any vector element as a 64bit int, regardless of what type it is.
GetAnyVectorElemI(const VectorOfAny * vec,reflection::BaseType elem_type,size_t i)241 inline int64_t GetAnyVectorElemI(const VectorOfAny *vec,
242                                  reflection::BaseType elem_type, size_t i) {
243   return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
244 }
245 
246 // Get any vector element as a double, regardless of what type it is.
GetAnyVectorElemF(const VectorOfAny * vec,reflection::BaseType elem_type,size_t i)247 inline double GetAnyVectorElemF(const VectorOfAny *vec,
248                                 reflection::BaseType elem_type, size_t i) {
249   return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
250 }
251 
252 // Get any vector element as a string, regardless of what type it is.
GetAnyVectorElemS(const VectorOfAny * vec,reflection::BaseType elem_type,size_t i)253 inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
254                                      reflection::BaseType elem_type, size_t i) {
255   return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i,
256                       nullptr, -1);
257 }
258 
259 // Get a vector element that's a table/string/vector from a generic vector.
260 // Pass Table/String/VectorOfAny as template parameter.
261 // Warning: does no typechecking.
262 template<typename T>
GetAnyVectorElemPointer(const VectorOfAny * vec,size_t i)263 T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
264   auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
265   return reinterpret_cast<T *>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
266 }
267 
268 // Get the inline-address of a vector element. Useful for Structs (pass Struct
269 // as template arg), or being able to address a range of scalars in-line.
270 // Get elem_size from GetTypeSizeInline().
271 // Note: little-endian data on all platforms, use EndianScalar() instead of
272 // raw pointer access with scalars).
273 template<typename T>
GetAnyVectorElemAddressOf(const VectorOfAny * vec,size_t i,size_t elem_size)274 T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
275                              size_t elem_size) {
276   return reinterpret_cast<T *>(vec->Data() + elem_size * i);
277 }
278 
279 // Similarly, for elements of tables.
280 template<typename T>
GetAnyFieldAddressOf(const Table & table,const reflection::Field & field)281 T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
282   return reinterpret_cast<T *>(table.GetAddressOf(field.offset()));
283 }
284 
285 // Similarly, for elements of structs.
286 template<typename T>
GetAnyFieldAddressOf(const Struct & st,const reflection::Field & field)287 T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
288   return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
289 }
290 
291 // Loop over all the fields of the provided `object` and call `func` on each one
292 // in increasing order by their field->id(). If `reverse` is true, `func` is
293 // called in descending order
294 void ForAllFields(const reflection::Object *object, bool reverse,
295                   std::function<void(const reflection::Field *)> func);
296 
297 // ------------------------- SETTERS -------------------------
298 
299 // Set any scalar field, if you know its exact type.
300 template<typename T>
SetField(Table * table,const reflection::Field & field,T val)301 bool SetField(Table *table, const reflection::Field &field, T val) {
302   reflection::BaseType type = field.type()->base_type();
303   if (!IsScalar(type)) { return false; }
304   FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
305   T def;
306   if (IsInteger(type)) {
307     def = GetFieldDefaultI<T>(field);
308   } else {
309     FLATBUFFERS_ASSERT(IsFloat(type));
310     def = GetFieldDefaultF<T>(field);
311   }
312   return table->SetField(field.offset(), val, def);
313 }
314 
315 // Raw helper functions used below: set any value in memory as a 64bit int, a
316 // double or a string.
317 // These work for all scalar values, but do nothing for other data types.
318 // To set a string, see SetString below.
319 void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val);
320 void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val);
321 void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
322 
323 // Set any table field as a 64bit int, regardless of type what it is.
SetAnyFieldI(Table * table,const reflection::Field & field,int64_t val)324 inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
325                          int64_t val) {
326   auto field_ptr = table->GetAddressOf(field.offset());
327   if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
328   SetAnyValueI(field.type()->base_type(), field_ptr, val);
329   return true;
330 }
331 
332 // Set any table field as a double, regardless of what type it is.
SetAnyFieldF(Table * table,const reflection::Field & field,double val)333 inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
334                          double val) {
335   auto field_ptr = table->GetAddressOf(field.offset());
336   if (!field_ptr) return val == GetFieldDefaultF<double>(field);
337   SetAnyValueF(field.type()->base_type(), field_ptr, val);
338   return true;
339 }
340 
341 // Set any table field as a string, regardless of what type it is.
SetAnyFieldS(Table * table,const reflection::Field & field,const char * val)342 inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
343                          const char *val) {
344   auto field_ptr = table->GetAddressOf(field.offset());
345   if (!field_ptr) return false;
346   SetAnyValueS(field.type()->base_type(), field_ptr, val);
347   return true;
348 }
349 
350 // Set any struct field as a 64bit int, regardless of type what it is.
SetAnyFieldI(Struct * st,const reflection::Field & field,int64_t val)351 inline void SetAnyFieldI(Struct *st, const reflection::Field &field,
352                          int64_t val) {
353   SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()),
354                val);
355 }
356 
357 // Set any struct field as a double, regardless of type what it is.
SetAnyFieldF(Struct * st,const reflection::Field & field,double val)358 inline void SetAnyFieldF(Struct *st, const reflection::Field &field,
359                          double val) {
360   SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()),
361                val);
362 }
363 
364 // Set any struct field as a string, regardless of type what it is.
SetAnyFieldS(Struct * st,const reflection::Field & field,const char * val)365 inline void SetAnyFieldS(Struct *st, const reflection::Field &field,
366                          const char *val) {
367   SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()),
368                val);
369 }
370 
371 // Set any vector element as a 64bit int, regardless of type what it is.
SetAnyVectorElemI(VectorOfAny * vec,reflection::BaseType elem_type,size_t i,int64_t val)372 inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type,
373                               size_t i, int64_t val) {
374   SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
375 }
376 
377 // Set any vector element as a double, regardless of type what it is.
SetAnyVectorElemF(VectorOfAny * vec,reflection::BaseType elem_type,size_t i,double val)378 inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type,
379                               size_t i, double val) {
380   SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
381 }
382 
383 // Set any vector element as a string, regardless of type what it is.
SetAnyVectorElemS(VectorOfAny * vec,reflection::BaseType elem_type,size_t i,const char * val)384 inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
385                               size_t i, const char *val) {
386   SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
387 }
388 
389 // ------------------------- RESIZING SETTERS -------------------------
390 
391 // "smart" pointer for use with resizing vectors: turns a pointer inside
392 // a vector into a relative offset, such that it is not affected by resizes.
393 template<typename T, typename U> class pointer_inside_vector {
394  public:
pointer_inside_vector(T * ptr,std::vector<U> & vec)395   pointer_inside_vector(T *ptr, std::vector<U> &vec)
396       : offset_(reinterpret_cast<uint8_t *>(ptr) -
397                 reinterpret_cast<uint8_t *>(vec.data())),
398         vec_(vec) {}
399 
400   T *operator*() const {
401     return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(vec_.data()) +
402                                  offset_);
403   }
404   T *operator->() const { return operator*(); }
405 
406  private:
407   size_t offset_;
408   std::vector<U> &vec_;
409 };
410 
411 // Helper to create the above easily without specifying template args.
412 template<typename T, typename U>
piv(T * ptr,std::vector<U> & vec)413 pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
414   return pointer_inside_vector<T, U>(ptr, vec);
415 }
416 
UnionTypeFieldSuffix()417 inline const char *UnionTypeFieldSuffix() { return "_type"; }
418 
419 // Helper to figure out the actual table type a union refers to.
GetUnionType(const reflection::Schema & schema,const reflection::Object & parent,const reflection::Field & unionfield,const Table & table)420 inline const reflection::Object &GetUnionType(
421     const reflection::Schema &schema, const reflection::Object &parent,
422     const reflection::Field &unionfield, const Table &table) {
423   auto enumdef = schema.enums()->Get(unionfield.type()->index());
424   // TODO: this is clumsy and slow, but no other way to find it?
425   auto type_field = parent.fields()->LookupByKey(
426       (unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
427   FLATBUFFERS_ASSERT(type_field);
428   auto union_type = GetFieldI<uint8_t>(table, *type_field);
429   auto enumval = enumdef->values()->LookupByKey(union_type);
430   return *schema.objects()->Get(enumval->union_type()->index());
431 }
432 
433 // Changes the contents of a string inside a FlatBuffer. FlatBuffer must
434 // live inside a std::vector so we can resize the buffer if needed.
435 // "str" must live inside "flatbuf" and may be invalidated after this call.
436 // If your FlatBuffer's root table is not the schema's root table, you should
437 // pass in your root_table type as well.
438 void SetString(const reflection::Schema &schema, const std::string &val,
439                const String *str, std::vector<uint8_t> *flatbuf,
440                const reflection::Object *root_table = nullptr);
441 
442 // Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
443 // live inside a std::vector so we can resize the buffer if needed.
444 // "vec" must live inside "flatbuf" and may be invalidated after this call.
445 // If your FlatBuffer's root table is not the schema's root table, you should
446 // pass in your root_table type as well.
447 uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
448                          const VectorOfAny *vec, uoffset_t num_elems,
449                          uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
450                          const reflection::Object *root_table = nullptr);
451 
452 template<typename T>
453 void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
454                   const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
455                   const reflection::Object *root_table = nullptr) {
456   auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
457   auto newelems = ResizeAnyVector(
458       schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
459       static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
460   // Set new elements to "val".
461   for (int i = 0; i < delta_elem; i++) {
462     auto loc = newelems + i * sizeof(T);
463     auto is_scalar = flatbuffers::is_scalar<T>::value;
464     if (is_scalar) {
465       WriteScalar(loc, val);
466     } else {  // struct
467       *reinterpret_cast<T *>(loc) = val;
468     }
469   }
470 }
471 
472 // Adds any new data (in the form of a new FlatBuffer) to an existing
473 // FlatBuffer. This can be used when any of the above methods are not
474 // sufficient, in particular for adding new tables and new fields.
475 // This is potentially slightly less efficient than a FlatBuffer constructed
476 // in one piece, since the new FlatBuffer doesn't share any vtables with the
477 // existing one.
478 // The return value can now be set using Vector::MutateOffset or SetFieldT
479 // below.
480 const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
481                              const uint8_t *newbuf, size_t newlen);
482 
SetFieldT(Table * table,const reflection::Field & field,const uint8_t * val)483 inline bool SetFieldT(Table *table, const reflection::Field &field,
484                       const uint8_t *val) {
485   FLATBUFFERS_ASSERT(sizeof(uoffset_t) ==
486                      GetTypeSize(field.type()->base_type()));
487   return table->SetPointer(field.offset(), val);
488 }
489 
490 // ------------------------- COPYING -------------------------
491 
492 // Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
493 // Can be used to do any kind of merging/selecting you may want to do out
494 // of existing buffers. Also useful to reconstruct a whole buffer if the
495 // above resizing functionality has introduced garbage in a buffer you want
496 // to remove.
497 // Note: this does not deal with DAGs correctly. If the table passed forms a
498 // DAG, the copy will be a tree instead (with duplicates). Strings can be
499 // shared however, by passing true for use_string_pooling.
500 
501 Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
502                                 const reflection::Schema &schema,
503                                 const reflection::Object &objectdef,
504                                 const Table &table,
505                                 bool use_string_pooling = false);
506 
507 // Verifies the provided flatbuffer using reflection.
508 // root should point to the root type for this flatbuffer.
509 // buf should point to the start of flatbuffer data.
510 // length specifies the size of the flatbuffer data.
511 bool Verify(const reflection::Schema &schema, const reflection::Object &root,
512             const uint8_t *buf, size_t length, uoffset_t max_depth = 64,
513             uoffset_t max_tables = 1000000);
514 
515 bool VerifySizePrefixed(const reflection::Schema &schema,
516                         const reflection::Object &root, const uint8_t *buf,
517                         size_t length, uoffset_t max_depth = 64,
518                         uoffset_t max_tables = 1000000);
519 
520 }  // namespace flatbuffers
521 
522 #endif  // FLATBUFFERS_REFLECTION_H_
523