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