github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/_include/flatbuffers/idl.h (about)

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