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