• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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_IDL_H_
18 #define FLATBUFFERS_IDL_H_
19 
20 #include <algorithm>
21 #include <functional>
22 #include <map>
23 #include <memory>
24 #include <stack>
25 #include <vector>
26 
27 #include "flatbuffers/base.h"
28 #include "flatbuffers/flatbuffers.h"
29 #include "flatbuffers/flexbuffers.h"
30 #include "flatbuffers/hash.h"
31 #include "flatbuffers/reflection.h"
32 
33 // This file defines the data types representing a parsed IDL (Interface
34 // Definition Language) / schema file.
35 
36 // Limits maximum depth of nested objects.
37 // Prevents stack overflow while parse scheme, or json, or flexbuffer.
38 #if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
39 #  define FLATBUFFERS_MAX_PARSING_DEPTH 64
40 #endif
41 
42 namespace flatbuffers {
43 
44 // The order of these matters for Is*() functions below.
45 // Additionally, Parser::ParseType assumes bool..string is a contiguous range
46 // of type tokens.
47 // clang-format off
48 #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
49   TD(NONE,     "",       uint8_t,  byte,   byte,    byte,   uint8,   u8,   UByte, UInt8, 0) \
50   TD(UTYPE,    "",       uint8_t,  byte,   byte,    byte,   uint8,   u8,   UByte, UInt8, 1) /* begin scalar/int */ \
51   TD(BOOL,     "bool",   uint8_t,  boolean,bool,    bool,   bool,    bool, Boolean, Bool, 2) \
52   TD(CHAR,     "byte",   int8_t,   byte,   int8,    sbyte,  int8,    i8,   Byte, Int8, 3) \
53   TD(UCHAR,    "ubyte",  uint8_t,  byte,   byte,    byte,   uint8,   u8,   UByte, UInt8, 4) \
54   TD(SHORT,    "short",  int16_t,  short,  int16,   short,  int16,   i16,  Short, Int16, 5) \
55   TD(USHORT,   "ushort", uint16_t, short,  uint16,  ushort, uint16,  u16,  UShort, UInt16, 6) \
56   TD(INT,      "int",    int32_t,  int,    int32,   int,    int32,   i32,  Int, Int32, 7) \
57   TD(UINT,     "uint",   uint32_t, int,    uint32,  uint,   uint32,  u32,  UInt, UInt32, 8) \
58   TD(LONG,     "long",   int64_t,  long,   int64,   long,   int64,   i64,  Long, Int64, 9) \
59   TD(ULONG,    "ulong",  uint64_t, long,   uint64,  ulong,  uint64,  u64,  ULong, UInt64, 10) /* end int */ \
60   TD(FLOAT,    "float",  float,    float,  float32, float,  float32, f32,  Float, Float32, 11) /* begin float */ \
61   TD(DOUBLE,   "double", double,   double, float64, double, float64, f64,  Double, Double, 12) /* end float/scalar */
62 #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
63   TD(STRING,   "string", Offset<void>,   int, int, StringOffset, int, unused, Int, Offset<String>, 13) \
64   TD(VECTOR,   "",       Offset<void>,   int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 14) \
65   TD(VECTOR64, "",       Offset64<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 18) \
66   TD(STRUCT,   "",       Offset<void>,   int, int, int,          int, unused, Int, Offset<UOffset>, 15) \
67   TD(UNION,    "",       Offset<void>,   int, int, int,          int, unused, Int, Offset<UOffset>, 16)
68 #define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
69   TD(ARRAY,    "",       int,            int, int, int,          int, unused, Int, Offset<UOffset>, 17)
70 // The fields are:
71 // - enum
72 // - FlatBuffers schema type.
73 // - C++ type.
74 // - Java type.
75 // - Go type.
76 // - C# / .Net type.
77 // - Python type.
78 // - Kotlin type.
79 // - Rust type.
80 // - Swift type.
81 // - enum value (matches the reflected values)
82 
83 // using these macros, we can now write code dealing with types just once, e.g.
84 
85 /*
86 switch (type) {
87   #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
88                          RTYPE, KTYPE, STYPE, ...) \
89     case BASE_TYPE_ ## ENUM: \
90       // do something specific to CTYPE here
91     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
92   #undef FLATBUFFERS_TD
93 }
94 */
95 
96 // If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
97 // of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
98 // In the above example, only CTYPE is used to generate the code, it can be rewritten:
99 
100 /*
101 switch (type) {
102   #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
103     case BASE_TYPE_ ## ENUM: \
104       // do something specific to CTYPE here
105     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
106   #undef FLATBUFFERS_TD
107 }
108 */
109 
110 #define FLATBUFFERS_GEN_TYPES(TD) \
111         FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
112         FLATBUFFERS_GEN_TYPES_POINTER(TD) \
113         FLATBUFFERS_GEN_TYPE_ARRAY(TD)
114 
115 // Create an enum for all the types above.
116 #ifdef __GNUC__
117 __extension__  // Stop GCC complaining about trailing comma with -Wpendantic.
118 #endif
119 enum BaseType {
120   #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
121               CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE, ENUM_VALUE) \
122     BASE_TYPE_ ## ENUM = ENUM_VALUE,
123     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
124   #undef FLATBUFFERS_TD
125 };
126 
127 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
128   static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
129                 "define largest_scalar_t as " #CTYPE);
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)130   FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
131 #undef FLATBUFFERS_TD
132 
133 inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
134                                            t <= BASE_TYPE_DOUBLE; }
IsInteger(BaseType t)135 inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
136                                            t <= BASE_TYPE_ULONG; }
IsFloat(BaseType t)137 inline bool IsFloat  (BaseType t) { return t == BASE_TYPE_FLOAT ||
138                                            t == BASE_TYPE_DOUBLE; }
IsLong(BaseType t)139 inline bool IsLong   (BaseType t) { return t == BASE_TYPE_LONG ||
140                                            t == BASE_TYPE_ULONG; }
IsBool(BaseType t)141 inline bool IsBool   (BaseType t) { return t == BASE_TYPE_BOOL; }
IsOneByte(BaseType t)142 inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
143                                            t <= BASE_TYPE_UCHAR; }
IsVector(BaseType t)144 inline bool IsVector (BaseType t) { return t == BASE_TYPE_VECTOR ||
145                                            t == BASE_TYPE_VECTOR64; }
146 
IsUnsigned(BaseType t)147 inline bool IsUnsigned(BaseType t) {
148   return (t == BASE_TYPE_UTYPE)  || (t == BASE_TYPE_UCHAR) ||
149          (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT)  ||
150          (t == BASE_TYPE_ULONG);
151 }
152 
SizeOf(const BaseType t)153 inline size_t SizeOf(const BaseType t) {
154   switch (t) {
155   #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
156     case BASE_TYPE_##ENUM: return sizeof(CTYPE);
157       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
158   #undef FLATBUFFERS_TD
159     default: FLATBUFFERS_ASSERT(0);
160   }
161   return 0;
162 }
163 
TypeName(const BaseType t)164 inline const char* TypeName(const BaseType t) {
165   switch (t) {
166   #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
167     case BASE_TYPE_##ENUM: return IDLTYPE;
168       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
169   #undef FLATBUFFERS_TD
170     default: FLATBUFFERS_ASSERT(0);
171   }
172   return nullptr;
173 }
174 
StringOf(const BaseType t)175 inline const char* StringOf(const BaseType t) {
176   switch (t) {
177   #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
178     case BASE_TYPE_##ENUM: return #CTYPE;
179       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
180   #undef FLATBUFFERS_TD
181     default: FLATBUFFERS_ASSERT(0);
182   }
183   return "";
184 }
185 
186 // clang-format on
187 
188 struct StructDef;
189 struct EnumDef;
190 class Parser;
191 
192 // Represents any type in the IDL, which is a combination of the BaseType
193 // and additional information for vectors/structs_.
194 struct Type {
195   explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
196                 EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
base_typeType197       : base_type(_base_type),
198         element(BASE_TYPE_NONE),
199         struct_def(_sd),
200         enum_def(_ed),
201         fixed_length(_fixed_length) {}
202 
203   bool operator==(const Type &o) const {
204     return base_type == o.base_type && element == o.element &&
205            struct_def == o.struct_def && enum_def == o.enum_def;
206   }
207 
VectorTypeType208   Type VectorType() const {
209     return Type(element, struct_def, enum_def, fixed_length);
210   }
211 
212   Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
213 
214   bool Deserialize(const Parser &parser, const reflection::Type *type);
215 
216   BaseType base_type;
217   BaseType element;       // only set if t == BASE_TYPE_VECTOR or
218                           // BASE_TYPE_VECTOR64
219   StructDef *struct_def;  // only set if t or element == BASE_TYPE_STRUCT
220   EnumDef *enum_def;      // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
221                           // or for an integral type derived from an enum.
222   uint16_t fixed_length;  // only set if t == BASE_TYPE_ARRAY
223 };
224 
225 // Represents a parsed scalar value, it's type, and field offset.
226 struct Value {
ValueValue227   Value()
228       : constant("0"),
229         offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
230   Type type;
231   std::string constant;
232   voffset_t offset;
233 };
234 
235 // Helper class that retains the original order of a set of identifiers and
236 // also provides quick lookup.
237 template<typename T> class SymbolTable {
238  public:
~SymbolTable()239   ~SymbolTable() {
240     for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
241   }
242 
Add(const std::string & name,T * e)243   bool Add(const std::string &name, T *e) {
244     vec.emplace_back(e);
245     auto it = dict.find(name);
246     if (it != dict.end()) return true;
247     dict[name] = e;
248     return false;
249   }
250 
Move(const std::string & oldname,const std::string & newname)251   void Move(const std::string &oldname, const std::string &newname) {
252     auto it = dict.find(oldname);
253     if (it != dict.end()) {
254       auto obj = it->second;
255       dict.erase(it);
256       dict[newname] = obj;
257     } else {
258       FLATBUFFERS_ASSERT(false);
259     }
260   }
261 
Lookup(const std::string & name)262   T *Lookup(const std::string &name) const {
263     auto it = dict.find(name);
264     return it == dict.end() ? nullptr : it->second;
265   }
266 
267  public:
268   std::map<std::string, T *> dict;  // quick lookup
269   std::vector<T *> vec;             // Used to iterate in order of insertion
270 };
271 
272 // A name space, as set in the schema.
273 struct Namespace {
NamespaceNamespace274   Namespace() : from_table(0) {}
275 
276   // Given a (potentially unqualified) name, return the "fully qualified" name
277   // which has a full namespaced descriptor.
278   // With max_components you can request less than the number of components
279   // the current namespace has.
280   std::string GetFullyQualifiedName(const std::string &name,
281                                     size_t max_components = 1000) const;
282 
283   std::vector<std::string> components;
284   size_t from_table;  // Part of the namespace corresponds to a message/table.
285 };
286 
287 inline bool operator<(const Namespace &a, const Namespace &b) {
288   size_t min_size = std::min(a.components.size(), b.components.size());
289   for (size_t i = 0; i < min_size; ++i) {
290     if (a.components[i] != b.components[i])
291       return a.components[i] < b.components[i];
292   }
293   return a.components.size() < b.components.size();
294 }
295 
296 // Base class for all definition types (fields, structs_, enums_).
297 struct Definition {
DefinitionDefinition298   Definition()
299       : generated(false),
300         defined_namespace(nullptr),
301         serialized_location(0),
302         index(-1),
303         refcount(1),
304         declaration_file(nullptr) {}
305 
306   flatbuffers::Offset<
307       flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
308   SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
309 
310   bool DeserializeAttributes(Parser &parser,
311                              const Vector<Offset<reflection::KeyValue>> *attrs);
312 
313   std::string name;
314   std::string file;
315   std::vector<std::string> doc_comment;
316   SymbolTable<Value> attributes;
317   bool generated;  // did we already output code for this definition?
318   Namespace *defined_namespace;  // Where it was defined.
319 
320   // For use with Serialize()
321   uoffset_t serialized_location;
322   int index;  // Inside the vector it is stored.
323   int refcount;
324   const std::string *declaration_file;
325 };
326 
327 struct FieldDef : public Definition {
FieldDefFieldDef328   FieldDef()
329       : deprecated(false),
330         key(false),
331         shared(false),
332         native_inline(false),
333         flexbuffer(false),
334         offset64(false),
335         presence(kDefault),
336         nested_flatbuffer(nullptr),
337         padding(0),
338         sibling_union_field(nullptr) {}
339 
340   Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
341                                       const Parser &parser) const;
342 
343   bool Deserialize(Parser &parser, const reflection::Field *field);
344 
IsScalarOptionalFieldDef345   bool IsScalarOptional() const {
346     return IsScalar() && IsOptional();
347   }
IsScalarFieldDef348   bool IsScalar() const {
349       return ::flatbuffers::IsScalar(value.type.base_type);
350   }
IsOptionalFieldDef351   bool IsOptional() const { return presence == kOptional; }
IsRequiredFieldDef352   bool IsRequired() const { return presence == kRequired; }
IsDefaultFieldDef353   bool IsDefault() const { return presence == kDefault; }
354 
355   Value value;
356   bool deprecated;  // Field is allowed to be present in old data, but can't be.
357                     // written in new data nor accessed in new code.
358   bool key;         // Field functions as a key for creating sorted vectors.
359   bool shared;  // Field will be using string pooling (i.e. CreateSharedString)
360                 // as default serialization behavior if field is a string.
361   bool native_inline;  // Field will be defined inline (instead of as a pointer)
362                        // for native tables if field is a struct.
363   bool flexbuffer;     // This field contains FlexBuffer data.
364   bool offset64;       // If the field uses 64-bit offsets.
365 
366   enum Presence {
367     // Field must always be present.
368     kRequired,
369     // Non-presence should be signalled to and controlled by users.
370     kOptional,
371     // Non-presence is hidden from users.
372     // Implementations may omit writing default values.
373     kDefault,
374   };
MakeFieldPresenceFieldDef375   Presence static MakeFieldPresence(bool optional, bool required) {
376     FLATBUFFERS_ASSERT(!(required && optional));
377     // clang-format off
378     return required ? FieldDef::kRequired
379          : optional ? FieldDef::kOptional
380                     : FieldDef::kDefault;
381     // clang-format on
382   }
383   Presence presence;
384 
385   StructDef *nested_flatbuffer;  // This field contains nested FlatBuffer data.
386   size_t padding;                // Bytes to always pad after this field.
387 
388   // sibling_union_field is always set to nullptr. The only exception is
389   // when FieldDef is a union field or an union type field. Therefore,
390   // sibling_union_field on a union field points to the union type field
391   // and vice-versa.
392   FieldDef *sibling_union_field;
393 };
394 
395 struct StructDef : public Definition {
StructDefStructDef396   StructDef()
397       : fixed(false),
398         predecl(true),
399         sortbysize(true),
400         has_key(false),
401         minalign(1),
402         bytesize(0) {}
403 
PadLastFieldStructDef404   void PadLastField(size_t min_align) {
405     auto padding = PaddingBytes(bytesize, min_align);
406     bytesize += padding;
407     if (fields.vec.size()) fields.vec.back()->padding = padding;
408   }
409 
410   Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
411                                        const Parser &parser) const;
412 
413   bool Deserialize(Parser &parser, const reflection::Object *object);
414 
415   SymbolTable<FieldDef> fields;
416 
417   bool fixed;       // If it's struct, not a table.
418   bool predecl;     // If it's used before it was defined.
419   bool sortbysize;  // Whether fields come in the declaration or size order.
420   bool has_key;     // It has a key field.
421   size_t minalign;  // What the whole object needs to be aligned to.
422   size_t bytesize;  // Size if fixed.
423 
424   flatbuffers::unique_ptr<std::string> original_location;
425   std::vector<voffset_t> reserved_ids;
426 };
427 
428 struct EnumDef;
429 struct EnumValBuilder;
430 
431 struct EnumVal {
432   Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
433                                         const Parser &parser) const;
434 
435   bool Deserialize(Parser &parser, const reflection::EnumVal *val);
436 
437   flatbuffers::Offset<
438       flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
439   SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
440 
441   bool DeserializeAttributes(Parser &parser,
442                              const Vector<Offset<reflection::KeyValue>> *attrs);
443 
GetAsUInt64EnumVal444   uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
GetAsInt64EnumVal445   int64_t GetAsInt64() const { return value; }
IsZeroEnumVal446   bool IsZero() const { return 0 == value; }
IsNonZeroEnumVal447   bool IsNonZero() const { return !IsZero(); }
448 
449   std::string name;
450   std::vector<std::string> doc_comment;
451   Type union_type;
452   SymbolTable<Value> attributes;
453 
454  private:
455   friend EnumDef;
456   friend EnumValBuilder;
457   friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
458 
EnumValEnumVal459   EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumValEnumVal460   EnumVal() : value(0) {}
461 
462   int64_t value;
463 };
464 
465 struct EnumDef : public Definition {
EnumDefEnumDef466   EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
467 
468   Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
469                                      const Parser &parser) const;
470 
471   bool Deserialize(Parser &parser, const reflection::Enum *values);
472 
473   template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
474   void SortByValue();
475   void RemoveDuplicates();
476 
477   std::string AllFlags() const;
478   const EnumVal *MinValue() const;
479   const EnumVal *MaxValue() const;
480   // Returns the number of integer steps from v1 to v2.
481   uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
482   // Returns the number of integer steps from Min to Max.
DistanceEnumDef483   uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
484 
485   EnumVal *ReverseLookup(int64_t enum_idx,
486                          bool skip_union_default = false) const;
487   EnumVal *FindByValue(const std::string &constant) const;
488 
ToStringEnumDef489   std::string ToString(const EnumVal &ev) const {
490     return IsUInt64() ? NumToString(ev.GetAsUInt64())
491                       : NumToString(ev.GetAsInt64());
492   }
493 
sizeEnumDef494   size_t size() const { return vals.vec.size(); }
495 
ValsEnumDef496   const std::vector<EnumVal *> &Vals() const { return vals.vec; }
497 
LookupEnumDef498   const EnumVal *Lookup(const std::string &enum_name) const {
499     return vals.Lookup(enum_name);
500   }
501 
502   bool is_union;
503   // Type is a union which uses type aliases where at least one type is
504   // available under two different names.
505   bool uses_multiple_type_instances;
506   Type underlying_type;
507 
508  private:
IsUInt64EnumDef509   bool IsUInt64() const {
510     return (BASE_TYPE_ULONG == underlying_type.base_type);
511   }
512 
513   friend EnumValBuilder;
514   SymbolTable<EnumVal> vals;
515 };
516 
IsString(const Type & type)517 inline bool IsString(const Type &type) {
518   return type.base_type == BASE_TYPE_STRING;
519 }
520 
IsStruct(const Type & type)521 inline bool IsStruct(const Type &type) {
522   return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
523 }
524 
IsIncompleteStruct(const Type & type)525 inline bool IsIncompleteStruct(const Type &type) {
526   return type.base_type == BASE_TYPE_STRUCT && type.struct_def->predecl;
527 }
528 
IsTable(const Type & type)529 inline bool IsTable(const Type &type) {
530   return type.base_type == BASE_TYPE_STRUCT && !type.struct_def->fixed;
531 }
532 
IsUnion(const Type & type)533 inline bool IsUnion(const Type &type) {
534   return type.enum_def != nullptr && type.enum_def->is_union;
535 }
536 
IsUnionType(const Type & type)537 inline bool IsUnionType(const Type &type) {
538   return IsUnion(type) && IsInteger(type.base_type);
539 }
540 
IsVector(const Type & type)541 inline bool IsVector(const Type &type) { return IsVector(type.base_type); }
542 
IsVectorOfStruct(const Type & type)543 inline bool IsVectorOfStruct(const Type &type) {
544   return IsVector(type) && IsStruct(type.VectorType());
545 }
546 
IsVectorOfTable(const Type & type)547 inline bool IsVectorOfTable(const Type &type) {
548   return IsVector(type) && IsTable(type.VectorType());
549 }
550 
IsArray(const Type & type)551 inline bool IsArray(const Type &type) {
552   return type.base_type == BASE_TYPE_ARRAY;
553 }
554 
IsSeries(const Type & type)555 inline bool IsSeries(const Type &type) {
556   return IsVector(type) || IsArray(type);
557 }
558 
IsEnum(const Type & type)559 inline bool IsEnum(const Type &type) {
560   return type.enum_def != nullptr && IsInteger(type.base_type);
561 }
562 
InlineSize(const Type & type)563 inline size_t InlineSize(const Type &type) {
564   return IsStruct(type)
565              ? type.struct_def->bytesize
566              : (IsArray(type)
567                     ? InlineSize(type.VectorType()) * type.fixed_length
568                     : SizeOf(type.base_type));
569 }
570 
InlineAlignment(const Type & type)571 inline size_t InlineAlignment(const Type &type) {
572   if (IsStruct(type)) {
573     return type.struct_def->minalign;
574   } else if (IsArray(type)) {
575     return IsStruct(type.VectorType()) ? type.struct_def->minalign
576                                        : SizeOf(type.element);
577   } else {
578     return SizeOf(type.base_type);
579   }
580 }
581 inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
582   return lhs.value == rhs.value;
583 }
584 inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
585   return !(lhs == rhs);
586 }
587 
EqualByName(const Type & a,const Type & b)588 inline bool EqualByName(const Type &a, const Type &b) {
589   return a.base_type == b.base_type && a.element == b.element &&
590          (a.struct_def == b.struct_def ||
591           (a.struct_def != nullptr && b.struct_def != nullptr &&
592            a.struct_def->name == b.struct_def->name)) &&
593          (a.enum_def == b.enum_def ||
594           (a.enum_def != nullptr && b.enum_def != nullptr &&
595            a.enum_def->name == b.enum_def->name));
596 }
597 
598 struct RPCCall : public Definition {
599   Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
600                                         const Parser &parser) const;
601 
602   bool Deserialize(Parser &parser, const reflection::RPCCall *call);
603 
604   StructDef *request, *response;
605 };
606 
607 struct ServiceDef : public Definition {
608   Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
609                                         const Parser &parser) const;
610   bool Deserialize(Parser &parser, const reflection::Service *service);
611 
612   SymbolTable<RPCCall> calls;
613 };
614 
615 struct IncludedFile {
616   // The name of the schema file being included, as defined in the .fbs file.
617   // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this
618   // value is "foo/bar/baz.fbs").
619   std::string schema_name;
620 
621   // The filename of where the included file was found, after searching the
622   // relative paths plus any other paths included with `flatc -I ...`. Note,
623   // while this is sometimes the same as schema_name, it is not always, since it
624   // can be defined relative to where flatc was invoked.
625   std::string filename;
626 };
627 
628 // Since IncludedFile is contained within a std::set, need to provide ordering.
629 inline bool operator<(const IncludedFile &a, const IncludedFile &b) {
630   return a.filename < b.filename;
631 }
632 
633 // Container of options that may apply to any of the source/text generators.
634 struct IDLOptions {
635   // field case style options for C++
636   enum CaseStyle { CaseStyle_Unchanged = 0, CaseStyle_Upper, CaseStyle_Lower };
637   enum class ProtoIdGapAction { NO_OP, WARNING, ERROR };
638   bool gen_jvmstatic;
639   // Use flexbuffers instead for binary and text generation
640   bool use_flexbuffers;
641   bool strict_json;
642   bool output_default_scalars_in_json;
643   int indent_step;
644   bool cpp_minify_enums;
645   bool output_enum_identifiers;
646   bool prefixed_enums;
647   bool scoped_enums;
648   bool emit_min_max_enum_values;
649   bool swift_implementation_only;
650   bool include_dependence_headers;
651   bool mutable_buffer;
652   bool one_file;
653   bool proto_mode;
654   bool proto_oneof_union;
655   bool generate_all;
656   bool skip_unexpected_fields_in_json;
657   bool generate_name_strings;
658   bool generate_object_based_api;
659   bool gen_compare;
660   std::string cpp_object_api_pointer_type;
661   std::string cpp_object_api_string_type;
662   bool cpp_object_api_string_flexible_constructor;
663   CaseStyle cpp_object_api_field_case_style;
664   bool cpp_direct_copy;
665   bool gen_nullable;
666   std::string java_package_prefix;
667   bool java_checkerframework;
668   bool gen_generated;
669   bool gen_json_coders;
670   std::string object_prefix;
671   std::string object_suffix;
672   bool union_value_namespacing;
673   bool allow_non_utf8;
674   bool natural_utf8;
675   std::string include_prefix;
676   bool keep_prefix;
677   bool binary_schema_comments;
678   bool binary_schema_builtins;
679   bool binary_schema_gen_embed;
680   bool binary_schema_absolute_paths;
681   std::string go_import;
682   std::string go_namespace;
683   std::string go_module_name;
684   bool protobuf_ascii_alike;
685   bool size_prefixed;
686   std::string root_type;
687   bool force_defaults;
688   bool java_primitive_has_method;
689   bool cs_gen_json_serializer;
690   std::vector<std::string> cpp_includes;
691   std::string cpp_std;
692   bool cpp_static_reflection;
693   std::string proto_namespace_suffix;
694   std::string filename_suffix;
695   std::string filename_extension;
696   bool no_warnings;
697   bool warnings_as_errors;
698   std::string project_root;
699   bool cs_global_alias;
700   bool json_nested_flatbuffers;
701   bool json_nested_flexbuffers;
702   bool json_nested_legacy_flatbuffers;
703   bool ts_flat_files;
704   bool ts_entry_points;
705   bool ts_no_import_ext;
706   bool no_leak_private_annotations;
707   bool require_json_eof;
708   bool keep_proto_id;
709 
710   /********************************** Python **********************************/
711   bool python_no_type_prefix_suffix;
712   bool python_typing;
713 
714   // The target Python version. Can be one of the following:
715   // -  "0"
716   // -  "2"
717   // -  "3"
718   // -  "2.<minor>"
719   // -  "3.<minor>"
720   // -  "2.<minor>.<micro>"
721   // -  "3.<minor>.<micro>"
722   //
723   // https://docs.python.org/3/faq/general.html#how-does-the-python-version-numbering-scheme-work
724   std::string python_version;
725 
726   // Whether to generate numpy helpers.
727   bool python_gen_numpy;
728 
729   bool ts_omit_entrypoint;
730   ProtoIdGapAction proto_id_gap_action;
731 
732   // Possible options for the more general generator below.
733   enum Language {
734     kJava = 1 << 0,
735     kCSharp = 1 << 1,
736     kGo = 1 << 2,
737     kCpp = 1 << 3,
738     kPython = 1 << 5,
739     kPhp = 1 << 6,
740     kJson = 1 << 7,
741     kBinary = 1 << 8,
742     kTs = 1 << 9,
743     kJsonSchema = 1 << 10,
744     kDart = 1 << 11,
745     kLua = 1 << 12,
746     kLobster = 1 << 13,
747     kRust = 1 << 14,
748     kKotlin = 1 << 15,
749     kSwift = 1 << 16,
750     kNim = 1 << 17,
751     kProto = 1 << 18,
752     kKotlinKmp = 1 << 19,
753     kMAX
754   };
755 
756   enum MiniReflect { kNone, kTypes, kTypesAndNames };
757 
758   MiniReflect mini_reflect;
759 
760   // If set, require all fields in a table to be explicitly numbered.
761   bool require_explicit_ids;
762 
763   // If set, implement serde::Serialize for generated Rust types
764   bool rust_serialize;
765 
766   // If set, generate rust types in individual files with a root module file.
767   bool rust_module_root_file;
768 
769   // The corresponding language bit will be set if a language is included
770   // for code generation.
771   unsigned long lang_to_generate;
772 
773   // If set (default behavior), empty string fields will be set to nullptr to
774   // make the flatbuffer more compact.
775   bool set_empty_strings_to_null;
776 
777   // If set (default behavior), empty vector fields will be set to nullptr to
778   // make the flatbuffer more compact.
779   bool set_empty_vectors_to_null;
780 
781   /*********************************** gRPC ***********************************/
782   std::string grpc_filename_suffix;
783   bool grpc_use_system_headers;
784   std::string grpc_search_path;
785   std::vector<std::string> grpc_additional_headers;
786 
787   /******************************* Python gRPC ********************************/
788   bool grpc_python_typed_handlers;
789 
IDLOptionsIDLOptions790   IDLOptions()
791       : gen_jvmstatic(false),
792         use_flexbuffers(false),
793         strict_json(false),
794         output_default_scalars_in_json(false),
795         indent_step(2),
796         cpp_minify_enums(false),
797         output_enum_identifiers(true),
798         prefixed_enums(true),
799         scoped_enums(false),
800         emit_min_max_enum_values(true),
801         swift_implementation_only(false),
802         include_dependence_headers(true),
803         mutable_buffer(false),
804         one_file(false),
805         proto_mode(false),
806         proto_oneof_union(false),
807         generate_all(false),
808         skip_unexpected_fields_in_json(false),
809         generate_name_strings(false),
810         generate_object_based_api(false),
811         gen_compare(false),
812         cpp_object_api_pointer_type("std::unique_ptr"),
813         cpp_object_api_string_flexible_constructor(false),
814         cpp_object_api_field_case_style(CaseStyle_Unchanged),
815         cpp_direct_copy(true),
816         gen_nullable(false),
817         java_checkerframework(false),
818         gen_generated(false),
819         gen_json_coders(false),
820         object_suffix("T"),
821         union_value_namespacing(true),
822         allow_non_utf8(false),
823         natural_utf8(false),
824         keep_prefix(false),
825         binary_schema_comments(false),
826         binary_schema_builtins(false),
827         binary_schema_gen_embed(false),
828         binary_schema_absolute_paths(false),
829         protobuf_ascii_alike(false),
830         size_prefixed(false),
831         force_defaults(false),
832         java_primitive_has_method(false),
833         cs_gen_json_serializer(false),
834         cpp_static_reflection(false),
835         filename_suffix("_generated"),
836         filename_extension(),
837         no_warnings(false),
838         warnings_as_errors(false),
839         project_root(""),
840         cs_global_alias(false),
841         json_nested_flatbuffers(true),
842         json_nested_flexbuffers(true),
843         json_nested_legacy_flatbuffers(false),
844         ts_flat_files(false),
845         ts_entry_points(false),
846         ts_no_import_ext(false),
847         no_leak_private_annotations(false),
848         require_json_eof(true),
849         keep_proto_id(false),
850         python_no_type_prefix_suffix(false),
851         python_typing(false),
852         python_gen_numpy(true),
853         ts_omit_entrypoint(false),
854         proto_id_gap_action(ProtoIdGapAction::WARNING),
855         mini_reflect(IDLOptions::kNone),
856         require_explicit_ids(false),
857         rust_serialize(false),
858         rust_module_root_file(false),
859         lang_to_generate(0),
860         set_empty_strings_to_null(true),
861         set_empty_vectors_to_null(true),
862         grpc_filename_suffix(".fb"),
863         grpc_use_system_headers(true),
864         grpc_python_typed_handlers(false) {}
865 };
866 
867 // This encapsulates where the parser is in the current source file.
868 struct ParserState {
ParserStateParserState869   ParserState()
870       : prev_cursor_(nullptr),
871         cursor_(nullptr),
872         line_start_(nullptr),
873         line_(0),
874         token_(-1),
875         attr_is_trivial_ascii_string_(true) {}
876 
877  protected:
ResetStateParserState878   void ResetState(const char *source) {
879     prev_cursor_ = source;
880     cursor_ = source;
881     line_ = 0;
882     MarkNewLine();
883   }
884 
MarkNewLineParserState885   void MarkNewLine() {
886     line_start_ = cursor_;
887     line_ += 1;
888   }
889 
CursorPositionParserState890   int64_t CursorPosition() const {
891     FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
892     return static_cast<int64_t>(cursor_ - line_start_);
893   }
894 
895   const char *prev_cursor_;
896   const char *cursor_;
897   const char *line_start_;
898   int line_;  // the current line being parsed
899   int token_;
900 
901   // Flag: text in attribute_ is true ASCII string without escape
902   // sequences. Only printable ASCII (without [\t\r\n]).
903   // Used for number-in-string (and base64 string in future).
904   bool attr_is_trivial_ascii_string_;
905   std::string attribute_;
906   std::vector<std::string> doc_comment_;
907 };
908 
909 // A way to make error propagation less error prone by requiring values to be
910 // checked.
911 // Once you create a value of this type you must either:
912 // - Call Check() on it.
913 // - Copy or assign it to another value.
914 // Failure to do so leads to an assert.
915 // This guarantees that this as return value cannot be ignored.
916 class CheckedError {
917  public:
CheckedError(bool error)918   explicit CheckedError(bool error)
919       : is_error_(error), has_been_checked_(false) {}
920 
921   CheckedError &operator=(const CheckedError &other) {
922     is_error_ = other.is_error_;
923     has_been_checked_ = false;
924     other.has_been_checked_ = true;
925     return *this;
926   }
927 
CheckedError(const CheckedError & other)928   CheckedError(const CheckedError &other) {
929     *this = other;  // Use assignment operator.
930   }
931 
~CheckedError()932   ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
933 
Check()934   bool Check() {
935     has_been_checked_ = true;
936     return is_error_;
937   }
938 
939  private:
940   bool is_error_;
941   mutable bool has_been_checked_;
942 };
943 
944 // Additionally, in GCC we can get these errors statically, for additional
945 // assurance:
946 // clang-format off
947 #ifdef __GNUC__
948 #define FLATBUFFERS_CHECKED_ERROR CheckedError \
949           __attribute__((warn_unused_result))
950 #else
951 #define FLATBUFFERS_CHECKED_ERROR CheckedError
952 #endif
953 // clang-format on
954 
955 class Parser : public ParserState {
956  public:
957   explicit Parser(const IDLOptions &options = IDLOptions())
current_namespace_(nullptr)958       : current_namespace_(nullptr),
959         empty_namespace_(nullptr),
960         flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
961         root_struct_def_(nullptr),
962         opts(options),
963         uses_flexbuffers_(false),
964         has_warning_(false),
965         advanced_features_(0),
966         source_(nullptr),
967         anonymous_counter_(0),
968         parse_depth_counter_(0) {
969     if (opts.force_defaults) { builder_.ForceDefaults(true); }
970     // Start out with the empty namespace being current.
971     empty_namespace_ = new Namespace();
972     namespaces_.push_back(empty_namespace_);
973     current_namespace_ = empty_namespace_;
974     known_attributes_["deprecated"] = true;
975     known_attributes_["required"] = true;
976     known_attributes_["key"] = true;
977     known_attributes_["shared"] = true;
978     known_attributes_["hash"] = true;
979     known_attributes_["id"] = true;
980     known_attributes_["force_align"] = true;
981     known_attributes_["bit_flags"] = true;
982     known_attributes_["original_order"] = true;
983     known_attributes_["nested_flatbuffer"] = true;
984     known_attributes_["csharp_partial"] = true;
985     known_attributes_["streaming"] = true;
986     known_attributes_["idempotent"] = true;
987     known_attributes_["cpp_type"] = true;
988     known_attributes_["cpp_ptr_type"] = true;
989     known_attributes_["cpp_ptr_type_get"] = true;
990     known_attributes_["cpp_str_type"] = true;
991     known_attributes_["cpp_str_flex_ctor"] = true;
992     known_attributes_["native_inline"] = true;
993     known_attributes_["native_custom_alloc"] = true;
994     known_attributes_["native_type"] = true;
995     known_attributes_["native_type_pack_name"] = true;
996     known_attributes_["native_default"] = true;
997     known_attributes_["flexbuffer"] = true;
998     known_attributes_["private"] = true;
999 
1000     // An attribute added to a field to indicate that is uses 64-bit addressing.
1001     known_attributes_["offset64"] = true;
1002 
1003     // An attribute added to a vector field to indicate that it uses 64-bit
1004     // addressing and it has a 64-bit length.
1005     known_attributes_["vector64"] = true;
1006   }
1007 
1008   // Copying is not allowed
1009   Parser(const Parser &) = delete;
1010   Parser &operator=(const Parser &) = delete;
1011 
1012   Parser(Parser &&) = default;
1013   Parser &operator=(Parser &&) = default;
1014 
~Parser()1015   ~Parser() {
1016     for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
1017       delete *it;
1018     }
1019   }
1020 
1021   // Parse the string containing either schema or JSON data, which will
1022   // populate the SymbolTable's or the FlatBufferBuilder above.
1023   // include_paths is used to resolve any include statements, and typically
1024   // should at least include the project path (where you loaded source_ from).
1025   // include_paths must be nullptr terminated if specified.
1026   // If include_paths is nullptr, it will attempt to load from the current
1027   // directory.
1028   // If the source was loaded from a file and isn't an include file,
1029   // supply its name in source_filename.
1030   // All paths specified in this call must be in posix format, if you accept
1031   // paths from user input, please call PosixPath on them first.
1032   bool Parse(const char *_source, const char **include_paths = nullptr,
1033              const char *source_filename = nullptr);
1034 
1035   bool ParseJson(const char *json, const char *json_filename = nullptr);
1036 
1037   // Returns the number of characters were consumed when parsing a JSON string.
1038   std::ptrdiff_t BytesConsumed() const;
1039 
1040   // Set the root type. May override the one set in the schema.
1041   bool SetRootType(const char *name);
1042 
1043   // Mark all definitions as already having code generated.
1044   void MarkGenerated();
1045 
1046   // Get the files recursively included by the given file. The returned
1047   // container will have at least the given file.
1048   std::set<std::string> GetIncludedFilesRecursive(
1049       const std::string &file_name) const;
1050 
1051   // Fills builder_ with a binary version of the schema parsed.
1052   // See reflection/reflection.fbs
1053   void Serialize();
1054 
1055   // Deserialize a schema buffer
1056   bool Deserialize(const uint8_t *buf, const size_t size);
1057 
1058   // Fills internal structure as if the schema passed had been loaded by parsing
1059   // with Parse except that included filenames will not be populated.
1060   bool Deserialize(const reflection::Schema *schema);
1061 
1062   Type *DeserializeType(const reflection::Type *type);
1063 
1064   // Checks that the schema represented by this parser is a safe evolution
1065   // of the schema provided. Returns non-empty error on any problems.
1066   std::string ConformTo(const Parser &base);
1067 
1068   // Similar to Parse(), but now only accepts JSON to be parsed into a
1069   // FlexBuffer.
1070   bool ParseFlexBuffer(const char *source, const char *source_filename,
1071                        flexbuffers::Builder *builder);
1072 
1073   StructDef *LookupStruct(const std::string &id) const;
1074   StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
1075 
1076   std::string UnqualifiedName(const std::string &fullQualifiedName);
1077 
1078   FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
1079 
1080   // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
1081   // in a schema.
1082   // @param opts Options used to parce a schema and generate code.
1083   static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
1084 
1085   // Get the set of included files that are directly referenced by the file
1086   // being parsed. This does not include files that are transitively included by
1087   // others includes.
1088   std::vector<IncludedFile> GetIncludedFiles() const;
1089 
1090  private:
1091   class ParseDepthGuard;
1092 
1093   void Message(const std::string &msg);
1094   void Warning(const std::string &msg);
1095   FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
1096   FLATBUFFERS_CHECKED_ERROR Next();
1097   FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
1098   bool Is(int t) const;
1099   bool IsIdent(const char *id) const;
1100   FLATBUFFERS_CHECKED_ERROR Expect(int t);
1101   std::string TokenToStringId(int t) const;
1102   EnumDef *LookupEnum(const std::string &id);
1103   FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
1104                                              std::string *last);
1105   FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
1106   FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
1107   FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
1108                                      const std::string &name, const Type &type,
1109                                      FieldDef **dest);
1110   FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
1111   FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
1112   FLATBUFFERS_CHECKED_ERROR ParseComma();
1113   FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
1114                                           size_t parent_fieldn,
1115                                           const StructDef *parent_struct_def,
1116                                           size_t count,
1117                                           bool inside_vector = false);
1118   template<typename F>
1119   FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
1120                                                  const StructDef *struct_def,
1121                                                  F body);
1122   FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
1123                                        std::string *value, uoffset_t *ovalue);
1124   void SerializeStruct(const StructDef &struct_def, const Value &val);
1125   void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
1126                        const Value &val);
1127   template<typename F>
1128   FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count, F body);
1129   FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
1130                                         FieldDef *field, size_t fieldn);
1131   FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
1132   FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
1133       Value &val, FieldDef *field, size_t fieldn,
1134       const StructDef *parent_struct_def);
1135   FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
1136   FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
1137                                           bool check, Value &e, BaseType req,
1138                                           bool *destmatch);
1139   FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
1140   FLATBUFFERS_CHECKED_ERROR TokenError();
1141   FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
1142                                              bool check_now);
1143   FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
1144   FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
1145                                                 std::string *result);
1146   StructDef *LookupCreateStruct(const std::string &name,
1147                                 bool create_if_new = true,
1148                                 bool definition = false);
1149   FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest,
1150                                       const char *filename);
1151   FLATBUFFERS_CHECKED_ERROR ParseNamespace();
1152   FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
1153                                         StructDef **dest);
1154   FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
1155                                       EnumDef **dest);
1156   FLATBUFFERS_CHECKED_ERROR ParseDecl(const char *filename);
1157   FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
1158   FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
1159                                              bool isextend, bool inside_oneof);
1160   FLATBUFFERS_CHECKED_ERROR ParseProtoMapField(StructDef *struct_def);
1161   FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
1162   FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
1163   FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
1164   FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
1165   FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
1166   FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
1167   FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(
1168       flexbuffers::Builder *builder);
1169   FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
1170   FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
1171                                            const char *source_filename);
1172   FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
1173                                       const char **include_paths,
1174                                       const char *source_filename);
1175   FLATBUFFERS_CHECKED_ERROR CheckPrivateLeak();
1176   FLATBUFFERS_CHECKED_ERROR CheckPrivatelyLeakedFields(
1177       const Definition &def, const Definition &value_type);
1178   FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
1179                                     const char **include_paths,
1180                                     const char *source_filename,
1181                                     const char *include_filename);
1182   FLATBUFFERS_CHECKED_ERROR DoParseJson();
1183   FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
1184                                        StructDef *struct_def,
1185                                        const char *suffix, BaseType baseType);
1186   FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(
1187       const std::string &align_constant, size_t min_align, size_t *align);
1188 
1189   bool SupportsAdvancedUnionFeatures() const;
1190   bool SupportsAdvancedArrayFeatures() const;
1191   bool SupportsOptionalScalars() const;
1192   bool SupportsDefaultVectorsAndStrings() const;
1193   bool Supports64BitOffsets() const;
1194   bool SupportsUnionUnderlyingType() const;
1195   Namespace *UniqueNamespace(Namespace *ns);
1196 
1197   FLATBUFFERS_CHECKED_ERROR RecurseError();
1198   template<typename F> CheckedError Recurse(F f);
1199 
1200   const std::string &GetPooledString(const std::string &s) const;
1201 
1202  public:
1203   SymbolTable<Type> types_;
1204   SymbolTable<StructDef> structs_;
1205   SymbolTable<EnumDef> enums_;
1206   SymbolTable<ServiceDef> services_;
1207   std::vector<Namespace *> namespaces_;
1208   Namespace *current_namespace_;
1209   Namespace *empty_namespace_;
1210   std::string error_;  // User readable error_ if Parse() == false
1211 
1212   FlatBufferBuilder builder_;  // any data contained in the file
1213   flexbuffers::Builder flex_builder_;
1214   flexbuffers::Reference flex_root_;
1215   StructDef *root_struct_def_;
1216   std::string file_identifier_;
1217   std::string file_extension_;
1218 
1219   std::map<uint64_t, std::string> included_files_;
1220   std::map<std::string, std::set<IncludedFile>> files_included_per_file_;
1221   std::vector<std::string> native_included_files_;
1222 
1223   std::map<std::string, bool> known_attributes_;
1224 
1225   IDLOptions opts;
1226   bool uses_flexbuffers_;
1227   bool has_warning_;
1228 
1229   uint64_t advanced_features_;
1230 
1231   std::string file_being_parsed_;
1232 
1233  private:
1234   const char *source_;
1235 
1236   std::vector<std::pair<Value, FieldDef *>> field_stack_;
1237 
1238   // TODO(cneo): Refactor parser to use string_cache more often to save
1239   // on memory usage.
1240   mutable std::set<std::string> string_cache_;
1241 
1242   int anonymous_counter_;
1243   int parse_depth_counter_;  // stack-overflow guard
1244 };
1245 
1246 // Utility functions for multiple generators:
1247 
1248 // Generate text (JSON) from a given FlatBuffer, and a given Parser
1249 // object that has been populated with the corresponding schema.
1250 // If ident_step is 0, no indentation will be generated. Additionally,
1251 // if it is less than 0, no linefeeds will be generated either.
1252 // See idl_gen_text.cpp.
1253 // strict_json adds "quotes" around field names if true.
1254 // These functions return nullptr on success, or an error string,
1255 // which may happen if the flatbuffer cannot be encoded in JSON (e.g.,
1256 // it contains non-UTF-8 byte arrays in String values).
1257 extern bool GenerateTextFromTable(const Parser &parser,
1258                                          const void *table,
1259                                          const std::string &tablename,
1260                                          std::string *text);
1261 extern const char *GenerateText(const Parser &parser, const void *flatbuffer,
1262                                 std::string *text);
1263 extern const char *GenerateTextFile(const Parser &parser,
1264                                     const std::string &path,
1265                                     const std::string &file_name);
1266 
1267 extern const char *GenTextFromTable(const Parser &parser, const void *table,
1268                                     const std::string &tablename,
1269                                     std::string *text);
1270 extern const char *GenText(const Parser &parser, const void *flatbuffer,
1271                            std::string *text);
1272 extern const char *GenTextFile(const Parser &parser, const std::string &path,
1273                                const std::string &file_name);
1274 
1275 // Generate GRPC Cpp interfaces.
1276 // See idl_gen_grpc.cpp.
1277 bool GenerateCppGRPC(const Parser &parser, const std::string &path,
1278                      const std::string &file_name);
1279 
1280 // Generate GRPC Go interfaces.
1281 // See idl_gen_grpc.cpp.
1282 bool GenerateGoGRPC(const Parser &parser, const std::string &path,
1283                     const std::string &file_name);
1284 
1285 // Generate GRPC Java classes.
1286 // See idl_gen_grpc.cpp
1287 bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
1288                       const std::string &file_name);
1289 
1290 // Generate GRPC Python interfaces.
1291 // See idl_gen_grpc.cpp.
1292 bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
1293                         const std::string &file_name);
1294 
1295 // Generate GRPC Swift interfaces.
1296 // See idl_gen_grpc.cpp.
1297 extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
1298                               const std::string &file_name);
1299 
1300 extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
1301                            const std::string &file_name);
1302 }  // namespace flatbuffers
1303 
1304 #endif  // FLATBUFFERS_IDL_H_
1305