blob: 44e35665d0e46cc9d84dc0f1cb9bc7a89e9c85c9 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
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
43namespace 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/*
84switch (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
103enum 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
118inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
119 t <= BASE_TYPE_DOUBLE; }
120inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
121 t <= BASE_TYPE_ULONG; }
122inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
123 t == BASE_TYPE_DOUBLE; }
124inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
125 t == BASE_TYPE_ULONG; }
126inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
127inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
128 t <= BASE_TYPE_UCHAR; }
129
130inline 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
138extern const char *const kTypeNames[];
139extern const char kTypeSizes[];
140
141inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
142
143struct StructDef;
144struct EnumDef;
145class Parser;
146
147// Represents any type in the IDL, which is a combination of the BaseType
148// and additional information for vectors/structs_.
149struct 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.
180struct 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.
191template<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.
227struct 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
241inline 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_).
251struct 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
279struct 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
309struct 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
341inline bool IsStruct(const Type &type) {
342 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
343}
344
345inline bool IsVector(const Type &type) {
346 return type.base_type == BASE_TYPE_VECTOR;
347}
348
349inline bool IsArray(const Type &type) {
350 return type.base_type == BASE_TYPE_ARRAY;
351}
352
353inline bool IsSeries(const Type &type) {
354 return IsVector(type) || IsArray(type);
355}
356
357inline bool IsEnum(const Type &type) {
358 return type.enum_def != nullptr && IsInteger(type.base_type);
359}
360
361inline size_t InlineSize(const Type &type) {
362 return IsStruct(type)
363 ? type.struct_def->bytesize
364 : (IsArray(type)
365 ? InlineSize(type.VectorType()) * type.fixed_length
366 : SizeOf(type.base_type));
367}
368
369inline size_t InlineAlignment(const Type &type) {
370 return IsStruct(type)
371 ? type.struct_def->minalign
372 : (SizeOf(IsArray(type) ? type.element : type.base_type));
373}
374
375struct EnumDef;
376struct EnumValBuilder;
377
378struct EnumVal {
379 Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
380
381 bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
382
383 uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
384 int64_t GetAsInt64() const { return value; }
385 bool IsZero() const { return 0 == value; }
386 bool IsNonZero() const { return !IsZero(); }
387
388 std::string name;
389 std::vector<std::string> doc_comment;
390 Type union_type;
391
392 private:
393 friend EnumDef;
394 friend EnumValBuilder;
395 friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
396
397 EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
398 EnumVal() : value(0) {}
399
400 int64_t value;
401};
402
403struct EnumDef : public Definition {
404 EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
405
406 Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
407 const Parser &parser) const;
408
409 bool Deserialize(Parser &parser, const reflection::Enum *values);
410
411 template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
412 void SortByValue();
413 void RemoveDuplicates();
414
415 std::string AllFlags() const;
416 const EnumVal *MinValue() const;
417 const EnumVal *MaxValue() const;
418 // Returns the number of integer steps from v1 to v2.
419 uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
420 // Returns the number of integer steps from Min to Max.
421 uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
422
423 EnumVal *ReverseLookup(int64_t enum_idx,
424 bool skip_union_default = false) const;
425 EnumVal *FindByValue(const std::string &constant) const;
426
427 std::string ToString(const EnumVal &ev) const {
428 return IsUInt64() ? NumToString(ev.GetAsUInt64())
429 : NumToString(ev.GetAsInt64());
430 }
431
432 size_t size() const { return vals.vec.size(); }
433
434 const std::vector<EnumVal *> &Vals() const {
435 FLATBUFFERS_ASSERT(false == vals.vec.empty());
436 return vals.vec;
437 }
438
439 const EnumVal *Lookup(const std::string &enum_name) const {
440 return vals.Lookup(enum_name);
441 }
442
443 bool is_union;
444 // Type is a union which uses type aliases where at least one type is
445 // available under two different names.
446 bool uses_multiple_type_instances;
447 Type underlying_type;
448
449 private:
450 bool IsUInt64() const {
451 return (BASE_TYPE_ULONG == underlying_type.base_type);
452 }
453
454 friend EnumValBuilder;
455 SymbolTable<EnumVal> vals;
456};
457
458inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
459 return lhs.value == rhs.value;
460}
461inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
462 return !(lhs == rhs);
463}
464
465inline bool EqualByName(const Type &a, const Type &b) {
466 return a.base_type == b.base_type && a.element == b.element &&
467 (a.struct_def == b.struct_def ||
468 a.struct_def->name == b.struct_def->name) &&
469 (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
470}
471
472struct RPCCall : public Definition {
473 Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
474
475 bool Deserialize(Parser &parser, const reflection::RPCCall *call);
476
477 StructDef *request, *response;
478};
479
480struct ServiceDef : public Definition {
481 Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
482 bool Deserialize(Parser &parser, const reflection::Service *service);
483
484 SymbolTable<RPCCall> calls;
485};
486
487// Container of options that may apply to any of the source/text generators.
488struct IDLOptions {
489 bool strict_json;
490 bool skip_js_exports;
491 bool use_goog_js_export_format;
492 bool use_ES6_js_export_format;
493 bool output_default_scalars_in_json;
494 int indent_step;
495 bool output_enum_identifiers;
496 bool prefixed_enums;
497 bool scoped_enums;
498 bool include_dependence_headers;
499 bool mutable_buffer;
500 bool one_file;
501 bool proto_mode;
502 bool proto_oneof_union;
503 bool generate_all;
504 bool skip_unexpected_fields_in_json;
505 bool generate_name_strings;
506 bool generate_object_based_api;
507 bool gen_compare;
508 std::string cpp_object_api_pointer_type;
509 std::string cpp_object_api_string_type;
510 bool cpp_object_api_string_flexible_constructor;
511 bool gen_nullable;
512 bool gen_generated;
513 std::string object_prefix;
514 std::string object_suffix;
515 bool union_value_namespacing;
516 bool allow_non_utf8;
517 bool natural_utf8;
518 std::string include_prefix;
519 bool keep_include_path;
520 bool binary_schema_comments;
521 bool binary_schema_builtins;
522 bool skip_flatbuffers_import;
523 std::string go_import;
524 std::string go_namespace;
525 bool reexport_ts_modules;
526 bool js_ts_short_names;
527 bool protobuf_ascii_alike;
528 bool size_prefixed;
529 std::string root_type;
530 bool force_defaults;
531 std::vector<std::string> cpp_includes;
532
533 // Possible options for the more general generator below.
534 enum Language {
535 kJava = 1 << 0,
536 kCSharp = 1 << 1,
537 kGo = 1 << 2,
538 kCpp = 1 << 3,
539 kJs = 1 << 4,
540 kPython = 1 << 5,
541 kPhp = 1 << 6,
542 kJson = 1 << 7,
543 kBinary = 1 << 8,
544 kTs = 1 << 9,
545 kJsonSchema = 1 << 10,
546 kDart = 1 << 11,
547 kLua = 1 << 12,
548 kLobster = 1 << 13,
549 kRust = 1 << 14,
550 kKotlin = 1 << 15,
551 kMAX
552 };
553
554 Language lang;
555
556 enum MiniReflect { kNone, kTypes, kTypesAndNames };
557
558 MiniReflect mini_reflect;
559
560 // The corresponding language bit will be set if a language is included
561 // for code generation.
562 unsigned long lang_to_generate;
563
564 // If set (default behavior), empty string and vector fields will be set to
565 // nullptr to make the flatbuffer more compact.
566 bool set_empty_to_null;
567
568 IDLOptions()
569 : strict_json(false),
570 skip_js_exports(false),
571 use_goog_js_export_format(false),
572 use_ES6_js_export_format(false),
573 output_default_scalars_in_json(false),
574 indent_step(2),
575 output_enum_identifiers(true),
576 prefixed_enums(true),
577 scoped_enums(false),
578 include_dependence_headers(true),
579 mutable_buffer(false),
580 one_file(false),
581 proto_mode(false),
582 proto_oneof_union(false),
583 generate_all(false),
584 skip_unexpected_fields_in_json(false),
585 generate_name_strings(false),
586 generate_object_based_api(false),
587 gen_compare(false),
588 cpp_object_api_pointer_type("std::unique_ptr"),
589 cpp_object_api_string_flexible_constructor(false),
590 gen_nullable(false),
591 gen_generated(false),
592 object_suffix("T"),
593 union_value_namespacing(true),
594 allow_non_utf8(false),
595 natural_utf8(false),
596 keep_include_path(false),
597 binary_schema_comments(false),
598 binary_schema_builtins(false),
599 skip_flatbuffers_import(false),
600 reexport_ts_modules(true),
601 js_ts_short_names(false),
602 protobuf_ascii_alike(false),
603 size_prefixed(false),
604 force_defaults(false),
605 lang(IDLOptions::kJava),
606 mini_reflect(IDLOptions::kNone),
607 lang_to_generate(0),
608 set_empty_to_null(true) {}
609};
610
611// This encapsulates where the parser is in the current source file.
612struct ParserState {
613 ParserState()
614 : cursor_(nullptr),
615 line_start_(nullptr),
616 line_(0),
617 token_(-1),
618 attr_is_trivial_ascii_string_(true) {}
619
620 protected:
621 void ResetState(const char *source) {
622 cursor_ = source;
623 line_ = 0;
624 MarkNewLine();
625 }
626
627 void MarkNewLine() {
628 line_start_ = cursor_;
629 line_ += 1;
630 }
631
632 int64_t CursorPosition() const {
633 FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
634 return static_cast<int64_t>(cursor_ - line_start_);
635 }
636
637 const char *cursor_;
638 const char *line_start_;
639 int line_; // the current line being parsed
640 int token_;
641
642 // Flag: text in attribute_ is true ASCII string without escape
643 // sequences. Only printable ASCII (without [\t\r\n]).
644 // Used for number-in-string (and base64 string in future).
645 bool attr_is_trivial_ascii_string_;
646 std::string attribute_;
647 std::vector<std::string> doc_comment_;
648};
649
650// A way to make error propagation less error prone by requiring values to be
651// checked.
652// Once you create a value of this type you must either:
653// - Call Check() on it.
654// - Copy or assign it to another value.
655// Failure to do so leads to an assert.
656// This guarantees that this as return value cannot be ignored.
657class CheckedError {
658 public:
659 explicit CheckedError(bool error)
660 : is_error_(error), has_been_checked_(false) {}
661
662 CheckedError &operator=(const CheckedError &other) {
663 is_error_ = other.is_error_;
664 has_been_checked_ = false;
665 other.has_been_checked_ = true;
666 return *this;
667 }
668
669 CheckedError(const CheckedError &other) {
670 *this = other; // Use assignment operator.
671 }
672
673 ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
674
675 bool Check() {
676 has_been_checked_ = true;
677 return is_error_;
678 }
679
680 private:
681 bool is_error_;
682 mutable bool has_been_checked_;
683};
684
685// Additionally, in GCC we can get these errors statically, for additional
686// assurance:
687// clang-format off
688#ifdef __GNUC__
689#define FLATBUFFERS_CHECKED_ERROR CheckedError \
690 __attribute__((warn_unused_result))
691#else
692#define FLATBUFFERS_CHECKED_ERROR CheckedError
693#endif
694// clang-format on
695
696class Parser : public ParserState {
697 public:
698 explicit Parser(const IDLOptions &options = IDLOptions())
699 : current_namespace_(nullptr),
700 empty_namespace_(nullptr),
701 root_struct_def_(nullptr),
702 opts(options),
703 uses_flexbuffers_(false),
704 source_(nullptr),
705 anonymous_counter(0),
706 recurse_protection_counter(0) {
707 if (opts.force_defaults) {
708 builder_.ForceDefaults(true);
709 }
710 // Start out with the empty namespace being current.
711 empty_namespace_ = new Namespace();
712 namespaces_.push_back(empty_namespace_);
713 current_namespace_ = empty_namespace_;
714 known_attributes_["deprecated"] = true;
715 known_attributes_["required"] = true;
716 known_attributes_["key"] = true;
717 known_attributes_["shared"] = true;
718 known_attributes_["hash"] = true;
719 known_attributes_["id"] = true;
720 known_attributes_["force_align"] = true;
721 known_attributes_["bit_flags"] = true;
722 known_attributes_["original_order"] = true;
723 known_attributes_["nested_flatbuffer"] = true;
724 known_attributes_["csharp_partial"] = true;
725 known_attributes_["streaming"] = true;
726 known_attributes_["idempotent"] = true;
727 known_attributes_["cpp_type"] = true;
728 known_attributes_["cpp_ptr_type"] = true;
729 known_attributes_["cpp_ptr_type_get"] = true;
730 known_attributes_["cpp_str_type"] = true;
731 known_attributes_["cpp_str_flex_ctor"] = true;
732 known_attributes_["native_inline"] = true;
733 known_attributes_["native_custom_alloc"] = true;
734 known_attributes_["native_type"] = true;
735 known_attributes_["native_default"] = true;
736 known_attributes_["flexbuffer"] = true;
737 known_attributes_["private"] = true;
738 }
739
740 ~Parser() {
741 for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
742 delete *it;
743 }
744 }
745
746 // Parse the string containing either schema or JSON data, which will
747 // populate the SymbolTable's or the FlatBufferBuilder above.
748 // include_paths is used to resolve any include statements, and typically
749 // should at least include the project path (where you loaded source_ from).
750 // include_paths must be nullptr terminated if specified.
751 // If include_paths is nullptr, it will attempt to load from the current
752 // directory.
753 // If the source was loaded from a file and isn't an include file,
754 // supply its name in source_filename.
755 // All paths specified in this call must be in posix format, if you accept
756 // paths from user input, please call PosixPath on them first.
757 bool Parse(const char *_source, const char **include_paths = nullptr,
758 const char *source_filename = nullptr);
759
760 // Set the root type. May override the one set in the schema.
761 bool SetRootType(const char *name);
762
763 // Mark all definitions as already having code generated.
764 void MarkGenerated();
765
766 // Get the files recursively included by the given file. The returned
767 // container will have at least the given file.
768 std::set<std::string> GetIncludedFilesRecursive(
769 const std::string &file_name) const;
770
771 // Fills builder_ with a binary version of the schema parsed.
772 // See reflection/reflection.fbs
773 void Serialize();
774
775 // Deserialize a schema buffer
776 bool Deserialize(const uint8_t *buf, const size_t size);
777
778 // Fills internal structure as if the schema passed had been loaded by parsing
779 // with Parse except that included filenames will not be populated.
780 bool Deserialize(const reflection::Schema* schema);
781
782 Type* DeserializeType(const reflection::Type* type);
783
784 // Checks that the schema represented by this parser is a safe evolution
785 // of the schema provided. Returns non-empty error on any problems.
786 std::string ConformTo(const Parser &base);
787
788 // Similar to Parse(), but now only accepts JSON to be parsed into a
789 // FlexBuffer.
790 bool ParseFlexBuffer(const char *source, const char *source_filename,
791 flexbuffers::Builder *builder);
792
793 StructDef *LookupStruct(const std::string &id) const;
794
795 std::string UnqualifiedName(const std::string &fullQualifiedName);
796
797 FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
798
799 private:
800 void Message(const std::string &msg);
801 void Warning(const std::string &msg);
802 FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
803 FLATBUFFERS_CHECKED_ERROR Next();
804 FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
805 bool Is(int t) const;
806 bool IsIdent(const char *id) const;
807 FLATBUFFERS_CHECKED_ERROR Expect(int t);
808 std::string TokenToStringId(int t) const;
809 EnumDef *LookupEnum(const std::string &id);
810 FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
811 std::string *last);
812 FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
813 FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
814 FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
815 const std::string &name, const Type &type,
816 FieldDef **dest);
817 FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
818 FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
819 FLATBUFFERS_CHECKED_ERROR ParseComma();
820 FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
821 size_t parent_fieldn,
822 const StructDef *parent_struct_def,
823 uoffset_t count,
824 bool inside_vector = false);
825 template<typename F>
826 FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
827 const StructDef *struct_def,
828 F body);
829 FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
830 std::string *value, uoffset_t *ovalue);
831 void SerializeStruct(const StructDef &struct_def, const Value &val);
832 void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
833 const Value &val);
834 template<typename F>
835 FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
836 FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
837 FieldDef *field, size_t fieldn);
838 FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
839 FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
840 size_t fieldn,
841 const StructDef *parent_struct_def);
842 FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
843 FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
844 BaseType req, bool *destmatch);
845 FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
846 FLATBUFFERS_CHECKED_ERROR TokenError();
847 FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now);
848 FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result);
849 StructDef *LookupCreateStruct(const std::string &name,
850 bool create_if_new = true,
851 bool definition = false);
852 FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
853 FLATBUFFERS_CHECKED_ERROR ParseNamespace();
854 FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
855 StructDef **dest);
856 FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
857 bool is_union,
858 EnumDef **dest);
859 FLATBUFFERS_CHECKED_ERROR ParseDecl();
860 FLATBUFFERS_CHECKED_ERROR ParseService();
861 FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
862 bool isextend, bool inside_oneof);
863 FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
864 FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
865 FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
866 FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
867 FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
868 FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
869 FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
870 FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
871 const char *source_filename);
872 FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
873 const char **include_paths,
874 const char *source_filename);
875 FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
876 const char **include_paths,
877 const char *source_filename,
878 const char *include_filename);
879 FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
880 StructDef *struct_def,
881 const char *suffix,
882 BaseType baseType);
883
884 bool SupportsAdvancedUnionFeatures() const;
885 bool SupportsAdvancedArrayFeatures() const;
886 Namespace *UniqueNamespace(Namespace *ns);
887
888 FLATBUFFERS_CHECKED_ERROR RecurseError();
889 template<typename F> CheckedError Recurse(F f);
890
891 public:
892 SymbolTable<Type> types_;
893 SymbolTable<StructDef> structs_;
894 SymbolTable<EnumDef> enums_;
895 SymbolTable<ServiceDef> services_;
896 std::vector<Namespace *> namespaces_;
897 Namespace *current_namespace_;
898 Namespace *empty_namespace_;
899 std::string error_; // User readable error_ if Parse() == false
900
901 FlatBufferBuilder builder_; // any data contained in the file
902 StructDef *root_struct_def_;
903 std::string file_identifier_;
904 std::string file_extension_;
905
906 std::map<std::string, std::string> included_files_;
907 std::map<std::string, std::set<std::string>> files_included_per_file_;
908 std::vector<std::string> native_included_files_;
909
910 std::map<std::string, bool> known_attributes_;
911
912 IDLOptions opts;
913 bool uses_flexbuffers_;
914
915 private:
916 const char *source_;
917
918 std::string file_being_parsed_;
919
920 std::vector<std::pair<Value, FieldDef *>> field_stack_;
921
922 int anonymous_counter;
923 int recurse_protection_counter;
924};
925
926// Utility functions for multiple generators:
927
928extern std::string MakeCamel(const std::string &in, bool first = true);
929
930// Generate text (JSON) from a given FlatBuffer, and a given Parser
931// object that has been populated with the corresponding schema.
932// If ident_step is 0, no indentation will be generated. Additionally,
933// if it is less than 0, no linefeeds will be generated either.
934// See idl_gen_text.cpp.
935// strict_json adds "quotes" around field names if true.
936// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
937// byte arrays in String values), returns false.
938extern bool GenerateTextFromTable(const Parser &parser,
939 const void *table,
940 const std::string &tablename,
941 std::string *text);
942extern bool GenerateText(const Parser &parser,
943 const void *flatbuffer,
944 std::string *text);
945extern bool GenerateTextFile(const Parser &parser,
946 const std::string &path,
947 const std::string &file_name);
948
949// Generate binary files from a given FlatBuffer, and a given Parser
950// object that has been populated with the corresponding schema.
951// See idl_gen_general.cpp.
952extern bool GenerateBinary(const Parser &parser,
953 const std::string &path,
954 const std::string &file_name);
955
956// Generate a C++ header from the definitions in the Parser object.
957// See idl_gen_cpp.
958extern bool GenerateCPP(const Parser &parser,
959 const std::string &path,
960 const std::string &file_name);
961
962extern bool GenerateDart(const Parser &parser,
963 const std::string &path,
964 const std::string &file_name);
965
966// Generate JavaScript or TypeScript code from the definitions in the Parser object.
967// See idl_gen_js.
968extern bool GenerateJSTS(const Parser &parser,
969 const std::string &path,
970 const std::string &file_name);
971
972// Generate Go files from the definitions in the Parser object.
973// See idl_gen_go.cpp.
974extern bool GenerateGo(const Parser &parser,
975 const std::string &path,
976 const std::string &file_name);
977
978// Generate Php code from the definitions in the Parser object.
979// See idl_gen_php.
980extern bool GeneratePhp(const Parser &parser,
981 const std::string &path,
982 const std::string &file_name);
983
984// Generate Python files from the definitions in the Parser object.
985// See idl_gen_python.cpp.
986extern bool GeneratePython(const Parser &parser,
987 const std::string &path,
988 const std::string &file_name);
989
990// Generate Lobster files from the definitions in the Parser object.
991// See idl_gen_lobster.cpp.
992extern bool GenerateLobster(const Parser &parser,
993 const std::string &path,
994 const std::string &file_name);
995
996// Generate Lua files from the definitions in the Parser object.
997// See idl_gen_lua.cpp.
998extern bool GenerateLua(const Parser &parser,
999 const std::string &path,
1000 const std::string &file_name);
1001
1002// Generate Rust files from the definitions in the Parser object.
1003// See idl_gen_rust.cpp.
1004extern bool GenerateRust(const Parser &parser,
1005 const std::string &path,
1006 const std::string &file_name);
1007
1008// Generate Json schema file
1009// See idl_gen_json_schema.cpp.
1010extern bool GenerateJsonSchema(const Parser &parser,
1011 const std::string &path,
1012 const std::string &file_name);
1013
1014extern bool GenerateKotlin(const Parser &parser, const std::string &path,
1015 const std::string &file_name);
1016
1017// Generate Java/C#/.. files from the definitions in the Parser object.
1018// See idl_gen_general.cpp.
1019extern bool GenerateGeneral(const Parser &parser,
1020 const std::string &path,
1021 const std::string &file_name);
1022
1023// Generate a schema file from the internal representation, useful after
1024// parsing a .proto schema.
1025extern std::string GenerateFBS(const Parser &parser,
1026 const std::string &file_name);
1027extern bool GenerateFBS(const Parser &parser,
1028 const std::string &path,
1029 const std::string &file_name);
1030
1031// Generate a make rule for the generated JavaScript or TypeScript code.
1032// See idl_gen_js.cpp.
1033extern std::string JSTSMakeRule(const Parser &parser,
1034 const std::string &path,
1035 const std::string &file_name);
1036
1037// Generate a make rule for the generated C++ header.
1038// See idl_gen_cpp.cpp.
1039extern std::string CPPMakeRule(const Parser &parser,
1040 const std::string &path,
1041 const std::string &file_name);
1042
1043// Generate a make rule for the generated Dart code
1044// see idl_gen_dart.cpp
1045extern std::string DartMakeRule(const Parser &parser,
1046 const std::string &path,
1047 const std::string &file_name);
1048
1049// Generate a make rule for the generated Rust code.
1050// See idl_gen_rust.cpp.
1051extern std::string RustMakeRule(const Parser &parser,
1052 const std::string &path,
1053 const std::string &file_name);
1054
1055// Generate a make rule for the generated Java/C#/... files.
1056// See idl_gen_general.cpp.
1057extern std::string GeneralMakeRule(const Parser &parser,
1058 const std::string &path,
1059 const std::string &file_name);
1060
1061// Generate a make rule for the generated text (JSON) files.
1062// See idl_gen_text.cpp.
1063extern std::string TextMakeRule(const Parser &parser,
1064 const std::string &path,
1065 const std::string &file_names);
1066
1067// Generate a make rule for the generated binary files.
1068// See idl_gen_general.cpp.
1069extern std::string BinaryMakeRule(const Parser &parser,
1070 const std::string &path,
1071 const std::string &file_name);
1072
1073// Generate GRPC Cpp interfaces.
1074// See idl_gen_grpc.cpp.
1075bool GenerateCppGRPC(const Parser &parser,
1076 const std::string &path,
1077 const std::string &file_name);
1078
1079// Generate GRPC Go interfaces.
1080// See idl_gen_grpc.cpp.
1081bool GenerateGoGRPC(const Parser &parser,
1082 const std::string &path,
1083 const std::string &file_name);
1084
1085// Generate GRPC Java classes.
1086// See idl_gen_grpc.cpp
1087bool GenerateJavaGRPC(const Parser &parser,
1088 const std::string &path,
1089 const std::string &file_name);
1090
1091} // namespace flatbuffers
1092
1093#endif // FLATBUFFERS_IDL_H_