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