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