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 scheme, or json, or flexbuffer.
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 (potentially 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 key(false),
295 shared(false),
296 native_inline(false),
297 flexbuffer(false),
298 presence(kDefault),
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
IsScalarOptionalFieldDef307 bool IsScalarOptional() const {
308 return IsScalar(value.type.base_type) && IsOptional();
309 }
IsOptionalFieldDef310 bool IsOptional() const {
311 return presence == kOptional;
312 }
IsRequiredFieldDef313 bool IsRequired() const {
314 return presence == kRequired;
315 }
IsDefaultFieldDef316 bool IsDefault() const {
317 return presence == kDefault;
318 }
319
320 Value value;
321 bool deprecated; // Field is allowed to be present in old data, but can't be.
322 // written in new data nor accessed in new code.
323 bool key; // Field functions as a key for creating sorted vectors.
324 bool shared; // Field will be using string pooling (i.e. CreateSharedString)
325 // as default serialization behavior if field is a string.
326 bool native_inline; // Field will be defined inline (instead of as a pointer)
327 // for native tables if field is a struct.
328 bool flexbuffer; // This field contains FlexBuffer data.
329
330 enum Presence {
331 // Field must always be present.
332 kRequired,
333 // Non-presence should be signalled to and controlled by users.
334 kOptional,
335 // Non-presence is hidden from users.
336 // Implementations may omit writing default values.
337 kDefault,
338 };
MakeFieldPresenceFieldDef339 Presence static MakeFieldPresence(bool optional, bool required) {
340 FLATBUFFERS_ASSERT(!(required && optional));
341 // clang-format off
342 return required ? FieldDef::kRequired
343 : optional ? FieldDef::kOptional
344 : FieldDef::kDefault;
345 // clang-format on
346 }
347 Presence presence;
348
349 StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
350 size_t padding; // Bytes to always pad after this field.
351 };
352
353 struct StructDef : public Definition {
StructDefStructDef354 StructDef()
355 : fixed(false),
356 predecl(true),
357 sortbysize(true),
358 has_key(false),
359 minalign(1),
360 bytesize(0) {}
361
PadLastFieldStructDef362 void PadLastField(size_t min_align) {
363 auto padding = PaddingBytes(bytesize, min_align);
364 bytesize += padding;
365 if (fields.vec.size()) fields.vec.back()->padding = padding;
366 }
367
368 Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
369 const Parser &parser) const;
370
371 bool Deserialize(Parser &parser, const reflection::Object *object);
372
373 SymbolTable<FieldDef> fields;
374
375 bool fixed; // If it's struct, not a table.
376 bool predecl; // If it's used before it was defined.
377 bool sortbysize; // Whether fields come in the declaration or size order.
378 bool has_key; // It has a key field.
379 size_t minalign; // What the whole object needs to be aligned to.
380 size_t bytesize; // Size if fixed.
381
382 flatbuffers::unique_ptr<std::string> original_location;
383 };
384
385 struct EnumDef;
386 struct EnumValBuilder;
387
388 struct EnumVal {
389 Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
390 const Parser &parser) const;
391
392 bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
393
GetAsUInt64EnumVal394 uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
GetAsInt64EnumVal395 int64_t GetAsInt64() const { return value; }
IsZeroEnumVal396 bool IsZero() const { return 0 == value; }
IsNonZeroEnumVal397 bool IsNonZero() const { return !IsZero(); }
398
399 std::string name;
400 std::vector<std::string> doc_comment;
401 Type union_type;
402
403 private:
404 friend EnumDef;
405 friend EnumValBuilder;
406 friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
407
EnumValEnumVal408 EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumValEnumVal409 EnumVal() : value(0) {}
410
411 int64_t value;
412 };
413
414 struct EnumDef : public Definition {
EnumDefEnumDef415 EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
416
417 Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
418 const Parser &parser) const;
419
420 bool Deserialize(Parser &parser, const reflection::Enum *values);
421
422 template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
423 void SortByValue();
424 void RemoveDuplicates();
425
426 std::string AllFlags() const;
427 const EnumVal *MinValue() const;
428 const EnumVal *MaxValue() const;
429 // Returns the number of integer steps from v1 to v2.
430 uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
431 // Returns the number of integer steps from Min to Max.
DistanceEnumDef432 uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
433
434 EnumVal *ReverseLookup(int64_t enum_idx,
435 bool skip_union_default = false) const;
436 EnumVal *FindByValue(const std::string &constant) const;
437
ToStringEnumDef438 std::string ToString(const EnumVal &ev) const {
439 return IsUInt64() ? NumToString(ev.GetAsUInt64())
440 : NumToString(ev.GetAsInt64());
441 }
442
sizeEnumDef443 size_t size() const { return vals.vec.size(); }
444
ValsEnumDef445 const std::vector<EnumVal *> &Vals() const { return vals.vec; }
446
LookupEnumDef447 const EnumVal *Lookup(const std::string &enum_name) const {
448 return vals.Lookup(enum_name);
449 }
450
451 bool is_union;
452 // Type is a union which uses type aliases where at least one type is
453 // available under two different names.
454 bool uses_multiple_type_instances;
455 Type underlying_type;
456
457 private:
IsUInt64EnumDef458 bool IsUInt64() const {
459 return (BASE_TYPE_ULONG == underlying_type.base_type);
460 }
461
462 friend EnumValBuilder;
463 SymbolTable<EnumVal> vals;
464 };
465
IsString(const Type & type)466 inline bool IsString(const Type &type) {
467 return type.base_type == BASE_TYPE_STRING;
468 }
469
IsStruct(const Type & type)470 inline bool IsStruct(const Type &type) {
471 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
472 }
473
IsUnion(const Type & type)474 inline bool IsUnion(const Type &type) {
475 return type.enum_def != nullptr && type.enum_def->is_union;
476 }
477
IsVector(const Type & type)478 inline bool IsVector(const Type &type) {
479 return type.base_type == BASE_TYPE_VECTOR;
480 }
481
IsArray(const Type & type)482 inline bool IsArray(const Type &type) {
483 return type.base_type == BASE_TYPE_ARRAY;
484 }
485
IsSeries(const Type & type)486 inline bool IsSeries(const Type &type) {
487 return IsVector(type) || IsArray(type);
488 }
489
IsEnum(const Type & type)490 inline bool IsEnum(const Type &type) {
491 return type.enum_def != nullptr && IsInteger(type.base_type);
492 }
493
InlineSize(const Type & type)494 inline size_t InlineSize(const Type &type) {
495 return IsStruct(type)
496 ? type.struct_def->bytesize
497 : (IsArray(type)
498 ? InlineSize(type.VectorType()) * type.fixed_length
499 : SizeOf(type.base_type));
500 }
501
InlineAlignment(const Type & type)502 inline size_t InlineAlignment(const Type &type) {
503 if (IsStruct(type)) {
504 return type.struct_def->minalign;
505 } else if (IsArray(type)) {
506 return IsStruct(type.VectorType()) ? type.struct_def->minalign
507 : SizeOf(type.element);
508 } else {
509 return SizeOf(type.base_type);
510 }
511 }
512 inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
513 return lhs.value == rhs.value;
514 }
515 inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
516 return !(lhs == rhs);
517 }
518
EqualByName(const Type & a,const Type & b)519 inline bool EqualByName(const Type &a, const Type &b) {
520 return a.base_type == b.base_type && a.element == b.element &&
521 (a.struct_def == b.struct_def ||
522 a.struct_def->name == b.struct_def->name) &&
523 (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
524 }
525
526 struct RPCCall : public Definition {
527 Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
528 const Parser &parser) const;
529
530 bool Deserialize(Parser &parser, const reflection::RPCCall *call);
531
532 StructDef *request, *response;
533 };
534
535 struct ServiceDef : public Definition {
536 Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
537 const Parser &parser) const;
538 bool Deserialize(Parser &parser, const reflection::Service *service);
539
540 SymbolTable<RPCCall> calls;
541 };
542
543 // Container of options that may apply to any of the source/text generators.
544 struct IDLOptions {
545 bool gen_jvmstatic;
546 // Use flexbuffers instead for binary and text generation
547 bool use_flexbuffers;
548 bool strict_json;
549 bool output_default_scalars_in_json;
550 int indent_step;
551 bool output_enum_identifiers;
552 bool prefixed_enums;
553 bool scoped_enums;
554 bool include_dependence_headers;
555 bool mutable_buffer;
556 bool one_file;
557 bool proto_mode;
558 bool proto_oneof_union;
559 bool generate_all;
560 bool skip_unexpected_fields_in_json;
561 bool generate_name_strings;
562 bool generate_object_based_api;
563 bool gen_compare;
564 std::string cpp_object_api_pointer_type;
565 std::string cpp_object_api_string_type;
566 bool cpp_object_api_string_flexible_constructor;
567 bool cpp_direct_copy;
568 bool gen_nullable;
569 bool java_checkerframework;
570 bool gen_generated;
571 std::string object_prefix;
572 std::string object_suffix;
573 bool union_value_namespacing;
574 bool allow_non_utf8;
575 bool natural_utf8;
576 std::string include_prefix;
577 bool keep_include_path;
578 bool binary_schema_comments;
579 bool binary_schema_builtins;
580 bool binary_schema_gen_embed;
581 std::string go_import;
582 std::string go_namespace;
583 bool protobuf_ascii_alike;
584 bool size_prefixed;
585 std::string root_type;
586 bool force_defaults;
587 bool java_primitive_has_method;
588 bool cs_gen_json_serializer;
589 std::vector<std::string> cpp_includes;
590 std::string cpp_std;
591 bool cpp_static_reflection;
592 std::string proto_namespace_suffix;
593 std::string filename_suffix;
594 std::string filename_extension;
595 bool no_warnings;
596
597 // Possible options for the more general generator below.
598 enum Language {
599 kJava = 1 << 0,
600 kCSharp = 1 << 1,
601 kGo = 1 << 2,
602 kCpp = 1 << 3,
603 kPython = 1 << 5,
604 kPhp = 1 << 6,
605 kJson = 1 << 7,
606 kBinary = 1 << 8,
607 kTs = 1 << 9,
608 kJsonSchema = 1 << 10,
609 kDart = 1 << 11,
610 kLua = 1 << 12,
611 kLobster = 1 << 13,
612 kRust = 1 << 14,
613 kKotlin = 1 << 15,
614 kSwift = 1 << 16,
615 kMAX
616 };
617
618 Language lang;
619
620 enum MiniReflect { kNone, kTypes, kTypesAndNames };
621
622 MiniReflect mini_reflect;
623
624 // If set, require all fields in a table to be explicitly numbered.
625 bool require_explicit_ids;
626
627 // The corresponding language bit will be set if a language is included
628 // for code generation.
629 unsigned long lang_to_generate;
630
631 // If set (default behavior), empty string fields will be set to nullptr to
632 // make the flatbuffer more compact.
633 bool set_empty_strings_to_null;
634
635 // If set (default behavior), empty vector fields will be set to nullptr to
636 // make the flatbuffer more compact.
637 bool set_empty_vectors_to_null;
638
IDLOptionsIDLOptions639 IDLOptions()
640 : gen_jvmstatic(false),
641 use_flexbuffers(false),
642 strict_json(false),
643 output_default_scalars_in_json(false),
644 indent_step(2),
645 output_enum_identifiers(true),
646 prefixed_enums(true),
647 scoped_enums(false),
648 include_dependence_headers(true),
649 mutable_buffer(false),
650 one_file(false),
651 proto_mode(false),
652 proto_oneof_union(false),
653 generate_all(false),
654 skip_unexpected_fields_in_json(false),
655 generate_name_strings(false),
656 generate_object_based_api(false),
657 gen_compare(false),
658 cpp_object_api_pointer_type("std::unique_ptr"),
659 cpp_object_api_string_flexible_constructor(false),
660 cpp_direct_copy(true),
661 gen_nullable(false),
662 java_checkerframework(false),
663 gen_generated(false),
664 object_suffix("T"),
665 union_value_namespacing(true),
666 allow_non_utf8(false),
667 natural_utf8(false),
668 keep_include_path(false),
669 binary_schema_comments(false),
670 binary_schema_builtins(false),
671 binary_schema_gen_embed(false),
672 protobuf_ascii_alike(false),
673 size_prefixed(false),
674 force_defaults(false),
675 java_primitive_has_method(false),
676 cs_gen_json_serializer(false),
677 cpp_static_reflection(false),
678 filename_suffix("_generated"),
679 filename_extension(),
680 no_warnings(false),
681 lang(IDLOptions::kJava),
682 mini_reflect(IDLOptions::kNone),
683 require_explicit_ids(false),
684 lang_to_generate(0),
685 set_empty_strings_to_null(true),
686 set_empty_vectors_to_null(true) {}
687 };
688
689 // This encapsulates where the parser is in the current source file.
690 struct ParserState {
ParserStateParserState691 ParserState()
692 : cursor_(nullptr),
693 line_start_(nullptr),
694 line_(0),
695 token_(-1),
696 attr_is_trivial_ascii_string_(true) {}
697
698 protected:
ResetStateParserState699 void ResetState(const char *source) {
700 cursor_ = source;
701 line_ = 0;
702 MarkNewLine();
703 }
704
MarkNewLineParserState705 void MarkNewLine() {
706 line_start_ = cursor_;
707 line_ += 1;
708 }
709
CursorPositionParserState710 int64_t CursorPosition() const {
711 FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
712 return static_cast<int64_t>(cursor_ - line_start_);
713 }
714
715 const char *cursor_;
716 const char *line_start_;
717 int line_; // the current line being parsed
718 int token_;
719
720 // Flag: text in attribute_ is true ASCII string without escape
721 // sequences. Only printable ASCII (without [\t\r\n]).
722 // Used for number-in-string (and base64 string in future).
723 bool attr_is_trivial_ascii_string_;
724 std::string attribute_;
725 std::vector<std::string> doc_comment_;
726 };
727
728 // A way to make error propagation less error prone by requiring values to be
729 // checked.
730 // Once you create a value of this type you must either:
731 // - Call Check() on it.
732 // - Copy or assign it to another value.
733 // Failure to do so leads to an assert.
734 // This guarantees that this as return value cannot be ignored.
735 class CheckedError {
736 public:
CheckedError(bool error)737 explicit CheckedError(bool error)
738 : is_error_(error), has_been_checked_(false) {}
739
740 CheckedError &operator=(const CheckedError &other) {
741 is_error_ = other.is_error_;
742 has_been_checked_ = false;
743 other.has_been_checked_ = true;
744 return *this;
745 }
746
CheckedError(const CheckedError & other)747 CheckedError(const CheckedError &other) {
748 *this = other; // Use assignment operator.
749 }
750
~CheckedError()751 ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
752
Check()753 bool Check() {
754 has_been_checked_ = true;
755 return is_error_;
756 }
757
758 private:
759 bool is_error_;
760 mutable bool has_been_checked_;
761 };
762
763 // Additionally, in GCC we can get these errors statically, for additional
764 // assurance:
765 // clang-format off
766 #ifdef __GNUC__
767 #define FLATBUFFERS_CHECKED_ERROR CheckedError \
768 __attribute__((warn_unused_result))
769 #else
770 #define FLATBUFFERS_CHECKED_ERROR CheckedError
771 #endif
772 // clang-format on
773
774 class Parser : public ParserState {
775 public:
776 explicit Parser(const IDLOptions &options = IDLOptions())
current_namespace_(nullptr)777 : current_namespace_(nullptr),
778 empty_namespace_(nullptr),
779 flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
780 root_struct_def_(nullptr),
781 opts(options),
782 uses_flexbuffers_(false),
783 advanced_features_(0),
784 source_(nullptr),
785 anonymous_counter_(0),
786 parse_depth_counter_(0) {
787 if (opts.force_defaults) { builder_.ForceDefaults(true); }
788 // Start out with the empty namespace being current.
789 empty_namespace_ = new Namespace();
790 namespaces_.push_back(empty_namespace_);
791 current_namespace_ = empty_namespace_;
792 known_attributes_["deprecated"] = true;
793 known_attributes_["required"] = true;
794 known_attributes_["key"] = true;
795 known_attributes_["shared"] = true;
796 known_attributes_["hash"] = true;
797 known_attributes_["id"] = true;
798 known_attributes_["force_align"] = true;
799 known_attributes_["bit_flags"] = true;
800 known_attributes_["original_order"] = true;
801 known_attributes_["nested_flatbuffer"] = true;
802 known_attributes_["csharp_partial"] = true;
803 known_attributes_["streaming"] = true;
804 known_attributes_["idempotent"] = true;
805 known_attributes_["cpp_type"] = true;
806 known_attributes_["cpp_ptr_type"] = true;
807 known_attributes_["cpp_ptr_type_get"] = true;
808 known_attributes_["cpp_str_type"] = true;
809 known_attributes_["cpp_str_flex_ctor"] = true;
810 known_attributes_["native_inline"] = true;
811 known_attributes_["native_custom_alloc"] = true;
812 known_attributes_["native_type"] = true;
813 known_attributes_["native_type_pack_name"] = true;
814 known_attributes_["native_default"] = true;
815 known_attributes_["flexbuffer"] = true;
816 known_attributes_["private"] = true;
817 }
818
~Parser()819 ~Parser() {
820 for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
821 delete *it;
822 }
823 }
824
825 // Parse the string containing either schema or JSON data, which will
826 // populate the SymbolTable's or the FlatBufferBuilder above.
827 // include_paths is used to resolve any include statements, and typically
828 // should at least include the project path (where you loaded source_ from).
829 // include_paths must be nullptr terminated if specified.
830 // If include_paths is nullptr, it will attempt to load from the current
831 // directory.
832 // If the source was loaded from a file and isn't an include file,
833 // supply its name in source_filename.
834 // All paths specified in this call must be in posix format, if you accept
835 // paths from user input, please call PosixPath on them first.
836 bool Parse(const char *_source, const char **include_paths = nullptr,
837 const char *source_filename = nullptr);
838
839 bool ParseJson(const char *json, const char *json_filename = nullptr);
840
841 // Set the root type. May override the one set in the schema.
842 bool SetRootType(const char *name);
843
844 // Mark all definitions as already having code generated.
845 void MarkGenerated();
846
847 // Get the files recursively included by the given file. The returned
848 // container will have at least the given file.
849 std::set<std::string> GetIncludedFilesRecursive(
850 const std::string &file_name) const;
851
852 // Fills builder_ with a binary version of the schema parsed.
853 // See reflection/reflection.fbs
854 void Serialize();
855
856 // Deserialize a schema buffer
857 bool Deserialize(const uint8_t *buf, const size_t size);
858
859 // Fills internal structure as if the schema passed had been loaded by parsing
860 // with Parse except that included filenames will not be populated.
861 bool Deserialize(const reflection::Schema *schema);
862
863 Type *DeserializeType(const reflection::Type *type);
864
865 // Checks that the schema represented by this parser is a safe evolution
866 // of the schema provided. Returns non-empty error on any problems.
867 std::string ConformTo(const Parser &base);
868
869 // Similar to Parse(), but now only accepts JSON to be parsed into a
870 // FlexBuffer.
871 bool ParseFlexBuffer(const char *source, const char *source_filename,
872 flexbuffers::Builder *builder);
873
874 StructDef *LookupStruct(const std::string &id) const;
875 StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
876
877 std::string UnqualifiedName(const std::string &fullQualifiedName);
878
879 FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
880
881 // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
882 // in a schema.
883 // @param opts Options used to parce a schema and generate code.
884 static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
885
886 private:
887 class ParseDepthGuard;
888
889 void Message(const std::string &msg);
890 void Warning(const std::string &msg);
891 FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
892 FLATBUFFERS_CHECKED_ERROR Next();
893 FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
894 bool Is(int t) const;
895 bool IsIdent(const char *id) const;
896 FLATBUFFERS_CHECKED_ERROR Expect(int t);
897 std::string TokenToStringId(int t) const;
898 EnumDef *LookupEnum(const std::string &id);
899 FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
900 std::string *last);
901 FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
902 FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
903 FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
904 const std::string &name, const Type &type,
905 FieldDef **dest);
906 FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
907 FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
908 FLATBUFFERS_CHECKED_ERROR ParseComma();
909 FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
910 size_t parent_fieldn,
911 const StructDef *parent_struct_def,
912 uoffset_t count,
913 bool inside_vector = false);
914 template<typename F>
915 FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
916 const StructDef *struct_def,
917 F body);
918 FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
919 std::string *value, uoffset_t *ovalue);
920 void SerializeStruct(const StructDef &struct_def, const Value &val);
921 void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
922 const Value &val);
923 template<typename F>
924 FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
925 FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
926 FieldDef *field, size_t fieldn);
927 FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
928 FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
929 Value &val, FieldDef *field, size_t fieldn,
930 const StructDef *parent_struct_def);
931 FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
932 FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
933 bool check, Value &e, BaseType req,
934 bool *destmatch);
935 FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
936 FLATBUFFERS_CHECKED_ERROR TokenError();
937 FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
938 bool check_now);
939 FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
940 FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
941 std::string *result);
942 StructDef *LookupCreateStruct(const std::string &name,
943 bool create_if_new = true,
944 bool definition = false);
945 FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
946 FLATBUFFERS_CHECKED_ERROR ParseNamespace();
947 FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
948 StructDef **dest);
949 FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
950 EnumDef **dest);
951 FLATBUFFERS_CHECKED_ERROR ParseDecl();
952 FLATBUFFERS_CHECKED_ERROR ParseService();
953 FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
954 bool isextend, bool inside_oneof);
955 FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
956 FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
957 FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
958 FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
959 FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
960 FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
961 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(
962 flexbuffers::Builder *builder);
963 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
964 FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
965 const char *source_filename);
966 FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
967 const char **include_paths,
968 const char *source_filename);
969 FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
970 const char **include_paths,
971 const char *source_filename,
972 const char *include_filename);
973 FLATBUFFERS_CHECKED_ERROR DoParseJson();
974 FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
975 StructDef *struct_def,
976 const char *suffix, BaseType baseType);
977 FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(
978 const std::string &align_constant, size_t min_align, size_t *align);
979
980 bool SupportsAdvancedUnionFeatures() const;
981 bool SupportsAdvancedArrayFeatures() const;
982 bool SupportsOptionalScalars() const;
983 bool SupportsDefaultVectorsAndStrings() const;
984 Namespace *UniqueNamespace(Namespace *ns);
985
986 FLATBUFFERS_CHECKED_ERROR RecurseError();
987 template<typename F> CheckedError Recurse(F f);
988
989 public:
990 SymbolTable<Type> types_;
991 SymbolTable<StructDef> structs_;
992 SymbolTable<EnumDef> enums_;
993 SymbolTable<ServiceDef> services_;
994 std::vector<Namespace *> namespaces_;
995 Namespace *current_namespace_;
996 Namespace *empty_namespace_;
997 std::string error_; // User readable error_ if Parse() == false
998
999 FlatBufferBuilder builder_; // any data contained in the file
1000 flexbuffers::Builder flex_builder_;
1001 flexbuffers::Reference flex_root_;
1002 StructDef *root_struct_def_;
1003 std::string file_identifier_;
1004 std::string file_extension_;
1005
1006 std::map<uint64_t, std::string> included_files_;
1007 std::map<std::string, std::set<std::string>> files_included_per_file_;
1008 std::vector<std::string> native_included_files_;
1009
1010 std::map<std::string, bool> known_attributes_;
1011
1012 IDLOptions opts;
1013 bool uses_flexbuffers_;
1014
1015 uint64_t advanced_features_;
1016
1017 private:
1018 const char *source_;
1019
1020 std::string file_being_parsed_;
1021
1022 std::vector<std::pair<Value, FieldDef *>> field_stack_;
1023
1024 int anonymous_counter_;
1025 int parse_depth_counter_; // stack-overflow guard
1026 };
1027
1028 // Utility functions for multiple generators:
1029
1030 extern std::string MakeCamel(const std::string &in, bool first = true);
1031
1032 extern std::string MakeScreamingCamel(const std::string &in);
1033
1034 // Generate text (JSON) from a given FlatBuffer, and a given Parser
1035 // object that has been populated with the corresponding schema.
1036 // If ident_step is 0, no indentation will be generated. Additionally,
1037 // if it is less than 0, no linefeeds will be generated either.
1038 // See idl_gen_text.cpp.
1039 // strict_json adds "quotes" around field names if true.
1040 // If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
1041 // byte arrays in String values), returns false.
1042 extern bool GenerateTextFromTable(const Parser &parser, const void *table,
1043 const std::string &tablename,
1044 std::string *text);
1045 extern bool GenerateText(const Parser &parser, const void *flatbuffer,
1046 std::string *text);
1047 extern bool GenerateTextFile(const Parser &parser, const std::string &path,
1048 const std::string &file_name);
1049
1050 // Generate Json schema to string
1051 // See idl_gen_json_schema.cpp.
1052 extern bool GenerateJsonSchema(const Parser &parser, std::string *json);
1053
1054 // Generate binary files from a given FlatBuffer, and a given Parser
1055 // object that has been populated with the corresponding schema.
1056 // See code_generators.cpp.
1057 extern bool GenerateBinary(const Parser &parser, const std::string &path,
1058 const std::string &file_name);
1059
1060 // Generate a C++ header from the definitions in the Parser object.
1061 // See idl_gen_cpp.
1062 extern bool GenerateCPP(const Parser &parser, const std::string &path,
1063 const std::string &file_name);
1064
1065 // Generate C# files from the definitions in the Parser object.
1066 // See idl_gen_csharp.cpp.
1067 extern bool GenerateCSharp(const Parser &parser, const std::string &path,
1068 const std::string &file_name);
1069
1070 extern bool GenerateDart(const Parser &parser, const std::string &path,
1071 const std::string &file_name);
1072
1073 // Generate Java files from the definitions in the Parser object.
1074 // See idl_gen_java.cpp.
1075 extern bool GenerateJava(const Parser &parser, const std::string &path,
1076 const std::string &file_name);
1077
1078 // Generate JavaScript or TypeScript code from the definitions in the Parser
1079 // object. See idl_gen_js.
1080 extern bool GenerateTS(const Parser &parser, const std::string &path,
1081 const std::string &file_name);
1082
1083 // Generate Go files from the definitions in the Parser object.
1084 // See idl_gen_go.cpp.
1085 extern bool GenerateGo(const Parser &parser, const std::string &path,
1086 const std::string &file_name);
1087
1088 // Generate Php code from the definitions in the Parser object.
1089 // See idl_gen_php.
1090 extern bool GeneratePhp(const Parser &parser, const std::string &path,
1091 const std::string &file_name);
1092
1093 // Generate Python files from the definitions in the Parser object.
1094 // See idl_gen_python.cpp.
1095 extern bool GeneratePython(const Parser &parser, const std::string &path,
1096 const std::string &file_name);
1097
1098 // Generate Lobster files from the definitions in the Parser object.
1099 // See idl_gen_lobster.cpp.
1100 extern bool GenerateLobster(const Parser &parser, const std::string &path,
1101 const std::string &file_name);
1102
1103 // Generate Lua files from the definitions in the Parser object.
1104 // See idl_gen_lua.cpp.
1105 extern bool GenerateLua(const Parser &parser, const std::string &path,
1106 const std::string &file_name);
1107
1108 // Generate Rust files from the definitions in the Parser object.
1109 // See idl_gen_rust.cpp.
1110 extern bool GenerateRust(const Parser &parser, const std::string &path,
1111 const std::string &file_name);
1112
1113 // Generate Json schema file
1114 // See idl_gen_json_schema.cpp.
1115 extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
1116 const std::string &file_name);
1117
1118 extern bool GenerateKotlin(const Parser &parser, const std::string &path,
1119 const std::string &file_name);
1120
1121 // Generate Swift classes.
1122 // See idl_gen_swift.cpp
1123 extern bool GenerateSwift(const Parser &parser, const std::string &path,
1124 const std::string &file_name);
1125
1126 // Generate a schema file from the internal representation, useful after
1127 // parsing a .proto schema.
1128 extern std::string GenerateFBS(const Parser &parser,
1129 const std::string &file_name);
1130 extern bool GenerateFBS(const Parser &parser, const std::string &path,
1131 const std::string &file_name);
1132
1133 // Generate a make rule for the generated TypeScript code.
1134 // See idl_gen_ts.cpp.
1135 extern std::string TSMakeRule(const Parser &parser, const std::string &path,
1136 const std::string &file_name);
1137
1138 // Generate a make rule for the generated C++ header.
1139 // See idl_gen_cpp.cpp.
1140 extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
1141 const std::string &file_name);
1142
1143 // Generate a make rule for the generated Dart code
1144 // see idl_gen_dart.cpp
1145 extern std::string DartMakeRule(const Parser &parser, const std::string &path,
1146 const std::string &file_name);
1147
1148 // Generate a make rule for the generated Rust code.
1149 // See idl_gen_rust.cpp.
1150 extern std::string RustMakeRule(const Parser &parser, const std::string &path,
1151 const std::string &file_name);
1152
1153 // Generate a make rule for generated Java or C# files.
1154 // See code_generators.cpp.
1155 extern std::string JavaCSharpMakeRule(const Parser &parser,
1156 const std::string &path,
1157 const std::string &file_name);
1158
1159 // Generate a make rule for the generated text (JSON) files.
1160 // See idl_gen_text.cpp.
1161 extern std::string TextMakeRule(const Parser &parser, const std::string &path,
1162 const std::string &file_names);
1163
1164 // Generate a make rule for the generated binary files.
1165 // See code_generators.cpp.
1166 extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
1167 const std::string &file_name);
1168
1169 // Generate GRPC Cpp interfaces.
1170 // See idl_gen_grpc.cpp.
1171 bool GenerateCppGRPC(const Parser &parser, const std::string &path,
1172 const std::string &file_name);
1173
1174 // Generate GRPC Go interfaces.
1175 // See idl_gen_grpc.cpp.
1176 bool GenerateGoGRPC(const Parser &parser, const std::string &path,
1177 const std::string &file_name);
1178
1179 // Generate GRPC Java classes.
1180 // See idl_gen_grpc.cpp
1181 bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
1182 const std::string &file_name);
1183
1184 // Generate GRPC Python interfaces.
1185 // See idl_gen_grpc.cpp.
1186 bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
1187 const std::string &file_name);
1188
1189 // Generate GRPC Swift interfaces.
1190 // See idl_gen_grpc.cpp.
1191 extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
1192 const std::string &file_name);
1193
1194 extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
1195 const std::string &file_name);
1196 } // namespace flatbuffers
1197
1198 #endif // FLATBUFFERS_IDL_H_
1199