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