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