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