Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / onert-micro / externals / flatbuffers / minireflect.h
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
3  * Copyright 2017 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_MINIREFLECT_H_
19 #define FLATBUFFERS_MINIREFLECT_H_
20
21 #include "flatbuffers/flatbuffers.h"
22 #include "flatbuffers/util.h"
23
24 namespace flatbuffers
25 {
26
27 // Utilities that can be used with the "mini reflection" tables present
28 // in generated code with --reflect-types (only types) or --reflect-names
29 // (also names).
30 // This allows basic reflection functionality such as pretty-printing
31 // that does not require the use of the schema parser or loading of binary
32 // schema files at runtime (reflection.h).
33
34 // For any of the functions below that take `const TypeTable *`, you pass
35 // `FooTypeTable()` if the type of the root is `Foo`.
36
37 // First, a generic iterator that can be used by multiple algorithms.
38
39 struct IterationVisitor
40 {
41   // These mark the scope of a table or struct.
42   virtual void StartSequence() {}
43   virtual void EndSequence() {}
44   // Called for each field regardless of whether it is present or not.
45   // If not present, val == nullptr. set_idx is the index of all set fields.
46   virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/, ElementaryType /*type*/,
47                      bool /*is_vector*/, const TypeTable * /*type_table*/, const char * /*name*/,
48                      const uint8_t * /*val*/)
49   {
50   }
51   // Called for a value that is actually present, after a field, or as part
52   // of a vector.
53   virtual void UType(uint8_t, const char *) {}
54   virtual void Bool(bool) {}
55   virtual void Char(int8_t, const char *) {}
56   virtual void UChar(uint8_t, const char *) {}
57   virtual void Short(int16_t, const char *) {}
58   virtual void UShort(uint16_t, const char *) {}
59   virtual void Int(int32_t, const char *) {}
60   virtual void UInt(uint32_t, const char *) {}
61   virtual void Long(int64_t) {}
62   virtual void ULong(uint64_t) {}
63   virtual void Float(float) {}
64   virtual void Double(double) {}
65   virtual void String(const String *) {}
66   virtual void Unknown(const uint8_t *) {} // From a future version.
67   // These mark the scope of a vector.
68   virtual void StartVector() {}
69   virtual void EndVector() {}
70   virtual void Element(size_t /*i*/, ElementaryType /*type*/, const TypeTable * /*type_table*/,
71                        const uint8_t * /*val*/)
72   {
73   }
74   virtual ~IterationVisitor() {}
75 };
76
77 inline size_t InlineSize(ElementaryType type, const TypeTable *type_table)
78 {
79   switch (type)
80   {
81     case ET_UTYPE:
82     case ET_BOOL:
83     case ET_CHAR:
84     case ET_UCHAR:
85       return 1;
86     case ET_SHORT:
87     case ET_USHORT:
88       return 2;
89     case ET_INT:
90     case ET_UINT:
91     case ET_FLOAT:
92     case ET_STRING:
93       return 4;
94     case ET_LONG:
95     case ET_ULONG:
96     case ET_DOUBLE:
97       return 8;
98     case ET_SEQUENCE:
99       switch (type_table->st)
100       {
101         case ST_TABLE:
102         case ST_UNION:
103           return 4;
104         case ST_STRUCT:
105           return static_cast<size_t>(type_table->values[type_table->num_elems]);
106         default:
107           FLATBUFFERS_ASSERT(false);
108           return 1;
109       }
110     default:
111       FLATBUFFERS_ASSERT(false);
112       return 1;
113   }
114 }
115
116 inline int64_t LookupEnum(int64_t enum_val, const int64_t *values, size_t num_values)
117 {
118   if (!values)
119     return enum_val;
120   for (size_t i = 0; i < num_values; i++)
121   {
122     if (enum_val == values[i])
123       return static_cast<int64_t>(i);
124   }
125   return -1; // Unknown enum value.
126 }
127
128 template <typename T> const char *EnumName(T tval, const TypeTable *type_table)
129 {
130   if (!type_table || !type_table->names)
131     return nullptr;
132   auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values, type_table->num_elems);
133   if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems))
134   {
135     return type_table->names[i];
136   }
137   return nullptr;
138 }
139
140 void IterateObject(const uint8_t *obj, const TypeTable *type_table, IterationVisitor *visitor);
141
142 inline void IterateValue(ElementaryType type, const uint8_t *val, const TypeTable *type_table,
143                          const uint8_t *prev_val, soffset_t vector_index, IterationVisitor *visitor)
144 {
145   switch (type)
146   {
147     case ET_UTYPE:
148     {
149       auto tval = ReadScalar<uint8_t>(val);
150       visitor->UType(tval, EnumName(tval, type_table));
151       break;
152     }
153     case ET_BOOL:
154     {
155       visitor->Bool(ReadScalar<uint8_t>(val) != 0);
156       break;
157     }
158     case ET_CHAR:
159     {
160       auto tval = ReadScalar<int8_t>(val);
161       visitor->Char(tval, EnumName(tval, type_table));
162       break;
163     }
164     case ET_UCHAR:
165     {
166       auto tval = ReadScalar<uint8_t>(val);
167       visitor->UChar(tval, EnumName(tval, type_table));
168       break;
169     }
170     case ET_SHORT:
171     {
172       auto tval = ReadScalar<int16_t>(val);
173       visitor->Short(tval, EnumName(tval, type_table));
174       break;
175     }
176     case ET_USHORT:
177     {
178       auto tval = ReadScalar<uint16_t>(val);
179       visitor->UShort(tval, EnumName(tval, type_table));
180       break;
181     }
182     case ET_INT:
183     {
184       auto tval = ReadScalar<int32_t>(val);
185       visitor->Int(tval, EnumName(tval, type_table));
186       break;
187     }
188     case ET_UINT:
189     {
190       auto tval = ReadScalar<uint32_t>(val);
191       visitor->UInt(tval, EnumName(tval, type_table));
192       break;
193     }
194     case ET_LONG:
195     {
196       visitor->Long(ReadScalar<int64_t>(val));
197       break;
198     }
199     case ET_ULONG:
200     {
201       visitor->ULong(ReadScalar<uint64_t>(val));
202       break;
203     }
204     case ET_FLOAT:
205     {
206       visitor->Float(ReadScalar<float>(val));
207       break;
208     }
209     case ET_DOUBLE:
210     {
211       visitor->Double(ReadScalar<double>(val));
212       break;
213     }
214     case ET_STRING:
215     {
216       val += ReadScalar<uoffset_t>(val);
217       visitor->String(reinterpret_cast<const String *>(val));
218       break;
219     }
220     case ET_SEQUENCE:
221     {
222       switch (type_table->st)
223       {
224         case ST_TABLE:
225           val += ReadScalar<uoffset_t>(val);
226           IterateObject(val, type_table, visitor);
227           break;
228         case ST_STRUCT:
229           IterateObject(val, type_table, visitor);
230           break;
231         case ST_UNION:
232         {
233           val += ReadScalar<uoffset_t>(val);
234           FLATBUFFERS_ASSERT(prev_val);
235           auto union_type = *prev_val; // Always a uint8_t.
236           if (vector_index >= 0)
237           {
238             auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
239             union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
240           }
241           auto type_code_idx = LookupEnum(union_type, type_table->values, type_table->num_elems);
242           if (type_code_idx >= 0 && type_code_idx < static_cast<int32_t>(type_table->num_elems))
243           {
244             auto type_code = type_table->type_codes[type_code_idx];
245             switch (type_code.base_type)
246             {
247               case ET_SEQUENCE:
248               {
249                 auto ref = type_table->type_refs[type_code.sequence_ref]();
250                 IterateObject(val, ref, visitor);
251                 break;
252               }
253               case ET_STRING:
254                 visitor->String(reinterpret_cast<const String *>(val));
255                 break;
256               default:
257                 visitor->Unknown(val);
258             }
259           }
260           else
261           {
262             visitor->Unknown(val);
263           }
264           break;
265         }
266         case ST_ENUM:
267           FLATBUFFERS_ASSERT(false);
268           break;
269       }
270       break;
271     }
272     default:
273     {
274       visitor->Unknown(val);
275       break;
276     }
277   }
278 }
279
280 inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
281                           IterationVisitor *visitor)
282 {
283   visitor->StartSequence();
284   const uint8_t *prev_val = nullptr;
285   size_t set_idx = 0;
286   size_t array_idx = 0;
287   for (size_t i = 0; i < type_table->num_elems; i++)
288   {
289     auto type_code = type_table->type_codes[i];
290     auto type = static_cast<ElementaryType>(type_code.base_type);
291     auto is_repeating = type_code.is_repeating != 0;
292     auto ref_idx = type_code.sequence_ref;
293     const TypeTable *ref = nullptr;
294     if (ref_idx >= 0)
295     {
296       ref = type_table->type_refs[ref_idx]();
297     }
298     auto name = type_table->names ? type_table->names[i] : nullptr;
299     const uint8_t *val = nullptr;
300     if (type_table->st == ST_TABLE)
301     {
302       val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
303         FieldIndexToOffset(static_cast<voffset_t>(i)));
304     }
305     else
306     {
307       val = obj + type_table->values[i];
308     }
309     visitor->Field(i, set_idx, type, is_repeating, ref, name, val);
310     if (val)
311     {
312       set_idx++;
313       if (is_repeating)
314       {
315         auto elem_ptr = val;
316         size_t size = 0;
317         if (type_table->st == ST_TABLE)
318         {
319           // variable length vector
320           val += ReadScalar<uoffset_t>(val);
321           auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
322           elem_ptr = vec->Data();
323           size = vec->size();
324         }
325         else
326         {
327           // otherwise fixed size array
328           size = type_table->array_sizes[array_idx];
329           ++array_idx;
330         }
331         visitor->StartVector();
332         for (size_t j = 0; j < size; j++)
333         {
334           visitor->Element(j, type, ref, elem_ptr);
335           IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j), visitor);
336           elem_ptr += InlineSize(type, ref);
337         }
338         visitor->EndVector();
339       }
340       else
341       {
342         IterateValue(type, val, ref, prev_val, -1, visitor);
343       }
344     }
345     prev_val = val;
346   }
347   visitor->EndSequence();
348 }
349
350 inline void IterateFlatBuffer(const uint8_t *buffer, const TypeTable *type_table,
351                               IterationVisitor *callback)
352 {
353   IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
354 }
355
356 // Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
357 // the output generated by idl_gen_text.cpp.
358
359 struct ToStringVisitor : public IterationVisitor
360 {
361   std::string s;
362   std::string d;
363   bool q;
364   std::string in;
365   size_t indent_level;
366   bool vector_delimited;
367   ToStringVisitor(std::string delimiter, bool quotes, std::string indent, bool vdelimited = true)
368     : d(delimiter), q(quotes), in(indent), indent_level(0), vector_delimited(vdelimited)
369   {
370   }
371   ToStringVisitor(std::string delimiter)
372     : d(delimiter), q(false), in(""), indent_level(0), vector_delimited(true)
373   {
374   }
375
376   void append_indent()
377   {
378     for (size_t i = 0; i < indent_level; i++)
379     {
380       s += in;
381     }
382   }
383
384   void StartSequence()
385   {
386     s += "{";
387     s += d;
388     indent_level++;
389   }
390   void EndSequence()
391   {
392     s += d;
393     indent_level--;
394     append_indent();
395     s += "}";
396   }
397   void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/, bool /*is_vector*/,
398              const TypeTable * /*type_table*/, const char *name, const uint8_t *val)
399   {
400     if (!val)
401       return;
402     if (set_idx)
403     {
404       s += ",";
405       s += d;
406     }
407     append_indent();
408     if (name)
409     {
410       if (q)
411         s += "\"";
412       s += name;
413       if (q)
414         s += "\"";
415       s += ": ";
416     }
417   }
418   template <typename T> void Named(T x, const char *name)
419   {
420     if (name)
421     {
422       if (q)
423         s += "\"";
424       s += name;
425       if (q)
426         s += "\"";
427     }
428     else
429     {
430       s += NumToString(x);
431     }
432   }
433   void UType(uint8_t x, const char *name) { Named(x, name); }
434   void Bool(bool x) { s += x ? "true" : "false"; }
435   void Char(int8_t x, const char *name) { Named(x, name); }
436   void UChar(uint8_t x, const char *name) { Named(x, name); }
437   void Short(int16_t x, const char *name) { Named(x, name); }
438   void UShort(uint16_t x, const char *name) { Named(x, name); }
439   void Int(int32_t x, const char *name) { Named(x, name); }
440   void UInt(uint32_t x, const char *name) { Named(x, name); }
441   void Long(int64_t x) { s += NumToString(x); }
442   void ULong(uint64_t x) { s += NumToString(x); }
443   void Float(float x) { s += NumToString(x); }
444   void Double(double x) { s += NumToString(x); }
445   void String(const struct String *str)
446   {
447     EscapeString(str->c_str(), str->size(), &s, true, false);
448   }
449   void Unknown(const uint8_t *) { s += "(?)"; }
450   void StartVector()
451   {
452     s += "[";
453     if (vector_delimited)
454     {
455       s += d;
456       indent_level++;
457       append_indent();
458     }
459     else
460     {
461       s += " ";
462     }
463   }
464   void EndVector()
465   {
466     if (vector_delimited)
467     {
468       s += d;
469       indent_level--;
470       append_indent();
471     }
472     else
473     {
474       s += " ";
475     }
476     s += "]";
477   }
478   void Element(size_t i, ElementaryType /*type*/, const TypeTable * /*type_table*/,
479                const uint8_t * /*val*/)
480   {
481     if (i)
482     {
483       s += ",";
484       if (vector_delimited)
485       {
486         s += d;
487         append_indent();
488       }
489       else
490       {
491         s += " ";
492       }
493     }
494   }
495 };
496
497 inline std::string FlatBufferToString(const uint8_t *buffer, const TypeTable *type_table,
498                                       bool multi_line = false, bool vector_delimited = true)
499 {
500   ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "", vector_delimited);
501   IterateFlatBuffer(buffer, type_table, &tostring_visitor);
502   return tostring_visitor.s;
503 }
504
505 } // namespace flatbuffers
506
507 #endif // FLATBUFFERS_MINIREFLECT_H_