Home | History | Annotate | Download | only in flatbuffers
      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);
    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; }
    117 inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
    118                                            t <= BASE_TYPE_ULONG; }
    119 inline bool IsFloat  (BaseType t) { return t == BASE_TYPE_FLOAT ||
    120                                            t == BASE_TYPE_DOUBLE; }
    121 inline bool IsLong   (BaseType t) { return t == BASE_TYPE_LONG ||
    122                                            t == BASE_TYPE_ULONG; }
    123 inline bool IsBool   (BaseType t) { return t == BASE_TYPE_BOOL; }
    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 
    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)
    142       : 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 
    152   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 {
    167   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:
    179   ~SymbolTable() {
    180     for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
    181   }
    182 
    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 
    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 
    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 {
    214   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 {
    229   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 {
    257   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 {
    287   StructDef()
    288       : fixed(false),
    289         predecl(true),
    290         sortbysize(true),
    291         has_key(false),
    292         minalign(1),
    293         bytesize(0) {}
    294 
    295   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 
    318 inline bool IsStruct(const Type &type) {
    319   return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
    320 }
    321 
    322 inline size_t InlineSize(const Type &type) {
    323   return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
    324 }
    325 
    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 {
    331   EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
    332   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);
    337 
    338   std::string name;
    339   std::vector<std::string> doc_comment;
    340   int64_t value;
    341   Type union_type;
    342 };
    343 
    344 struct EnumDef : public Definition {
    345   EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
    346 
    347   EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
    348     for (auto it = vals.vec.begin() +
    349                    static_cast<int>(is_union && skip_union_default);
    350          it != vals.vec.end(); ++it) {
    351       if ((*it)->value == enum_idx) { return *it; }
    352     }
    353     return nullptr;
    354   }
    355 
    356   Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
    357 
    358   bool Deserialize(Parser &parser, const reflection::Enum *values);
    359 
    360   SymbolTable<EnumVal> vals;
    361   bool is_union;
    362   // Type is a union which uses type aliases where at least one type is
    363   // available under two different names.
    364   bool uses_multiple_type_instances;
    365   Type underlying_type;
    366 };
    367 
    368 inline bool EqualByName(const Type &a, const Type &b) {
    369   return a.base_type == b.base_type && a.element == b.element &&
    370          (a.struct_def == b.struct_def ||
    371           a.struct_def->name == b.struct_def->name) &&
    372          (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
    373 }
    374 
    375 struct RPCCall : public Definition {
    376   Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
    377 
    378   bool Deserialize(Parser &parser, const reflection::RPCCall *call);
    379 
    380   StructDef *request, *response;
    381 };
    382 
    383 struct ServiceDef : public Definition {
    384   Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
    385   bool Deserialize(Parser &parser, const reflection::Service *service);
    386 
    387   SymbolTable<RPCCall> calls;
    388 };
    389 
    390 // Container of options that may apply to any of the source/text generators.
    391 struct IDLOptions {
    392   bool strict_json;
    393   bool skip_js_exports;
    394   bool use_goog_js_export_format;
    395   bool use_ES6_js_export_format;
    396   bool output_default_scalars_in_json;
    397   int indent_step;
    398   bool output_enum_identifiers;
    399   bool prefixed_enums;
    400   bool scoped_enums;
    401   bool include_dependence_headers;
    402   bool mutable_buffer;
    403   bool one_file;
    404   bool proto_mode;
    405   bool proto_oneof_union;
    406   bool generate_all;
    407   bool skip_unexpected_fields_in_json;
    408   bool generate_name_strings;
    409   bool generate_object_based_api;
    410   bool gen_compare;
    411   std::string cpp_object_api_pointer_type;
    412   std::string cpp_object_api_string_type;
    413   bool gen_nullable;
    414   bool gen_generated;
    415   std::string object_prefix;
    416   std::string object_suffix;
    417   bool union_value_namespacing;
    418   bool allow_non_utf8;
    419   bool natural_utf8;
    420   std::string include_prefix;
    421   bool keep_include_path;
    422   bool binary_schema_comments;
    423   bool binary_schema_builtins;
    424   bool skip_flatbuffers_import;
    425   std::string go_import;
    426   std::string go_namespace;
    427   bool reexport_ts_modules;
    428   bool js_ts_short_names;
    429   bool protobuf_ascii_alike;
    430   bool size_prefixed;
    431   std::string root_type;
    432   bool force_defaults;
    433 
    434   // Possible options for the more general generator below.
    435   enum Language {
    436     kJava = 1 << 0,
    437     kCSharp = 1 << 1,
    438     kGo = 1 << 2,
    439     kCpp = 1 << 3,
    440     kJs = 1 << 4,
    441     kPython = 1 << 5,
    442     kPhp = 1 << 6,
    443     kJson = 1 << 7,
    444     kBinary = 1 << 8,
    445     kTs = 1 << 9,
    446     kJsonSchema = 1 << 10,
    447     kDart = 1 << 11,
    448     kLua = 1 << 12,
    449     kLobster = 1 << 13,
    450     kRust = 1 << 14,
    451     kMAX
    452   };
    453 
    454   Language lang;
    455 
    456   enum MiniReflect { kNone, kTypes, kTypesAndNames };
    457 
    458   MiniReflect mini_reflect;
    459 
    460   // The corresponding language bit will be set if a language is included
    461   // for code generation.
    462   unsigned long lang_to_generate;
    463 
    464   // If set (default behavior), empty string and vector fields will be set to
    465   // nullptr to make the flatbuffer more compact.
    466   bool set_empty_to_null;
    467 
    468   IDLOptions()
    469       : strict_json(false),
    470         skip_js_exports(false),
    471         use_goog_js_export_format(false),
    472         use_ES6_js_export_format(false),
    473         output_default_scalars_in_json(false),
    474         indent_step(2),
    475         output_enum_identifiers(true),
    476         prefixed_enums(true),
    477         scoped_enums(false),
    478         include_dependence_headers(true),
    479         mutable_buffer(false),
    480         one_file(false),
    481         proto_mode(false),
    482         proto_oneof_union(false),
    483         generate_all(false),
    484         skip_unexpected_fields_in_json(false),
    485         generate_name_strings(false),
    486         generate_object_based_api(false),
    487         gen_compare(false),
    488         cpp_object_api_pointer_type("std::unique_ptr"),
    489         gen_nullable(false),
    490         gen_generated(false),
    491         object_suffix("T"),
    492         union_value_namespacing(true),
    493         allow_non_utf8(false),
    494         natural_utf8(false),
    495         keep_include_path(false),
    496         binary_schema_comments(false),
    497         binary_schema_builtins(false),
    498         skip_flatbuffers_import(false),
    499         reexport_ts_modules(true),
    500         js_ts_short_names(false),
    501         protobuf_ascii_alike(false),
    502         size_prefixed(false),
    503         force_defaults(false),
    504         lang(IDLOptions::kJava),
    505         mini_reflect(IDLOptions::kNone),
    506         lang_to_generate(0),
    507         set_empty_to_null(true) {}
    508 };
    509 
    510 // This encapsulates where the parser is in the current source file.
    511 struct ParserState {
    512   ParserState()
    513       : cursor_(nullptr),
    514         line_start_(nullptr),
    515         line_(0),
    516         token_(-1),
    517         attr_is_trivial_ascii_string_(true) {}
    518 
    519  protected:
    520   void ResetState(const char *source) {
    521     cursor_ = source;
    522     line_ = 0;
    523     MarkNewLine();
    524   }
    525 
    526   void MarkNewLine() {
    527     line_start_ = cursor_;
    528     line_ += 1;
    529   }
    530 
    531   int64_t CursorPosition() const {
    532     FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
    533     return static_cast<int64_t>(cursor_ - line_start_);
    534   }
    535 
    536   const char *cursor_;
    537   const char *line_start_;
    538   int line_;  // the current line being parsed
    539   int token_;
    540 
    541   // Flag: text in attribute_ is true ASCII string without escape
    542   // sequences. Only printable ASCII (without [\t\r\n]).
    543   // Used for number-in-string (and base64 string in future).
    544   bool attr_is_trivial_ascii_string_;
    545   std::string attribute_;
    546   std::vector<std::string> doc_comment_;
    547 };
    548 
    549 // A way to make error propagation less error prone by requiring values to be
    550 // checked.
    551 // Once you create a value of this type you must either:
    552 // - Call Check() on it.
    553 // - Copy or assign it to another value.
    554 // Failure to do so leads to an assert.
    555 // This guarantees that this as return value cannot be ignored.
    556 class CheckedError {
    557  public:
    558   explicit CheckedError(bool error)
    559       : is_error_(error), has_been_checked_(false) {}
    560 
    561   CheckedError &operator=(const CheckedError &other) {
    562     is_error_ = other.is_error_;
    563     has_been_checked_ = false;
    564     other.has_been_checked_ = true;
    565     return *this;
    566   }
    567 
    568   CheckedError(const CheckedError &other) {
    569     *this = other;  // Use assignment operator.
    570   }
    571 
    572   ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
    573 
    574   bool Check() {
    575     has_been_checked_ = true;
    576     return is_error_;
    577   }
    578 
    579  private:
    580   bool is_error_;
    581   mutable bool has_been_checked_;
    582 };
    583 
    584 // Additionally, in GCC we can get these errors statically, for additional
    585 // assurance:
    586 // clang-format off
    587 #ifdef __GNUC__
    588 #define FLATBUFFERS_CHECKED_ERROR CheckedError \
    589           __attribute__((warn_unused_result))
    590 #else
    591 #define FLATBUFFERS_CHECKED_ERROR CheckedError
    592 #endif
    593 // clang-format on
    594 
    595 class Parser : public ParserState {
    596  public:
    597   explicit Parser(const IDLOptions &options = IDLOptions())
    598       : current_namespace_(nullptr),
    599         empty_namespace_(nullptr),
    600         root_struct_def_(nullptr),
    601         opts(options),
    602         uses_flexbuffers_(false),
    603         source_(nullptr),
    604         anonymous_counter(0),
    605         recurse_protection_counter(0) {
    606     if (opts.force_defaults) {
    607       builder_.ForceDefaults(true);
    608     }
    609     // Start out with the empty namespace being current.
    610     empty_namespace_ = new Namespace();
    611     namespaces_.push_back(empty_namespace_);
    612     current_namespace_ = empty_namespace_;
    613     known_attributes_["deprecated"] = true;
    614     known_attributes_["required"] = true;
    615     known_attributes_["key"] = true;
    616     known_attributes_["shared"] = true;
    617     known_attributes_["hash"] = true;
    618     known_attributes_["id"] = true;
    619     known_attributes_["force_align"] = true;
    620     known_attributes_["bit_flags"] = true;
    621     known_attributes_["original_order"] = true;
    622     known_attributes_["nested_flatbuffer"] = true;
    623     known_attributes_["csharp_partial"] = true;
    624     known_attributes_["streaming"] = true;
    625     known_attributes_["idempotent"] = true;
    626     known_attributes_["cpp_type"] = true;
    627     known_attributes_["cpp_ptr_type"] = true;
    628     known_attributes_["cpp_ptr_type_get"] = true;
    629     known_attributes_["cpp_str_type"] = true;
    630     known_attributes_["native_inline"] = true;
    631     known_attributes_["native_custom_alloc"] = true;
    632     known_attributes_["native_type"] = true;
    633     known_attributes_["native_default"] = true;
    634     known_attributes_["flexbuffer"] = true;
    635     known_attributes_["private"] = true;
    636   }
    637 
    638   ~Parser() {
    639     for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
    640       delete *it;
    641     }
    642   }
    643 
    644   // Parse the string containing either schema or JSON data, which will
    645   // populate the SymbolTable's or the FlatBufferBuilder above.
    646   // include_paths is used to resolve any include statements, and typically
    647   // should at least include the project path (where you loaded source_ from).
    648   // include_paths must be nullptr terminated if specified.
    649   // If include_paths is nullptr, it will attempt to load from the current
    650   // directory.
    651   // If the source was loaded from a file and isn't an include file,
    652   // supply its name in source_filename.
    653   // All paths specified in this call must be in posix format, if you accept
    654   // paths from user input, please call PosixPath on them first.
    655   bool Parse(const char *_source, const char **include_paths = nullptr,
    656              const char *source_filename = nullptr);
    657 
    658   // Set the root type. May override the one set in the schema.
    659   bool SetRootType(const char *name);
    660 
    661   // Mark all definitions as already having code generated.
    662   void MarkGenerated();
    663 
    664   // Get the files recursively included by the given file. The returned
    665   // container will have at least the given file.
    666   std::set<std::string> GetIncludedFilesRecursive(
    667       const std::string &file_name) const;
    668 
    669   // Fills builder_ with a binary version of the schema parsed.
    670   // See reflection/reflection.fbs
    671   void Serialize();
    672 
    673   // Deserialize a schema buffer
    674   bool Deserialize(const uint8_t *buf, const size_t size);
    675 
    676   // Fills internal structure as if the schema passed had been loaded by parsing
    677   // with Parse except that included filenames will not be populated.
    678   bool Deserialize(const reflection::Schema* schema);
    679 
    680   Type* DeserializeType(const reflection::Type* type);
    681 
    682   // Checks that the schema represented by this parser is a safe evolution
    683   // of the schema provided. Returns non-empty error on any problems.
    684   std::string ConformTo(const Parser &base);
    685 
    686   // Similar to Parse(), but now only accepts JSON to be parsed into a
    687   // FlexBuffer.
    688   bool ParseFlexBuffer(const char *source, const char *source_filename,
    689                        flexbuffers::Builder *builder);
    690 
    691   FLATBUFFERS_CHECKED_ERROR InvalidNumber(const char *number,
    692                                           const std::string &msg);
    693 
    694   StructDef *LookupStruct(const std::string &id) const;
    695 
    696   std::string UnqualifiedName(std::string fullQualifiedName);
    697 
    698  private:
    699   void Message(const std::string &msg);
    700   void Warning(const std::string &msg);
    701   FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
    702   FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
    703   FLATBUFFERS_CHECKED_ERROR Next();
    704   FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
    705   bool Is(int t) const;
    706   bool IsIdent(const char *id) const;
    707   FLATBUFFERS_CHECKED_ERROR Expect(int t);
    708   std::string TokenToStringId(int t) const;
    709   EnumDef *LookupEnum(const std::string &id);
    710   FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
    711                                              std::string *last);
    712   FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
    713   FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
    714   FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
    715                                      const std::string &name, const Type &type,
    716                                      FieldDef **dest);
    717   FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
    718   FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
    719   FLATBUFFERS_CHECKED_ERROR ParseComma();
    720   FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
    721                                           size_t parent_fieldn,
    722                                           const StructDef *parent_struct_def);
    723   template<typename F>
    724   FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
    725                                                  const StructDef *struct_def,
    726                                                  F body);
    727   FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
    728                                        std::string *value, uoffset_t *ovalue);
    729   void SerializeStruct(const StructDef &struct_def, const Value &val);
    730   template<typename F>
    731   FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count, F body);
    732   FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
    733   FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
    734                                                   size_t fieldn,
    735                                                   const StructDef *parent_struct_def);
    736   FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
    737   FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
    738                                           BaseType req, bool *destmatch);
    739   FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
    740   FLATBUFFERS_CHECKED_ERROR TokenError();
    741   FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now);
    742   FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
    743   StructDef *LookupCreateStruct(const std::string &name,
    744                                 bool create_if_new = true,
    745                                 bool definition = false);
    746   FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
    747   FLATBUFFERS_CHECKED_ERROR ParseNamespace();
    748   FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
    749                                         StructDef **dest);
    750   FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
    751                                       bool is_union,
    752                                       EnumDef **dest);
    753   FLATBUFFERS_CHECKED_ERROR ParseDecl();
    754   FLATBUFFERS_CHECKED_ERROR ParseService();
    755   FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
    756                                              bool isextend, bool inside_oneof);
    757   FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
    758   FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
    759   FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
    760   FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
    761   FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
    762   FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
    763   FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
    764   FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
    765                                            const char *source_filename);
    766   FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
    767                                     const char **include_paths,
    768                                     const char *source_filename);
    769   FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
    770                                            const char **include_paths,
    771                                            const char *source_filename,
    772                                            const char *include_filename);
    773   FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
    774                                        StructDef *struct_def,
    775                                        const char *suffix,
    776                                        BaseType baseType);
    777 
    778   bool SupportsVectorOfUnions() const;
    779   Namespace *UniqueNamespace(Namespace *ns);
    780 
    781   FLATBUFFERS_CHECKED_ERROR RecurseError();
    782   template<typename F> CheckedError Recurse(F f);
    783 
    784  public:
    785   SymbolTable<Type> types_;
    786   SymbolTable<StructDef> structs_;
    787   SymbolTable<EnumDef> enums_;
    788   SymbolTable<ServiceDef> services_;
    789   std::vector<Namespace *> namespaces_;
    790   Namespace *current_namespace_;
    791   Namespace *empty_namespace_;
    792   std::string error_;         // User readable error_ if Parse() == false
    793 
    794   FlatBufferBuilder builder_;  // any data contained in the file
    795   StructDef *root_struct_def_;
    796   std::string file_identifier_;
    797   std::string file_extension_;
    798 
    799   std::map<std::string, std::string> included_files_;
    800   std::map<std::string, std::set<std::string>> files_included_per_file_;
    801   std::vector<std::string> native_included_files_;
    802 
    803   std::map<std::string, bool> known_attributes_;
    804 
    805   IDLOptions opts;
    806   bool uses_flexbuffers_;
    807 
    808  private:
    809   const char *source_;
    810 
    811   std::string file_being_parsed_;
    812 
    813   std::vector<std::pair<Value, FieldDef *>> field_stack_;
    814 
    815   int anonymous_counter;
    816   int recurse_protection_counter;
    817 };
    818 
    819 // Utility functions for multiple generators:
    820 
    821 extern std::string MakeCamel(const std::string &in, bool first = true);
    822 
    823 // Generate text (JSON) from a given FlatBuffer, and a given Parser
    824 // object that has been populated with the corresponding schema.
    825 // If ident_step is 0, no indentation will be generated. Additionally,
    826 // if it is less than 0, no linefeeds will be generated either.
    827 // See idl_gen_text.cpp.
    828 // strict_json adds "quotes" around field names if true.
    829 // If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
    830 // byte arrays in String values), returns false.
    831 extern bool GenerateText(const Parser &parser,
    832                          const void *flatbuffer,
    833                          std::string *text);
    834 extern bool GenerateTextFile(const Parser &parser,
    835                              const std::string &path,
    836                              const std::string &file_name);
    837 
    838 // Generate binary files from a given FlatBuffer, and a given Parser
    839 // object that has been populated with the corresponding schema.
    840 // See idl_gen_general.cpp.
    841 extern bool GenerateBinary(const Parser &parser,
    842                            const std::string &path,
    843                            const std::string &file_name);
    844 
    845 // Generate a C++ header from the definitions in the Parser object.
    846 // See idl_gen_cpp.
    847 extern bool GenerateCPP(const Parser &parser,
    848                         const std::string &path,
    849                         const std::string &file_name);
    850 
    851 extern bool GenerateDart(const Parser &parser,
    852                          const std::string &path,
    853                          const std::string &file_name);
    854 
    855 // Generate JavaScript or TypeScript code from the definitions in the Parser object.
    856 // See idl_gen_js.
    857 extern bool GenerateJSTS(const Parser &parser,
    858                        const std::string &path,
    859                        const std::string &file_name);
    860 
    861 // Generate Go files from the definitions in the Parser object.
    862 // See idl_gen_go.cpp.
    863 extern bool GenerateGo(const Parser &parser,
    864                        const std::string &path,
    865                        const std::string &file_name);
    866 
    867 // Generate Php code from the definitions in the Parser object.
    868 // See idl_gen_php.
    869 extern bool GeneratePhp(const Parser &parser,
    870                         const std::string &path,
    871                         const std::string &file_name);
    872 
    873 // Generate Python files from the definitions in the Parser object.
    874 // See idl_gen_python.cpp.
    875 extern bool GeneratePython(const Parser &parser,
    876                            const std::string &path,
    877                            const std::string &file_name);
    878 
    879 // Generate Lobster files from the definitions in the Parser object.
    880 // See idl_gen_lobster.cpp.
    881 extern bool GenerateLobster(const Parser &parser,
    882                             const std::string &path,
    883                             const std::string &file_name);
    884 
    885 // Generate Lua files from the definitions in the Parser object.
    886 // See idl_gen_lua.cpp.
    887 extern bool GenerateLua(const Parser &parser,
    888                       const std::string &path,
    889                       const std::string &file_name);
    890 
    891 // Generate Rust files from the definitions in the Parser object.
    892 // See idl_gen_rust.cpp.
    893 extern bool GenerateRust(const Parser &parser,
    894                          const std::string &path,
    895                          const std::string &file_name);
    896 
    897 // Generate Json schema file
    898 // See idl_gen_json_schema.cpp.
    899 extern bool GenerateJsonSchema(const Parser &parser,
    900                            const std::string &path,
    901                            const std::string &file_name);
    902 
    903 // Generate Java/C#/.. files from the definitions in the Parser object.
    904 // See idl_gen_general.cpp.
    905 extern bool GenerateGeneral(const Parser &parser,
    906                             const std::string &path,
    907                             const std::string &file_name);
    908 
    909 // Generate a schema file from the internal representation, useful after
    910 // parsing a .proto schema.
    911 extern std::string GenerateFBS(const Parser &parser,
    912                                const std::string &file_name);
    913 extern bool GenerateFBS(const Parser &parser,
    914                         const std::string &path,
    915                         const std::string &file_name);
    916 
    917 // Generate a make rule for the generated JavaScript or TypeScript code.
    918 // See idl_gen_js.cpp.
    919 extern std::string JSTSMakeRule(const Parser &parser,
    920                               const std::string &path,
    921                               const std::string &file_name);
    922 
    923 // Generate a make rule for the generated C++ header.
    924 // See idl_gen_cpp.cpp.
    925 extern std::string CPPMakeRule(const Parser &parser,
    926                                const std::string &path,
    927                                const std::string &file_name);
    928 
    929 // Generate a make rule for the generated Dart code
    930 // see idl_gen_dart.cpp
    931 extern std::string DartMakeRule(const Parser &parser,
    932                                 const std::string &path,
    933                                 const std::string &file_name);
    934 
    935 // Generate a make rule for the generated Rust code.
    936 // See idl_gen_rust.cpp.
    937 extern std::string RustMakeRule(const Parser &parser,
    938                                 const std::string &path,
    939                                 const std::string &file_name);
    940 
    941 // Generate a make rule for the generated Java/C#/... files.
    942 // See idl_gen_general.cpp.
    943 extern std::string GeneralMakeRule(const Parser &parser,
    944                                    const std::string &path,
    945                                    const std::string &file_name);
    946 
    947 // Generate a make rule for the generated text (JSON) files.
    948 // See idl_gen_text.cpp.
    949 extern std::string TextMakeRule(const Parser &parser,
    950                                 const std::string &path,
    951                                 const std::string &file_names);
    952 
    953 // Generate a make rule for the generated binary files.
    954 // See idl_gen_general.cpp.
    955 extern std::string BinaryMakeRule(const Parser &parser,
    956                                   const std::string &path,
    957                                   const std::string &file_name);
    958 
    959 // Generate GRPC Cpp interfaces.
    960 // See idl_gen_grpc.cpp.
    961 bool GenerateCppGRPC(const Parser &parser,
    962                      const std::string &path,
    963                      const std::string &file_name);
    964 
    965 // Generate GRPC Go interfaces.
    966 // See idl_gen_grpc.cpp.
    967 bool GenerateGoGRPC(const Parser &parser,
    968                     const std::string &path,
    969                     const std::string &file_name);
    970 
    971 // Generate GRPC Java classes.
    972 // See idl_gen_grpc.cpp
    973 bool GenerateJavaGRPC(const Parser &parser,
    974                       const std::string &path,
    975                       const std::string &file_name);
    976 
    977 }  // namespace flatbuffers
    978 
    979 #endif  // FLATBUFFERS_IDL_H_
    980