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