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
37namespace 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/*
74switch (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
91enum 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
104inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
105                                           t <= BASE_TYPE_DOUBLE; }
106inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
107                                           t <= BASE_TYPE_ULONG; }
108inline bool IsFloat  (BaseType t) { return t == BASE_TYPE_FLOAT ||
109                                           t == BASE_TYPE_DOUBLE; }
110inline bool IsLong   (BaseType t) { return t == BASE_TYPE_LONG ||
111                                           t == BASE_TYPE_ULONG; }
112inline bool IsBool   (BaseType t) { return t == BASE_TYPE_BOOL; }
113
114extern const char *const kTypeNames[];
115extern const char kTypeSizes[];
116
117inline size_t SizeOf(BaseType t) {
118  return kTypeSizes[t];
119}
120
121struct StructDef;
122struct EnumDef;
123class Parser;
124
125// Represents any type in the IDL, which is a combination of the BaseType
126// and additional information for vectors/structs_.
127struct 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.
153struct 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.
163template<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.
201struct 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_).
217struct 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
239struct 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
259struct 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
290inline bool IsStruct(const Type &type) {
291  return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
292}
293
294inline size_t InlineSize(const Type &type) {
295  return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
296}
297
298inline size_t InlineAlignment(const Type &type) {
299  return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
300}
301
302struct 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
314struct 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
337inline 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
345struct RPCCall {
346  std::string name;
347  SymbolTable<Value> attributes;
348  StructDef *request, *response;
349};
350
351struct ServiceDef : public Definition {
352  SymbolTable<RPCCall> calls;
353};
354
355// Container of options that may apply to any of the source/text generators.
356struct 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.
446struct 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.
465class 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
499class 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
583private:
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
716extern 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.
726extern bool GenerateText(const Parser &parser,
727                         const void *flatbuffer,
728                         std::string *text);
729extern 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.
736extern 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.
742extern std::string GenerateCPP(const Parser &parser,
743                               const std::string &include_guard_ident);
744extern 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.
750extern std::string GenerateJS(const Parser &parser);
751extern 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.
757extern 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.
763extern 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.
769extern 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.
775extern 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.
781extern 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.
787extern 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.
793extern 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.
799extern std::string GenerateFBS(const Parser &parser,
800                               const std::string &file_name);
801extern 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.
807extern 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.
813extern 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.
819extern 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.
825extern 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.
831extern 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.
837bool 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.
843bool 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