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); 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; } 117 inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE && 118 t <= BASE_TYPE_ULONG; } 119 inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT || 120 t == BASE_TYPE_DOUBLE; } 121 inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG || 122 t == BASE_TYPE_ULONG; } 123 inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; } 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 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) 142 : 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 152 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 { 167 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: 179 ~SymbolTable() { 180 for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; } 181 } 182 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 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 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 { 214 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 { 229 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 { 257 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 { 287 StructDef() 288 : fixed(false), 289 predecl(true), 290 sortbysize(true), 291 has_key(false), 292 minalign(1), 293 bytesize(0) {} 294 295 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 318 inline bool IsStruct(const Type &type) { 319 return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; 320 } 321 322 inline size_t InlineSize(const Type &type) { 323 return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type); 324 } 325 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 { 331 EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {} 332 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 { 345 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 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 468 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 { 512 ParserState() 513 : cursor_(nullptr), 514 line_start_(nullptr), 515 line_(0), 516 token_(-1), 517 attr_is_trivial_ascii_string_(true) {} 518 519 protected: 520 void ResetState(const char *source) { 521 cursor_ = source; 522 line_ = 0; 523 MarkNewLine(); 524 } 525 526 void MarkNewLine() { 527 line_start_ = cursor_; 528 line_ += 1; 529 } 530 531 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: 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 568 CheckedError(const CheckedError &other) { 569 *this = other; // Use assignment operator. 570 } 571 572 ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); } 573 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()) 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 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