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 <map>
21 #include <memory>
22 #include <stack>
23 
24 #include "flatbuffers/base.h"
25 #include "flatbuffers/flatbuffers.h"
26 #include "flatbuffers/flexbuffers.h"
27 #include "flatbuffers/hash.h"
28 #include "flatbuffers/reflection.h"
29 
30 #if !defined(FLATBUFFERS_CPP98_STL)
31 #  include <functional>
32 #endif  // !defined(FLATBUFFERS_CPP98_STL)
33 
34 // This file defines the data types representing a parsed IDL (Interface
35 // Definition Language) / schema file.
36 
37 // Limits maximum depth of nested objects.
38 // Prevents stack overflow while parse flatbuffers or json.
39 #if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
40 #  define FLATBUFFERS_MAX_PARSING_DEPTH 64
41 #endif
42 
43 namespace flatbuffers {
44 
45 // The order of these matters for Is*() functions below.
46 // Additionally, Parser::ParseType assumes bool..string is a contiguous range
47 // of type tokens.
48 // clang-format off
49 #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
50   TD(NONE,   "",       uint8_t,  byte,   byte,    byte,   uint8,   u8) \
51   TD(UTYPE,  "",       uint8_t,  byte,   byte,    byte,   uint8,   u8) /* begin scalar/int */ \
52   TD(BOOL,   "bool",   uint8_t,  boolean,bool,    bool,   bool,    bool) \
53   TD(CHAR,   "byte",   int8_t,   byte,   int8,    sbyte,  int8,    i8) \
54   TD(UCHAR,  "ubyte",  uint8_t,  byte,   byte,    byte,   uint8,   u8) \
55   TD(SHORT,  "short",  int16_t,  short,  int16,   short,  int16,   i16) \
56   TD(USHORT, "ushort", uint16_t, short,  uint16,  ushort, uint16,  u16) \
57   TD(INT,    "int",    int32_t,  int,    int32,   int,    int32,   i32) \
58   TD(UINT,   "uint",   uint32_t, int,    uint32,  uint,   uint32,  u32) \
59   TD(LONG,   "long",   int64_t,  long,   int64,   long,   int64,   i64) \
60   TD(ULONG,  "ulong",  uint64_t, long,   uint64,  ulong,  uint64,  u64) /* end int */ \
61   TD(FLOAT,  "float",  float,    float,  float32, float,  float32, f32) /* begin float */ \
62   TD(DOUBLE, "double", double,   double, float64, double, float64, f64) /* end float/scalar */
63 #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
64   TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused) \
65   TD(VECTOR, "",       Offset<void>, int, int, VectorOffset, int, unused) \
66   TD(STRUCT, "",       Offset<void>, int, int, int,          int, unused) \
67   TD(UNION,  "",       Offset<void>, int, int, int,          int, unused)
68 
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 // - Rust type.
78 
79 // using these macros, we can now write code dealing with types just once, e.g.
80 
81 /*
82 switch (type) {
83   #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
84                          RTYPE) \
85     case BASE_TYPE_ ## ENUM: \
86       // do something specific to CTYPE here
87     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
88   #undef FLATBUFFERS_TD
89 }
90 */
91 
92 #define FLATBUFFERS_GEN_TYPES(TD) \
93         FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
94         FLATBUFFERS_GEN_TYPES_POINTER(TD)
95 
96 // Create an enum for all the types above.
97 #ifdef __GNUC__
98 __extension__  // Stop GCC complaining about trailing comma with -Wpendantic.
99 #endif
100 enum BaseType {
101   #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
102                          RTYPE) \
103       BASE_TYPE_ ## ENUM,
104     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
105   #undef FLATBUFFERS_TD
106 };
107 
108 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
109                        RTYPE) \
110     static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
111                   "define largest_scalar_t as " #CTYPE);
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)112   FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
113 #undef FLATBUFFERS_TD
114 
115 inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
116                                            t <= BASE_TYPE_DOUBLE; }
IsInteger(BaseType t)117 inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
118                                            t <= BASE_TYPE_ULONG; }
IsFloat(BaseType t)119 inline bool IsFloat  (BaseType t) { return t == BASE_TYPE_FLOAT ||
120                                            t == BASE_TYPE_DOUBLE; }
IsLong(BaseType t)121 inline bool IsLong   (BaseType t) { return t == BASE_TYPE_LONG ||
122                                            t == BASE_TYPE_ULONG; }
IsBool(BaseType t)123 inline bool IsBool   (BaseType t) { return t == BASE_TYPE_BOOL; }
IsOneByte(BaseType t)124 inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
125                                            t <= BASE_TYPE_UCHAR; }
126 // clang-format on
127 
128 extern const char *const kTypeNames[];
129 extern const char kTypeSizes[];
130 
SizeOf(BaseType t)131 inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
132 
133 struct StructDef;
134 struct EnumDef;
135 class Parser;
136 
137 // Represents any type in the IDL, which is a combination of the BaseType
138 // and additional information for vectors/structs_.
139 struct Type {
140   explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
141                 EnumDef *_ed = nullptr)
base_typeType142       : base_type(_base_type),
143         element(BASE_TYPE_NONE),
144         struct_def(_sd),
145         enum_def(_ed) {}
146 
147   bool operator==(const Type &o) {
148     return base_type == o.base_type && element == o.element &&
149            struct_def == o.struct_def && enum_def == o.enum_def;
150   }
151 
VectorTypeType152   Type VectorType() const { return Type(element, struct_def, enum_def); }
153 
154   Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
155 
156   bool Deserialize(const Parser &parser, const reflection::Type *type);
157 
158   BaseType base_type;
159   BaseType element;       // only set if t == BASE_TYPE_VECTOR
160   StructDef *struct_def;  // only set if t or element == BASE_TYPE_STRUCT
161   EnumDef *enum_def;      // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
162                           // or for an integral type derived from an enum.
163 };
164 
165 // Represents a parsed scalar value, it's type, and field offset.
166 struct Value {
ValueValue167   Value()
168       : constant("0"),
169         offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
170   Type type;
171   std::string constant;
172   voffset_t offset;
173 };
174 
175 // Helper class that retains the original order of a set of identifiers and
176 // also provides quick lookup.
177 template<typename T> class SymbolTable {
178  public:
~SymbolTable()179   ~SymbolTable() {
180     for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
181   }
182 
Add(const std::string & name,T * e)183   bool Add(const std::string &name, T *e) {
184     vector_emplace_back(&vec, e);
185     auto it = dict.find(name);
186     if (it != dict.end()) return true;
187     dict[name] = e;
188     return false;
189   }
190 
Move(const std::string & oldname,const std::string & newname)191   void Move(const std::string &oldname, const std::string &newname) {
192     auto it = dict.find(oldname);
193     if (it != dict.end()) {
194       auto obj = it->second;
195       dict.erase(it);
196       dict[newname] = obj;
197     } else {
198       FLATBUFFERS_ASSERT(false);
199     }
200   }
201 
Lookup(const std::string & name)202   T *Lookup(const std::string &name) const {
203     auto it = dict.find(name);
204     return it == dict.end() ? nullptr : it->second;
205   }
206 
207  public:
208   std::map<std::string, T *> dict;  // quick lookup
209   std::vector<T *> vec;             // Used to iterate in order of insertion
210 };
211 
212 // A name space, as set in the schema.
213 struct Namespace {
NamespaceNamespace214   Namespace() : from_table(0) {}
215 
216   // Given a (potentally unqualified) name, return the "fully qualified" name
217   // which has a full namespaced descriptor.
218   // With max_components you can request less than the number of components
219   // the current namespace has.
220   std::string GetFullyQualifiedName(const std::string &name,
221                                     size_t max_components = 1000) const;
222 
223   std::vector<std::string> components;
224   size_t from_table;  // Part of the namespace corresponds to a message/table.
225 };
226 
227 // Base class for all definition types (fields, structs_, enums_).
228 struct Definition {
DefinitionDefinition229   Definition()
230       : generated(false),
231         defined_namespace(nullptr),
232         serialized_location(0),
233         index(-1),
234         refcount(1) {}
235 
236   flatbuffers::Offset<
237       flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
238   SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
239 
240   bool DeserializeAttributes(Parser &parser,
241                              const Vector<Offset<reflection::KeyValue>> *attrs);
242 
243   std::string name;
244   std::string file;
245   std::vector<std::string> doc_comment;
246   SymbolTable<Value> attributes;
247   bool generated;  // did we already output code for this definition?
248   Namespace *defined_namespace;  // Where it was defined.
249 
250   // For use with Serialize()
251   uoffset_t serialized_location;
252   int index;  // Inside the vector it is stored.
253   int refcount;
254 };
255 
256 struct FieldDef : public Definition {
FieldDefFieldDef257   FieldDef()
258       : deprecated(false),
259         required(false),
260         key(false),
261         shared(false),
262         native_inline(false),
263         flexbuffer(false),
264         nested_flatbuffer(NULL),
265         padding(0) {}
266 
267   Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
268                                       const Parser &parser) const;
269 
270   bool Deserialize(Parser &parser, const reflection::Field *field);
271 
272   Value value;
273   bool deprecated;  // Field is allowed to be present in old data, but can't be.
274                     // written in new data nor accessed in new code.
275   bool required;    // Field must always be present.
276   bool key;         // Field functions as a key for creating sorted vectors.
277   bool shared;  // Field will be using string pooling (i.e. CreateSharedString)
278                 // as default serialization behavior if field is a string.
279   bool native_inline;  // Field will be defined inline (instead of as a pointer)
280                        // for native tables if field is a struct.
281   bool flexbuffer;     // This field contains FlexBuffer data.
282   StructDef *nested_flatbuffer;  // This field contains nested FlatBuffer data.
283   size_t padding;                // Bytes to always pad after this field.
284 };
285 
286 struct StructDef : public Definition {
StructDefStructDef287   StructDef()
288       : fixed(false),
289         predecl(true),
290         sortbysize(true),
291         has_key(false),
292         minalign(1),
293         bytesize(0) {}
294 
PadLastFieldStructDef295   void PadLastField(size_t min_align) {
296     auto padding = PaddingBytes(bytesize, min_align);
297     bytesize += padding;
298     if (fields.vec.size()) fields.vec.back()->padding = padding;
299   }
300 
301   Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
302                                        const Parser &parser) const;
303 
304   bool Deserialize(Parser &parser, const reflection::Object *object);
305 
306   SymbolTable<FieldDef> fields;
307 
308   bool fixed;       // If it's struct, not a table.
309   bool predecl;     // If it's used before it was defined.
310   bool sortbysize;  // Whether fields come in the declaration or size order.
311   bool has_key;     // It has a key field.
312   size_t minalign;  // What the whole object needs to be aligned to.
313   size_t bytesize;  // Size if fixed.
314 
315   flatbuffers::unique_ptr<std::string> original_location;
316 };
317 
IsStruct(const Type & type)318 inline bool IsStruct(const Type &type) {
319   return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
320 }
321 
InlineSize(const Type & type)322 inline size_t InlineSize(const Type &type) {
323   return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
324 }
325 
InlineAlignment(const Type & type)326 inline size_t InlineAlignment(const Type &type) {
327   return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
328 }
329 
330 struct EnumVal {
EnumValEnumVal331   EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumValEnumVal332   EnumVal() : value(0) {}
333 
334   Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
335 
336   bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
IsZeroEnumVal337   bool IsZero() const { return 0 == value; }
IsNonZeroEnumVal338   bool IsNonZero() const { return !IsZero(); }
339 
340   std::string name;
341   std::vector<std::string> doc_comment;
342   int64_t value;
343   Type union_type;
344 };
345 
346 struct EnumDef : public Definition {
EnumDefEnumDef347   EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
348 
349   EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
350     for (auto it = Vals().begin() +
351                    static_cast<int>(is_union && skip_union_default);
352          it != Vals().end(); ++it) {
353       if ((*it)->value == enum_idx) { return *it; }
354     }
355     return nullptr;
356   }
357 
358   Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
359 
360   bool Deserialize(Parser &parser, const reflection::Enum *values);
361 
sizeEnumDef362   size_t size() const { return vals.vec.size(); }
363 
ValsEnumDef364   const std::vector<EnumVal *> &Vals() const {
365     return vals.vec;
366   }
367 
368   SymbolTable<EnumVal> vals;
369   bool is_union;
370   // Type is a union which uses type aliases where at least one type is
371   // available under two different names.
372   bool uses_multiple_type_instances;
373   Type underlying_type;
374 };
375 
EqualByName(const Type & a,const Type & b)376 inline bool EqualByName(const Type &a, const Type &b) {
377   return a.base_type == b.base_type && a.element == b.element &&
378          (a.struct_def == b.struct_def ||
379           a.struct_def->name == b.struct_def->name) &&
380          (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
381 }
382 
383 struct RPCCall : public Definition {
384   Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
385 
386   bool Deserialize(Parser &parser, const reflection::RPCCall *call);
387 
388   StructDef *request, *response;
389 };
390 
391 struct ServiceDef : public Definition {
392   Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
393   bool Deserialize(Parser &parser, const reflection::Service *service);
394 
395   SymbolTable<RPCCall> calls;
396 };
397 
398 // Container of options that may apply to any of the source/text generators.
399 struct IDLOptions {
400   bool strict_json;
401   bool skip_js_exports;
402   bool use_goog_js_export_format;
403   bool use_ES6_js_export_format;
404   bool output_default_scalars_in_json;
405   int indent_step;
406   bool output_enum_identifiers;
407   bool prefixed_enums;
408   bool scoped_enums;
409   bool include_dependence_headers;
410   bool mutable_buffer;
411   bool one_file;
412   bool proto_mode;
413   bool proto_oneof_union;
414   bool generate_all;
415   bool skip_unexpected_fields_in_json;
416   bool generate_name_strings;
417   bool generate_object_based_api;
418   bool gen_compare;
419   std::string cpp_object_api_pointer_type;
420   std::string cpp_object_api_string_type;
421   bool cpp_object_api_string_flexible_constructor;
422   bool gen_nullable;
423   bool gen_generated;
424   std::string object_prefix;
425   std::string object_suffix;
426   bool union_value_namespacing;
427   bool allow_non_utf8;
428   bool natural_utf8;
429   std::string include_prefix;
430   bool keep_include_path;
431   bool binary_schema_comments;
432   bool binary_schema_builtins;
433   bool skip_flatbuffers_import;
434   std::string go_import;
435   std::string go_namespace;
436   bool reexport_ts_modules;
437   bool js_ts_short_names;
438   bool protobuf_ascii_alike;
439   bool size_prefixed;
440   std::string root_type;
441   bool force_defaults;
442 
443   // Possible options for the more general generator below.
444   enum Language {
445     kJava = 1 << 0,
446     kCSharp = 1 << 1,
447     kGo = 1 << 2,
448     kCpp = 1 << 3,
449     kJs = 1 << 4,
450     kPython = 1 << 5,
451     kPhp = 1 << 6,
452     kJson = 1 << 7,
453     kBinary = 1 << 8,
454     kTs = 1 << 9,
455     kJsonSchema = 1 << 10,
456     kDart = 1 << 11,
457     kLua = 1 << 12,
458     kLobster = 1 << 13,
459     kRust = 1 << 14,
460     kMAX
461   };
462 
463   Language lang;
464 
465   enum MiniReflect { kNone, kTypes, kTypesAndNames };
466 
467   MiniReflect mini_reflect;
468 
469   // The corresponding language bit will be set if a language is included
470   // for code generation.
471   unsigned long lang_to_generate;
472 
473   // If set (default behavior), empty string and vector fields will be set to
474   // nullptr to make the flatbuffer more compact.
475   bool set_empty_to_null;
476 
IDLOptionsIDLOptions477   IDLOptions()
478       : strict_json(false),
479         skip_js_exports(false),
480         use_goog_js_export_format(false),
481         use_ES6_js_export_format(false),
482         output_default_scalars_in_json(false),
483         indent_step(2),
484         output_enum_identifiers(true),
485         prefixed_enums(true),
486         scoped_enums(false),
487         include_dependence_headers(true),
488         mutable_buffer(false),
489         one_file(false),
490         proto_mode(false),
491         proto_oneof_union(false),
492         generate_all(false),
493         skip_unexpected_fields_in_json(false),
494         generate_name_strings(false),
495         generate_object_based_api(false),
496         gen_compare(false),
497         cpp_object_api_pointer_type("std::unique_ptr"),
498         cpp_object_api_string_flexible_constructor(false),
499         gen_nullable(false),
500         gen_generated(false),
501         object_suffix("T"),
502         union_value_namespacing(true),
503         allow_non_utf8(false),
504         natural_utf8(false),
505         keep_include_path(false),
506         binary_schema_comments(false),
507         binary_schema_builtins(false),
508         skip_flatbuffers_import(false),
509         reexport_ts_modules(true),
510         js_ts_short_names(false),
511         protobuf_ascii_alike(false),
512         size_prefixed(false),
513         force_defaults(false),
514         lang(IDLOptions::kJava),
515         mini_reflect(IDLOptions::kNone),
516         lang_to_generate(0),
517         set_empty_to_null(true) {}
518 };
519 
520 // This encapsulates where the parser is in the current source file.
521 struct ParserState {
ParserStateParserState522   ParserState()
523       : cursor_(nullptr),
524         line_start_(nullptr),
525         line_(0),
526         token_(-1),
527         attr_is_trivial_ascii_string_(true) {}
528 
529  protected:
ResetStateParserState530   void ResetState(const char *source) {
531     cursor_ = source;
532     line_ = 0;
533     MarkNewLine();
534   }
535 
MarkNewLineParserState536   void MarkNewLine() {
537     line_start_ = cursor_;
538     line_ += 1;
539   }
540 
CursorPositionParserState541   int64_t CursorPosition() const {
542     FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
543     return static_cast<int64_t>(cursor_ - line_start_);
544   }
545 
546   const char *cursor_;
547   const char *line_start_;
548   int line_;  // the current line being parsed
549   int token_;
550 
551   // Flag: text in attribute_ is true ASCII string without escape
552   // sequences. Only printable ASCII (without [\t\r\n]).
553   // Used for number-in-string (and base64 string in future).
554   bool attr_is_trivial_ascii_string_;
555   std::string attribute_;
556   std::vector<std::string> doc_comment_;
557 };
558 
559 // A way to make error propagation less error prone by requiring values to be
560 // checked.
561 // Once you create a value of this type you must either:
562 // - Call Check() on it.
563 // - Copy or assign it to another value.
564 // Failure to do so leads to an assert.
565 // This guarantees that this as return value cannot be ignored.
566 class CheckedError {
567  public:
CheckedError(bool error)568   explicit CheckedError(bool error)
569       : is_error_(error), has_been_checked_(false) {}
570 
571   CheckedError &operator=(const CheckedError &other) {
572     is_error_ = other.is_error_;
573     has_been_checked_ = false;
574     other.has_been_checked_ = true;
575     return *this;
576   }
577 
CheckedError(const CheckedError & other)578   CheckedError(const CheckedError &other) {
579     *this = other;  // Use assignment operator.
580   }
581 
~CheckedError()582   ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
583 
Check()584   bool Check() {
585     has_been_checked_ = true;
586     return is_error_;
587   }
588 
589  private:
590   bool is_error_;
591   mutable bool has_been_checked_;
592 };
593 
594 // Additionally, in GCC we can get these errors statically, for additional
595 // assurance:
596 // clang-format off
597 #ifdef __GNUC__
598 #define FLATBUFFERS_CHECKED_ERROR CheckedError \
599           __attribute__((warn_unused_result))
600 #else
601 #define FLATBUFFERS_CHECKED_ERROR CheckedError
602 #endif
603 // clang-format on
604 
605 class Parser : public ParserState {
606  public:
607   explicit Parser(const IDLOptions &options = IDLOptions())
current_namespace_(nullptr)608       : current_namespace_(nullptr),
609         empty_namespace_(nullptr),
610         root_struct_def_(nullptr),
611         opts(options),
612         uses_flexbuffers_(false),
613         source_(nullptr),
614         anonymous_counter(0),
615         recurse_protection_counter(0) {
616     if (opts.force_defaults) {
617       builder_.ForceDefaults(true);
618     }
619     // Start out with the empty namespace being current.
620     empty_namespace_ = new Namespace();
621     namespaces_.push_back(empty_namespace_);
622     current_namespace_ = empty_namespace_;
623     known_attributes_["deprecated"] = true;
624     known_attributes_["required"] = true;
625     known_attributes_["key"] = true;
626     known_attributes_["shared"] = true;
627     known_attributes_["hash"] = true;
628     known_attributes_["id"] = true;
629     known_attributes_["force_align"] = true;
630     known_attributes_["bit_flags"] = true;
631     known_attributes_["original_order"] = true;
632     known_attributes_["nested_flatbuffer"] = true;
633     known_attributes_["csharp_partial"] = true;
634     known_attributes_["streaming"] = true;
635     known_attributes_["idempotent"] = true;
636     known_attributes_["cpp_type"] = true;
637     known_attributes_["cpp_ptr_type"] = true;
638     known_attributes_["cpp_ptr_type_get"] = true;
639     known_attributes_["cpp_str_type"] = true;
640     known_attributes_["cpp_str_flex_ctor"] = true;
641     known_attributes_["native_inline"] = true;
642     known_attributes_["native_custom_alloc"] = true;
643     known_attributes_["native_type"] = true;
644     known_attributes_["native_default"] = true;
645     known_attributes_["flexbuffer"] = true;
646     known_attributes_["private"] = true;
647   }
648 
~Parser()649   ~Parser() {
650     for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
651       delete *it;
652     }
653   }
654 
655   // Parse the string containing either schema or JSON data, which will
656   // populate the SymbolTable's or the FlatBufferBuilder above.
657   // include_paths is used to resolve any include statements, and typically
658   // should at least include the project path (where you loaded source_ from).
659   // include_paths must be nullptr terminated if specified.
660   // If include_paths is nullptr, it will attempt to load from the current
661   // directory.
662   // If the source was loaded from a file and isn't an include file,
663   // supply its name in source_filename.
664   // All paths specified in this call must be in posix format, if you accept
665   // paths from user input, please call PosixPath on them first.
666   bool Parse(const char *_source, const char **include_paths = nullptr,
667              const char *source_filename = nullptr);
668 
669   // Set the root type. May override the one set in the schema.
670   bool SetRootType(const char *name);
671 
672   // Mark all definitions as already having code generated.
673   void MarkGenerated();
674 
675   // Get the files recursively included by the given file. The returned
676   // container will have at least the given file.
677   std::set<std::string> GetIncludedFilesRecursive(
678       const std::string &file_name) const;
679 
680   // Fills builder_ with a binary version of the schema parsed.
681   // See reflection/reflection.fbs
682   void Serialize();
683 
684   // Deserialize a schema buffer
685   bool Deserialize(const uint8_t *buf, const size_t size);
686 
687   // Fills internal structure as if the schema passed had been loaded by parsing
688   // with Parse except that included filenames will not be populated.
689   bool Deserialize(const reflection::Schema* schema);
690 
691   Type* DeserializeType(const reflection::Type* type);
692 
693   // Checks that the schema represented by this parser is a safe evolution
694   // of the schema provided. Returns non-empty error on any problems.
695   std::string ConformTo(const Parser &base);
696 
697   // Similar to Parse(), but now only accepts JSON to be parsed into a
698   // FlexBuffer.
699   bool ParseFlexBuffer(const char *source, const char *source_filename,
700                        flexbuffers::Builder *builder);
701 
702   StructDef *LookupStruct(const std::string &id) const;
703 
704   std::string UnqualifiedName(std::string fullQualifiedName);
705 
706   FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
707 
708  private:
709   void Message(const std::string &msg);
710   void Warning(const std::string &msg);
711   FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
712   FLATBUFFERS_CHECKED_ERROR Next();
713   FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
714   bool Is(int t) const;
715   bool IsIdent(const char *id) const;
716   FLATBUFFERS_CHECKED_ERROR Expect(int t);
717   std::string TokenToStringId(int t) const;
718   EnumDef *LookupEnum(const std::string &id);
719   FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
720                                              std::string *last);
721   FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
722   FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
723   FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
724                                      const std::string &name, const Type &type,
725                                      FieldDef **dest);
726   FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
727   FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
728   FLATBUFFERS_CHECKED_ERROR ParseComma();
729   FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
730                                           size_t parent_fieldn,
731                                           const StructDef *parent_struct_def,
732                                           uoffset_t count,
733                                           bool inside_vector = false);
734   template<typename F>
735   FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
736                                                  const StructDef *struct_def,
737                                                  F body);
738   FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
739                                        std::string *value, uoffset_t *ovalue);
740   void SerializeStruct(const StructDef &struct_def, const Value &val);
741   template<typename F>
742   FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
743   FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
744                                         FieldDef *field, size_t fieldn);
745   FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
746                                                   size_t fieldn,
747                                                   const StructDef *parent_struct_def);
748   FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
749   FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
750                                           BaseType req, bool *destmatch);
751   FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
752   FLATBUFFERS_CHECKED_ERROR TokenError();
753   FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now);
754   FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result);
755   StructDef *LookupCreateStruct(const std::string &name,
756                                 bool create_if_new = true,
757                                 bool definition = false);
758   FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
759   FLATBUFFERS_CHECKED_ERROR ParseNamespace();
760   FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
761                                         StructDef **dest);
762   FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
763                                       bool is_union,
764                                       EnumDef **dest);
765   FLATBUFFERS_CHECKED_ERROR ParseDecl();
766   FLATBUFFERS_CHECKED_ERROR ParseService();
767   FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
768                                              bool isextend, bool inside_oneof);
769   FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
770   FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
771   FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
772   FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
773   FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
774   FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
775   FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
776   FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
777                                            const char *source_filename);
778   FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
779                                     const char **include_paths,
780                                     const char *source_filename);
781   FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
782                                            const char **include_paths,
783                                            const char *source_filename,
784                                            const char *include_filename);
785   FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
786                                        StructDef *struct_def,
787                                        const char *suffix,
788                                        BaseType baseType);
789 
790   bool SupportsAdvancedUnionFeatures() const;
791   Namespace *UniqueNamespace(Namespace *ns);
792 
793   FLATBUFFERS_CHECKED_ERROR RecurseError();
794   template<typename F> CheckedError Recurse(F f);
795 
796  public:
797   SymbolTable<Type> types_;
798   SymbolTable<StructDef> structs_;
799   SymbolTable<EnumDef> enums_;
800   SymbolTable<ServiceDef> services_;
801   std::vector<Namespace *> namespaces_;
802   Namespace *current_namespace_;
803   Namespace *empty_namespace_;
804   std::string error_;         // User readable error_ if Parse() == false
805 
806   FlatBufferBuilder builder_;  // any data contained in the file
807   StructDef *root_struct_def_;
808   std::string file_identifier_;
809   std::string file_extension_;
810 
811   std::map<std::string, std::string> included_files_;
812   std::map<std::string, std::set<std::string>> files_included_per_file_;
813   std::vector<std::string> native_included_files_;
814 
815   std::map<std::string, bool> known_attributes_;
816 
817   IDLOptions opts;
818   bool uses_flexbuffers_;
819 
820  private:
821   const char *source_;
822 
823   std::string file_being_parsed_;
824 
825   std::vector<std::pair<Value, FieldDef *>> field_stack_;
826 
827   int anonymous_counter;
828   int recurse_protection_counter;
829 };
830 
831 // Utility functions for multiple generators:
832 
833 extern std::string MakeCamel(const std::string &in, bool first = true);
834 
835 // Generate text (JSON) from a given FlatBuffer, and a given Parser
836 // object that has been populated with the corresponding schema.
837 // If ident_step is 0, no indentation will be generated. Additionally,
838 // if it is less than 0, no linefeeds will be generated either.
839 // See idl_gen_text.cpp.
840 // strict_json adds "quotes" around field names if true.
841 // If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
842 // byte arrays in String values), returns false.
843 extern bool GenerateTextFromTable(const Parser &parser,
844                                   const void *table,
845                                   const std::string &tablename,
846                                   std::string *text);
847 extern bool GenerateText(const Parser &parser,
848                          const void *flatbuffer,
849                          std::string *text);
850 extern bool GenerateTextFile(const Parser &parser,
851                              const std::string &path,
852                              const std::string &file_name);
853 
854 // Generate binary files from a given FlatBuffer, and a given Parser
855 // object that has been populated with the corresponding schema.
856 // See idl_gen_general.cpp.
857 extern bool GenerateBinary(const Parser &parser,
858                            const std::string &path,
859                            const std::string &file_name);
860 
861 // Generate a C++ header from the definitions in the Parser object.
862 // See idl_gen_cpp.
863 extern bool GenerateCPP(const Parser &parser,
864                         const std::string &path,
865                         const std::string &file_name);
866 
867 extern bool GenerateDart(const Parser &parser,
868                          const std::string &path,
869                          const std::string &file_name);
870 
871 // Generate JavaScript or TypeScript code from the definitions in the Parser object.
872 // See idl_gen_js.
873 extern bool GenerateJSTS(const Parser &parser,
874                        const std::string &path,
875                        const std::string &file_name);
876 
877 // Generate Go files from the definitions in the Parser object.
878 // See idl_gen_go.cpp.
879 extern bool GenerateGo(const Parser &parser,
880                        const std::string &path,
881                        const std::string &file_name);
882 
883 // Generate Php code from the definitions in the Parser object.
884 // See idl_gen_php.
885 extern bool GeneratePhp(const Parser &parser,
886                         const std::string &path,
887                         const std::string &file_name);
888 
889 // Generate Python files from the definitions in the Parser object.
890 // See idl_gen_python.cpp.
891 extern bool GeneratePython(const Parser &parser,
892                            const std::string &path,
893                            const std::string &file_name);
894 
895 // Generate Lobster files from the definitions in the Parser object.
896 // See idl_gen_lobster.cpp.
897 extern bool GenerateLobster(const Parser &parser,
898                             const std::string &path,
899                             const std::string &file_name);
900 
901 // Generate Lua files from the definitions in the Parser object.
902 // See idl_gen_lua.cpp.
903 extern bool GenerateLua(const Parser &parser,
904                       const std::string &path,
905                       const std::string &file_name);
906 
907 // Generate Rust files from the definitions in the Parser object.
908 // See idl_gen_rust.cpp.
909 extern bool GenerateRust(const Parser &parser,
910                          const std::string &path,
911                          const std::string &file_name);
912 
913 // Generate Json schema file
914 // See idl_gen_json_schema.cpp.
915 extern bool GenerateJsonSchema(const Parser &parser,
916                            const std::string &path,
917                            const std::string &file_name);
918 
919 // Generate Java/C#/.. files from the definitions in the Parser object.
920 // See idl_gen_general.cpp.
921 extern bool GenerateGeneral(const Parser &parser,
922                             const std::string &path,
923                             const std::string &file_name);
924 
925 // Generate a schema file from the internal representation, useful after
926 // parsing a .proto schema.
927 extern std::string GenerateFBS(const Parser &parser,
928                                const std::string &file_name);
929 extern bool GenerateFBS(const Parser &parser,
930                         const std::string &path,
931                         const std::string &file_name);
932 
933 // Generate a make rule for the generated JavaScript or TypeScript code.
934 // See idl_gen_js.cpp.
935 extern std::string JSTSMakeRule(const Parser &parser,
936                               const std::string &path,
937                               const std::string &file_name);
938 
939 // Generate a make rule for the generated C++ header.
940 // See idl_gen_cpp.cpp.
941 extern std::string CPPMakeRule(const Parser &parser,
942                                const std::string &path,
943                                const std::string &file_name);
944 
945 // Generate a make rule for the generated Dart code
946 // see idl_gen_dart.cpp
947 extern std::string DartMakeRule(const Parser &parser,
948                                 const std::string &path,
949                                 const std::string &file_name);
950 
951 // Generate a make rule for the generated Rust code.
952 // See idl_gen_rust.cpp.
953 extern std::string RustMakeRule(const Parser &parser,
954                                 const std::string &path,
955                                 const std::string &file_name);
956 
957 // Generate a make rule for the generated Java/C#/... files.
958 // See idl_gen_general.cpp.
959 extern std::string GeneralMakeRule(const Parser &parser,
960                                    const std::string &path,
961                                    const std::string &file_name);
962 
963 // Generate a make rule for the generated text (JSON) files.
964 // See idl_gen_text.cpp.
965 extern std::string TextMakeRule(const Parser &parser,
966                                 const std::string &path,
967                                 const std::string &file_names);
968 
969 // Generate a make rule for the generated binary files.
970 // See idl_gen_general.cpp.
971 extern std::string BinaryMakeRule(const Parser &parser,
972                                   const std::string &path,
973                                   const std::string &file_name);
974 
975 // Generate GRPC Cpp interfaces.
976 // See idl_gen_grpc.cpp.
977 bool GenerateCppGRPC(const Parser &parser,
978                      const std::string &path,
979                      const std::string &file_name);
980 
981 // Generate GRPC Go interfaces.
982 // See idl_gen_grpc.cpp.
983 bool GenerateGoGRPC(const Parser &parser,
984                     const std::string &path,
985                     const std::string &file_name);
986 
987 // Generate GRPC Java classes.
988 // See idl_gen_grpc.cpp
989 bool GenerateJavaGRPC(const Parser &parser,
990                       const std::string &path,
991                       const std::string &file_name);
992 
993 }  // namespace flatbuffers
994 
995 #endif  // FLATBUFFERS_IDL_H_
996