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 // independent from idl_parser, since this code is not needed for most clients 18 19 #include "flatbuffers/flatbuffers.h" 20 #include "flatbuffers/idl.h" 21 #include "flatbuffers/util.h" 22 #include "flatbuffers/code_generators.h" 23 24 namespace flatbuffers { 25 26 // Pedantic warning free version of toupper(). 27 inline char ToUpper(char c) { 28 return static_cast<char>(::toupper(c)); 29 } 30 31 static std::string GeneratedFileName(const std::string &path, 32 const std::string &file_name) { 33 return path + file_name + "_generated.h"; 34 } 35 36 namespace cpp { 37 class CppGenerator : public BaseGenerator { 38 public: 39 CppGenerator(const Parser &parser, const std::string &path, 40 const std::string &file_name) 41 : BaseGenerator(parser, path, file_name, "", "::"), 42 cur_name_space_(nullptr) { 43 const char *keywords[] = { 44 "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", 45 "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", 46 "break", "case", "catch", "char", "char16_t", "char32_t", "class", 47 "compl", "concept", "const", "constexpr", "const_cast", "continue", 48 "co_await", "co_return", "co_yield", "decltype", "default", "delete", 49 "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", 50 "extern", "false", "float", "for", "friend", "goto", "if", "import", 51 "inline", "int", "long", "module", "mutable", "namespace", "new", 52 "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", 53 "private", "protected", "public", "register", "reinterpret_cast", 54 "requires", "return", "short", "signed", "sizeof", "static", 55 "static_assert", "static_cast", "struct", "switch", "synchronized", 56 "template", "this", "thread_local", "throw", "true", "try", "typedef", 57 "typeid", "typename", "union", "unsigned", "using", "virtual", "void", 58 "volatile", "wchar_t", "while", "xor", "xor_eq", nullptr 59 }; 60 for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw); 61 } 62 63 std::string GenIncludeGuard() const { 64 // Generate include guard. 65 std::string guard = file_name_; 66 // Remove any non-alpha-numeric characters that may appear in a filename. 67 struct IsAlnum { 68 bool operator()(char c) { return !isalnum(c); } 69 }; 70 guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()), 71 guard.end()); 72 guard = "FLATBUFFERS_GENERATED_" + guard; 73 guard += "_"; 74 // For further uniqueness, also add the namespace. 75 auto name_space = parser_.current_namespace_; 76 for (auto it = name_space->components.begin(); 77 it != name_space->components.end(); ++it) { 78 guard += *it + "_"; 79 } 80 guard += "H_"; 81 std::transform(guard.begin(), guard.end(), guard.begin(), ToUpper); 82 return guard; 83 } 84 85 void GenIncludeDependencies() { 86 int num_includes = 0; 87 for (auto it = parser_.native_included_files_.begin(); 88 it != parser_.native_included_files_.end(); ++it) { 89 code_ += "#include \"" + *it + "\""; 90 num_includes++; 91 } 92 for (auto it = parser_.included_files_.begin(); 93 it != parser_.included_files_.end(); ++it) { 94 if (it->second.empty()) 95 continue; 96 auto noext = flatbuffers::StripExtension(it->second); 97 auto basename = flatbuffers::StripPath(noext); 98 99 code_ += "#include \"" + parser_.opts.include_prefix + 100 (parser_.opts.keep_include_path ? noext : basename) + 101 "_generated.h\""; 102 num_includes++; 103 } 104 if (num_includes) code_ += ""; 105 } 106 107 std::string EscapeKeyword(const std::string &name) const { 108 return keywords_.find(name) == keywords_.end() ? name : name + "_"; 109 } 110 111 std::string Name(const Definition &def) const { 112 return EscapeKeyword(def.name); 113 } 114 115 std::string Name(const EnumVal &ev) const { 116 return EscapeKeyword(ev.name); 117 } 118 119 // Iterate through all definitions we haven't generate code for (enums, 120 // structs, and tables) and output them to a single file. 121 bool generate() { 122 code_.Clear(); 123 code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; 124 125 const auto include_guard = GenIncludeGuard(); 126 code_ += "#ifndef " + include_guard; 127 code_ += "#define " + include_guard; 128 code_ += ""; 129 130 if (parser_.opts.gen_nullable) { 131 code_ += "#pragma clang system_header\n\n"; 132 } 133 134 code_ += "#include \"flatbuffers/flatbuffers.h\""; 135 if (parser_.uses_flexbuffers_) { 136 code_ += "#include \"flatbuffers/flexbuffers.h\""; 137 } 138 code_ += ""; 139 140 if (parser_.opts.include_dependence_headers) { 141 GenIncludeDependencies(); 142 } 143 144 assert(!cur_name_space_); 145 146 // Generate forward declarations for all structs/tables, since they may 147 // have circular references. 148 for (auto it = parser_.structs_.vec.begin(); 149 it != parser_.structs_.vec.end(); ++it) { 150 const auto &struct_def = **it; 151 if (!struct_def.generated) { 152 SetNameSpace(struct_def.defined_namespace); 153 code_ += "struct " + Name(struct_def) + ";"; 154 if (parser_.opts.generate_object_based_api && !struct_def.fixed) { 155 code_ += "struct " + 156 NativeName(Name(struct_def), &struct_def, parser_.opts) + 157 ";"; 158 } 159 code_ += ""; 160 } 161 } 162 163 // Generate code for all the enum declarations. 164 for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); 165 ++it) { 166 const auto &enum_def = **it; 167 if (!enum_def.generated) { 168 SetNameSpace(enum_def.defined_namespace); 169 GenEnum(enum_def); 170 } 171 } 172 173 // Generate code for all structs, then all tables. 174 for (auto it = parser_.structs_.vec.begin(); 175 it != parser_.structs_.vec.end(); ++it) { 176 const auto &struct_def = **it; 177 if (struct_def.fixed && !struct_def.generated) { 178 SetNameSpace(struct_def.defined_namespace); 179 GenStruct(struct_def); 180 } 181 } 182 for (auto it = parser_.structs_.vec.begin(); 183 it != parser_.structs_.vec.end(); ++it) { 184 const auto &struct_def = **it; 185 if (!struct_def.fixed && !struct_def.generated) { 186 SetNameSpace(struct_def.defined_namespace); 187 GenTable(struct_def); 188 } 189 } 190 for (auto it = parser_.structs_.vec.begin(); 191 it != parser_.structs_.vec.end(); ++it) { 192 const auto &struct_def = **it; 193 if (!struct_def.fixed && !struct_def.generated) { 194 SetNameSpace(struct_def.defined_namespace); 195 GenTablePost(struct_def); 196 } 197 } 198 199 // Generate code for union verifiers. 200 for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); 201 ++it) { 202 const auto &enum_def = **it; 203 if (enum_def.is_union && !enum_def.generated) { 204 SetNameSpace(enum_def.defined_namespace); 205 GenUnionPost(enum_def); 206 } 207 } 208 209 // Generate code for mini reflection. 210 if (parser_.opts.mini_reflect != IDLOptions::kNone) { 211 // To break cyclic dependencies, first pre-declare all tables/structs. 212 for (auto it = parser_.structs_.vec.begin(); 213 it != parser_.structs_.vec.end(); ++it) { 214 const auto &struct_def = **it; 215 if (!struct_def.generated) { 216 SetNameSpace(struct_def.defined_namespace); 217 GenMiniReflectPre(&struct_def); 218 } 219 } 220 // Then the unions/enums that may refer to them. 221 for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); 222 ++it) { 223 const auto &enum_def = **it; 224 if (!enum_def.generated) { 225 SetNameSpace(enum_def.defined_namespace); 226 GenMiniReflect(nullptr, &enum_def); 227 } 228 } 229 // Then the full tables/structs. 230 for (auto it = parser_.structs_.vec.begin(); 231 it != parser_.structs_.vec.end(); ++it) { 232 const auto &struct_def = **it; 233 if (!struct_def.generated) { 234 SetNameSpace(struct_def.defined_namespace); 235 GenMiniReflect(&struct_def, nullptr); 236 } 237 } 238 } 239 240 // Generate convenient global helper functions: 241 if (parser_.root_struct_def_) { 242 auto &struct_def = *parser_.root_struct_def_; 243 SetNameSpace(struct_def.defined_namespace); 244 auto name = Name(struct_def); 245 auto qualified_name = 246 cur_name_space_->GetFullyQualifiedName(name); 247 auto cpp_name = TranslateNameSpace(qualified_name); 248 249 code_.SetValue("STRUCT_NAME", name); 250 code_.SetValue("CPP_NAME", cpp_name); 251 code_.SetValue("NULLABLE_EXT", NullableExtension()); 252 253 // The root datatype accessor: 254 code_ += "inline \\"; 255 code_ += "const {{CPP_NAME}} *{{NULLABLE_EXT}}Get{{STRUCT_NAME}}(const void *buf) {"; 256 code_ += " return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);"; 257 code_ += "}"; 258 code_ += ""; 259 260 if (parser_.opts.mutable_buffer) { 261 code_ += "inline \\"; 262 code_ += "{{STRUCT_NAME}} *GetMutable{{STRUCT_NAME}}(void *buf) {"; 263 code_ += " return flatbuffers::GetMutableRoot<{{STRUCT_NAME}}>(buf);"; 264 code_ += "}"; 265 code_ += ""; 266 } 267 268 if (parser_.file_identifier_.length()) { 269 // Return the identifier 270 code_ += "inline const char *{{STRUCT_NAME}}Identifier() {"; 271 code_ += " return \"" + parser_.file_identifier_ + "\";"; 272 code_ += "}"; 273 code_ += ""; 274 275 // Check if a buffer has the identifier. 276 code_ += "inline \\"; 277 code_ += "bool {{STRUCT_NAME}}BufferHasIdentifier(const void *buf) {"; 278 code_ += " return flatbuffers::BufferHasIdentifier("; 279 code_ += " buf, {{STRUCT_NAME}}Identifier());"; 280 code_ += "}"; 281 code_ += ""; 282 } 283 284 // The root verifier. 285 if (parser_.file_identifier_.length()) { 286 code_.SetValue("ID", name + "Identifier()"); 287 } else { 288 code_.SetValue("ID", "nullptr"); 289 } 290 291 code_ += "inline bool Verify{{STRUCT_NAME}}Buffer("; 292 code_ += " flatbuffers::Verifier &verifier) {"; 293 code_ += " return verifier.VerifyBuffer<{{CPP_NAME}}>({{ID}});"; 294 code_ += "}"; 295 code_ += ""; 296 297 if (parser_.file_extension_.length()) { 298 // Return the extension 299 code_ += "inline const char *{{STRUCT_NAME}}Extension() {"; 300 code_ += " return \"" + parser_.file_extension_ + "\";"; 301 code_ += "}"; 302 code_ += ""; 303 } 304 305 // Finish a buffer with a given root object: 306 code_ += "inline void Finish{{STRUCT_NAME}}Buffer("; 307 code_ += " flatbuffers::FlatBufferBuilder &fbb,"; 308 code_ += " flatbuffers::Offset<{{CPP_NAME}}> root) {"; 309 if (parser_.file_identifier_.length()) 310 code_ += " fbb.Finish(root, {{STRUCT_NAME}}Identifier());"; 311 else 312 code_ += " fbb.Finish(root);"; 313 code_ += "}"; 314 code_ += ""; 315 316 if (parser_.opts.generate_object_based_api) { 317 // A convenient root unpack function. 318 auto native_name = 319 NativeName(WrapInNameSpace(struct_def), &struct_def, parser_.opts); 320 code_.SetValue("UNPACK_RETURN", 321 GenTypeNativePtr(native_name, nullptr, false)); 322 code_.SetValue("UNPACK_TYPE", 323 GenTypeNativePtr(native_name, nullptr, true)); 324 325 code_ += "inline {{UNPACK_RETURN}} UnPack{{STRUCT_NAME}}("; 326 code_ += " const void *buf,"; 327 code_ += " const flatbuffers::resolver_function_t *res = nullptr) {"; 328 code_ += " return {{UNPACK_TYPE}}\\"; 329 code_ += "(Get{{STRUCT_NAME}}(buf)->UnPack(res));"; 330 code_ += "}"; 331 code_ += ""; 332 } 333 } 334 335 if (cur_name_space_) SetNameSpace(nullptr); 336 337 // Close the include guard. 338 code_ += "#endif // " + include_guard; 339 340 const auto file_path = GeneratedFileName(path_, file_name_); 341 const auto final_code = code_.ToString(); 342 return SaveFile(file_path.c_str(), final_code, false); 343 } 344 345 private: 346 CodeWriter code_; 347 348 std::set<std::string> keywords_; 349 350 // This tracks the current namespace so we can insert namespace declarations. 351 const Namespace *cur_name_space_; 352 353 const Namespace *CurrentNameSpace() const { return cur_name_space_; } 354 355 // Translates a qualified name in flatbuffer text format to the same name in 356 // the equivalent C++ namespace. 357 static std::string TranslateNameSpace(const std::string &qualified_name) { 358 std::string cpp_qualified_name = qualified_name; 359 size_t start_pos = 0; 360 while ((start_pos = cpp_qualified_name.find(".", start_pos)) != 361 std::string::npos) { 362 cpp_qualified_name.replace(start_pos, 1, "::"); 363 } 364 return cpp_qualified_name; 365 } 366 367 void GenComment(const std::vector<std::string> &dc, const char *prefix = "") { 368 std::string text; 369 ::flatbuffers::GenComment(dc, &text, nullptr, prefix); 370 code_ += text + "\\"; 371 } 372 373 // Return a C++ type from the table in idl.h 374 std::string GenTypeBasic(const Type &type, bool user_facing_type) const { 375 static const char *ctypename[] = { 376 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 377 #CTYPE, 378 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 379 #undef FLATBUFFERS_TD 380 }; 381 if (user_facing_type) { 382 if (type.enum_def) return WrapInNameSpace(*type.enum_def); 383 if (type.base_type == BASE_TYPE_BOOL) return "bool"; 384 } 385 return ctypename[type.base_type]; 386 } 387 388 // Return a C++ pointer type, specialized to the actual struct/table types, 389 // and vector element types. 390 std::string GenTypePointer(const Type &type) const { 391 switch (type.base_type) { 392 case BASE_TYPE_STRING: { 393 return "flatbuffers::String"; 394 } 395 case BASE_TYPE_VECTOR: { 396 const auto type_name = GenTypeWire(type.VectorType(), "", false); 397 return "flatbuffers::Vector<" + type_name + ">"; 398 } 399 case BASE_TYPE_STRUCT: { 400 return WrapInNameSpace(*type.struct_def); 401 } 402 case BASE_TYPE_UNION: 403 // fall through 404 default: { 405 return "void"; 406 } 407 } 408 } 409 410 // Return a C++ type for any type (scalar/pointer) specifically for 411 // building a flatbuffer. 412 std::string GenTypeWire(const Type &type, const char *postfix, 413 bool user_facing_type) const { 414 if (IsScalar(type.base_type)) { 415 return GenTypeBasic(type, user_facing_type) + postfix; 416 } else if (IsStruct(type)) { 417 return "const " + GenTypePointer(type) + " *"; 418 } else { 419 return "flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix; 420 } 421 } 422 423 // Return a C++ type for any type (scalar/pointer) that reflects its 424 // serialized size. 425 std::string GenTypeSize(const Type &type) const { 426 if (IsScalar(type.base_type)) { 427 return GenTypeBasic(type, false); 428 } else if (IsStruct(type)) { 429 return GenTypePointer(type); 430 } else { 431 return "flatbuffers::uoffset_t"; 432 } 433 } 434 435 std::string NullableExtension() { 436 return parser_.opts.gen_nullable ? " _Nullable " : ""; 437 } 438 439 static std::string NativeName(const std::string &name, const StructDef *sd, const IDLOptions & opts) { 440 return sd && !sd->fixed ? opts.object_prefix + name + opts.object_suffix : name; 441 } 442 443 const std::string &PtrType(const FieldDef *field) { 444 auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr; 445 return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type; 446 } 447 448 const std::string NativeString(const FieldDef *field) { 449 auto attr = field ? field->attributes.Lookup("cpp_str_type") : nullptr; 450 auto &ret = attr ? attr->constant : parser_.opts.cpp_object_api_string_type; 451 if (ret.empty()) { 452 return "std::string"; 453 } 454 return ret; 455 } 456 457 std::string GenTypeNativePtr(const std::string &type, const FieldDef *field, 458 bool is_constructor) { 459 auto &ptr_type = PtrType(field); 460 if (ptr_type != "naked") { 461 return ptr_type + "<" + type + ">"; 462 } else if (is_constructor) { 463 return ""; 464 } else { 465 return type + " *"; 466 } 467 } 468 469 std::string GenPtrGet(const FieldDef &field) { 470 auto &ptr_type = PtrType(&field); 471 return ptr_type == "naked" ? "" : ".get()"; 472 } 473 474 std::string GenTypeNative(const Type &type, bool invector, 475 const FieldDef &field) { 476 switch (type.base_type) { 477 case BASE_TYPE_STRING: { 478 return NativeString(&field); 479 } 480 case BASE_TYPE_VECTOR: { 481 const auto type_name = GenTypeNative(type.VectorType(), true, field); 482 if (type.struct_def && type.struct_def->attributes.Lookup("native_custom_alloc")) { 483 auto native_custom_alloc = type.struct_def->attributes.Lookup("native_custom_alloc"); 484 return "std::vector<" + type_name + "," + native_custom_alloc->constant + "<" + type_name + ">>"; 485 } else 486 return "std::vector<" + type_name + ">"; 487 } 488 case BASE_TYPE_STRUCT: { 489 auto type_name = WrapInNameSpace(*type.struct_def); 490 if (IsStruct(type)) { 491 auto native_type = type.struct_def->attributes.Lookup("native_type"); 492 if (native_type) { 493 type_name = native_type->constant; 494 } 495 if (invector || field.native_inline) { 496 return type_name; 497 } else { 498 return GenTypeNativePtr(type_name, &field, false); 499 } 500 } else { 501 return GenTypeNativePtr(NativeName(type_name, type.struct_def, parser_.opts), 502 &field, false); 503 } 504 } 505 case BASE_TYPE_UNION: { 506 return type.enum_def->name + "Union"; 507 } 508 default: { 509 return GenTypeBasic(type, true); 510 } 511 } 512 } 513 514 // Return a C++ type for any type (scalar/pointer) specifically for 515 // using a flatbuffer. 516 std::string GenTypeGet(const Type &type, const char *afterbasic, 517 const char *beforeptr, const char *afterptr, 518 bool user_facing_type) { 519 if (IsScalar(type.base_type)) { 520 return GenTypeBasic(type, user_facing_type) + afterbasic; 521 } else { 522 return beforeptr + GenTypePointer(type) + afterptr; 523 } 524 } 525 526 std::string GenEnumDecl(const EnumDef &enum_def) const { 527 const IDLOptions &opts = parser_.opts; 528 return (opts.scoped_enums ? "enum class " : "enum ") + Name(enum_def); 529 } 530 531 std::string GenEnumValDecl(const EnumDef &enum_def, 532 const std::string &enum_val) const { 533 const IDLOptions &opts = parser_.opts; 534 return opts.prefixed_enums ? Name(enum_def) + "_" + enum_val : enum_val; 535 } 536 537 std::string GetEnumValUse(const EnumDef &enum_def, 538 const EnumVal &enum_val) const { 539 const IDLOptions &opts = parser_.opts; 540 if (opts.scoped_enums) { 541 return Name(enum_def) + "::" + Name(enum_val); 542 } else if (opts.prefixed_enums) { 543 return Name(enum_def) + "_" + Name(enum_val); 544 } else { 545 return Name(enum_val); 546 } 547 } 548 549 std::string StripUnionType(const std::string &name) { 550 return name.substr(0, name.size() - strlen(UnionTypeFieldSuffix())); 551 } 552 553 std::string GetUnionElement(const EnumVal &ev, bool wrap, bool actual_type, 554 bool native_type = false) { 555 if (ev.union_type.base_type == BASE_TYPE_STRUCT) { 556 auto name = actual_type ? ev.union_type.struct_def->name : Name(ev); 557 return wrap 558 ? WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name) 559 : name; 560 } else if (ev.union_type.base_type == BASE_TYPE_STRING) { 561 return actual_type 562 ? (native_type ? "std::string" : "flatbuffers::String") 563 : Name(ev); 564 } else { 565 assert(false); 566 return Name(ev); 567 } 568 } 569 570 std::string UnionVerifySignature(const EnumDef &enum_def) { 571 return "bool Verify" + Name(enum_def) + 572 "(flatbuffers::Verifier &verifier, const void *obj, " + 573 Name(enum_def) + " type)"; 574 } 575 576 std::string UnionVectorVerifySignature(const EnumDef &enum_def) { 577 return "bool Verify" + Name(enum_def) + "Vector" + 578 "(flatbuffers::Verifier &verifier, " + 579 "const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " + 580 "const flatbuffers::Vector<uint8_t> *types)"; 581 } 582 583 std::string UnionUnPackSignature(const EnumDef &enum_def, 584 bool inclass) { 585 return (inclass ? "static " : "") + 586 std::string("void *") + 587 (inclass ? "" : Name(enum_def) + "Union::") + 588 "UnPack(const void *obj, " + Name(enum_def) + 589 " type, const flatbuffers::resolver_function_t *resolver)"; 590 } 591 592 std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) { 593 return "flatbuffers::Offset<void> " + 594 (inclass ? "" : Name(enum_def) + "Union::") + 595 "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + 596 "const flatbuffers::rehasher_function_t *_rehasher" + 597 (inclass ? " = nullptr" : "") + ") const"; 598 } 599 600 std::string TableCreateSignature(const StructDef &struct_def, 601 bool predecl, 602 const IDLOptions & opts) { 603 return "flatbuffers::Offset<" + Name(struct_def) + "> Create" + 604 Name(struct_def) + 605 "(flatbuffers::FlatBufferBuilder &_fbb, const " + 606 NativeName(Name(struct_def), &struct_def, opts) + 607 " *_o, const flatbuffers::rehasher_function_t *_rehasher" + 608 (predecl ? " = nullptr" : "") + ")"; 609 } 610 611 std::string TablePackSignature(const StructDef &struct_def, 612 bool inclass, 613 const IDLOptions & opts) { 614 return std::string(inclass ? "static " : "") + 615 "flatbuffers::Offset<" + Name(struct_def) + "> " + 616 (inclass ? "" : Name(struct_def) + "::") + 617 "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + 618 "const " + NativeName(Name(struct_def), &struct_def, opts) + "* _o, " + 619 "const flatbuffers::rehasher_function_t *_rehasher" + 620 (inclass ? " = nullptr" : "") + ")"; 621 } 622 623 std::string TableUnPackSignature(const StructDef &struct_def, 624 bool inclass, 625 const IDLOptions & opts) { 626 return NativeName(Name(struct_def), &struct_def, opts) + " *" + 627 (inclass ? "" : Name(struct_def) + "::") + 628 "UnPack(const flatbuffers::resolver_function_t *_resolver" + 629 (inclass ? " = nullptr" : "") + ") const"; 630 } 631 632 std::string TableUnPackToSignature(const StructDef &struct_def, 633 bool inclass, 634 const IDLOptions & opts) { 635 return "void " + (inclass ? "" : Name(struct_def) + "::") + 636 "UnPackTo(" + NativeName(Name(struct_def), &struct_def, opts) + " *" + 637 "_o, const flatbuffers::resolver_function_t *_resolver" + 638 (inclass ? " = nullptr" : "") + ") const"; 639 } 640 641 void GenMiniReflectPre(const StructDef *struct_def) { 642 code_.SetValue("NAME", struct_def->name); 643 code_ += "inline flatbuffers::TypeTable *{{NAME}}TypeTable();"; 644 code_ += ""; 645 } 646 647 void GenMiniReflect(const StructDef *struct_def, 648 const EnumDef *enum_def) { 649 code_.SetValue("NAME", struct_def ? struct_def->name : enum_def->name); 650 code_.SetValue("SEQ_TYPE", struct_def 651 ? (struct_def->fixed ? "ST_STRUCT" : "ST_TABLE") 652 : (enum_def->is_union ? "ST_UNION" : "ST_ENUM")); 653 auto num_fields = struct_def 654 ? struct_def->fields.vec.size() 655 : enum_def->vals.vec.size(); 656 code_.SetValue("NUM_FIELDS", NumToString(num_fields)); 657 std::vector<std::string> names; 658 std::vector<Type> types; 659 bool consecutive_enum_from_zero = true; 660 if (struct_def) { 661 for (auto it = struct_def->fields.vec.begin(); 662 it != struct_def->fields.vec.end(); ++it) { 663 const auto &field = **it; 664 names.push_back(Name(field)); 665 types.push_back(field.value.type); 666 } 667 } else { 668 for (auto it = enum_def->vals.vec.begin(); it != enum_def->vals.vec.end(); 669 ++it) { 670 const auto &ev = **it; 671 names.push_back(Name(ev)); 672 types.push_back(enum_def->is_union ? ev.union_type 673 : Type(enum_def->underlying_type)); 674 if (static_cast<int64_t>(it - enum_def->vals.vec.begin()) != ev.value) { 675 consecutive_enum_from_zero = false; 676 } 677 } 678 } 679 std::string ts; 680 std::vector<std::string> type_refs; 681 for (auto it = types.begin(); it != types.end(); ++it) { 682 auto &type = *it; 683 if (!ts.empty()) ts += ",\n "; 684 auto is_vector = type.base_type == BASE_TYPE_VECTOR; 685 auto bt = is_vector ? type.element : type.base_type; 686 auto et = IsScalar(bt) || bt == BASE_TYPE_STRING 687 ? bt - BASE_TYPE_UTYPE + ET_UTYPE 688 : ET_SEQUENCE; 689 int ref_idx = -1; 690 std::string ref_name = type.struct_def 691 ? WrapInNameSpace(*type.struct_def) 692 : type.enum_def 693 ? WrapInNameSpace(*type.enum_def) 694 : ""; 695 if (!ref_name.empty()) { 696 auto rit = type_refs.begin(); 697 for (; rit != type_refs.end(); ++rit) { 698 if (*rit == ref_name) { 699 ref_idx = static_cast<int>(rit - type_refs.begin()); 700 break; 701 } 702 } 703 if (rit == type_refs.end()) { 704 ref_idx = static_cast<int>(type_refs.size()); 705 type_refs.push_back(ref_name); 706 } 707 } 708 ts += "{ flatbuffers::" + std::string(ElementaryTypeNames()[et]) + ", " + 709 NumToString(is_vector) + ", " + NumToString(ref_idx) + " }"; 710 } 711 std::string rs; 712 for (auto it = type_refs.begin(); it != type_refs.end(); ++it) { 713 if (!rs.empty()) rs += ",\n "; 714 rs += *it + "TypeTable"; 715 } 716 std::string ns; 717 for (auto it = names.begin(); it != names.end(); ++it) { 718 if (!ns.empty()) ns += ",\n "; 719 ns += "\"" + *it + "\""; 720 } 721 std::string vs; 722 if (enum_def && !consecutive_enum_from_zero) { 723 for (auto it = enum_def->vals.vec.begin(); it != enum_def->vals.vec.end(); 724 ++it) { 725 const auto &ev = **it; 726 if (!vs.empty()) vs += ", "; 727 vs += NumToString(ev.value); 728 } 729 } else if (struct_def && struct_def->fixed) { 730 for (auto it = struct_def->fields.vec.begin(); 731 it != struct_def->fields.vec.end(); ++it) { 732 const auto &field = **it; 733 vs += NumToString(field.value.offset); 734 vs += ", "; 735 } 736 vs += NumToString(struct_def->bytesize); 737 } 738 code_.SetValue("TYPES", ts); 739 code_.SetValue("REFS", rs); 740 code_.SetValue("NAMES", ns); 741 code_.SetValue("VALUES", vs); 742 code_ += "inline flatbuffers::TypeTable *{{NAME}}TypeTable() {"; 743 if (num_fields) { 744 code_ += " static flatbuffers::TypeCode type_codes[] = {"; 745 code_ += " {{TYPES}}"; 746 code_ += " };"; 747 } 748 if (!type_refs.empty()) { 749 code_ += " static flatbuffers::TypeFunction type_refs[] = {"; 750 code_ += " {{REFS}}"; 751 code_ += " };"; 752 } 753 if (!vs.empty()) { 754 code_ += " static const int32_t values[] = { {{VALUES}} };"; 755 } 756 auto has_names = num_fields && 757 parser_.opts.mini_reflect == IDLOptions::kTypesAndNames; 758 if (has_names) { 759 code_ += " static const char *names[] = {"; 760 code_ += " {{NAMES}}"; 761 code_ += " };"; 762 } 763 code_ += " static flatbuffers::TypeTable tt = {"; 764 code_ += std::string(" flatbuffers::{{SEQ_TYPE}}, {{NUM_FIELDS}}, ") + 765 (num_fields ? "type_codes, " : "nullptr, ") + 766 (!type_refs.empty() ? "type_refs, ": "nullptr, " ) + 767 (!vs.empty() ? "values, " : "nullptr, ") + 768 (has_names ? "names" : "nullptr"); 769 code_ += " };"; 770 code_ += " return &tt;"; 771 code_ += "}"; 772 code_ += ""; 773 } 774 775 // Generate an enum declaration, 776 // an enum string lookup table, 777 // and an enum array of values 778 void GenEnum(const EnumDef &enum_def) { 779 code_.SetValue("ENUM_NAME", Name(enum_def)); 780 code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false)); 781 code_.SetValue("SEP", ""); 782 783 GenComment(enum_def.doc_comment); 784 code_ += GenEnumDecl(enum_def) + "\\"; 785 if (parser_.opts.scoped_enums) 786 code_ += " : {{BASE_TYPE}}\\"; 787 code_ += " {"; 788 789 int64_t anyv = 0; 790 const EnumVal *minv = nullptr, *maxv = nullptr; 791 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 792 ++it) { 793 const auto &ev = **it; 794 795 GenComment(ev.doc_comment, " "); 796 code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(ev))); 797 code_.SetValue("VALUE", NumToString(ev.value)); 798 code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; 799 code_.SetValue("SEP", ",\n"); 800 801 minv = !minv || minv->value > ev.value ? &ev : minv; 802 maxv = !maxv || maxv->value < ev.value ? &ev : maxv; 803 anyv |= ev.value; 804 } 805 806 if (parser_.opts.scoped_enums || parser_.opts.prefixed_enums) { 807 assert(minv && maxv); 808 809 code_.SetValue("SEP", ",\n"); 810 if (enum_def.attributes.Lookup("bit_flags")) { 811 code_.SetValue("KEY", GenEnumValDecl(enum_def, "NONE")); 812 code_.SetValue("VALUE", "0"); 813 code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; 814 815 code_.SetValue("KEY", GenEnumValDecl(enum_def, "ANY")); 816 code_.SetValue("VALUE", NumToString(anyv)); 817 code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; 818 } else { // MIN & MAX are useless for bit_flags 819 code_.SetValue("KEY",GenEnumValDecl(enum_def, "MIN")); 820 code_.SetValue("VALUE", GenEnumValDecl(enum_def, minv->name)); 821 code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; 822 823 code_.SetValue("KEY",GenEnumValDecl(enum_def, "MAX")); 824 code_.SetValue("VALUE", GenEnumValDecl(enum_def, maxv->name)); 825 code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; 826 } 827 } 828 code_ += ""; 829 code_ += "};"; 830 831 if (parser_.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags")) { 832 code_ += "DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})"; 833 } 834 code_ += ""; 835 836 // Generate an array of all enumeration values 837 auto num_fields = NumToString(enum_def.vals.vec.size()); 838 code_ += "inline {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" + num_fields + "] {"; 839 code_ += " static {{ENUM_NAME}} values[] = {"; 840 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 841 ++it) { 842 const auto &ev = **it; 843 auto value = GetEnumValUse(enum_def, ev); 844 auto suffix = *it != enum_def.vals.vec.back() ? "," : ""; 845 code_ += " " + value + suffix; 846 } 847 code_ += " };"; 848 code_ += " return values;"; 849 code_ += "}"; 850 code_ += ""; 851 852 // Generate a generate string table for enum values. 853 // Problem is, if values are very sparse that could generate really big 854 // tables. Ideally in that case we generate a map lookup instead, but for 855 // the moment we simply don't output a table at all. 856 auto range = 857 enum_def.vals.vec.back()->value - enum_def.vals.vec.front()->value + 1; 858 // Average distance between values above which we consider a table 859 // "too sparse". Change at will. 860 static const int kMaxSparseness = 5; 861 if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < 862 kMaxSparseness) { 863 code_ += "inline const char **EnumNames{{ENUM_NAME}}() {"; 864 code_ += " static const char *names[] = {"; 865 866 auto val = enum_def.vals.vec.front()->value; 867 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 868 ++it) { 869 const auto &ev = **it; 870 while (val++ != ev.value) { 871 code_ += " \"\","; 872 } 873 code_ += " \"" + Name(ev) + "\","; 874 } 875 code_ += " nullptr"; 876 code_ += " };"; 877 878 code_ += " return names;"; 879 code_ += "}"; 880 code_ += ""; 881 882 code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {"; 883 884 code_ += " const size_t index = static_cast<int>(e)\\"; 885 if (enum_def.vals.vec.front()->value) { 886 auto vals = GetEnumValUse(enum_def, *enum_def.vals.vec.front()); 887 code_ += " - static_cast<int>(" + vals + ")\\"; 888 } 889 code_ += ";"; 890 891 code_ += " return EnumNames{{ENUM_NAME}}()[index];"; 892 code_ += "}"; 893 code_ += ""; 894 } 895 896 // Generate type traits for unions to map from a type to union enum value. 897 if (enum_def.is_union && !enum_def.uses_type_aliases) { 898 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 899 ++it) { 900 const auto &ev = **it; 901 902 if (it == enum_def.vals.vec.begin()) { 903 code_ += "template<typename T> struct {{ENUM_NAME}}Traits {"; 904 } 905 else { 906 auto name = GetUnionElement(ev, true, true); 907 code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {"; 908 } 909 910 auto value = GetEnumValUse(enum_def, ev); 911 code_ += " static const {{ENUM_NAME}} enum_value = " + value + ";"; 912 code_ += "};"; 913 code_ += ""; 914 } 915 } 916 917 if (parser_.opts.generate_object_based_api && enum_def.is_union) { 918 // Generate a union type 919 code_.SetValue("NAME", Name(enum_def)); 920 code_.SetValue("NONE", 921 GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"))); 922 923 code_ += "struct {{NAME}}Union {"; 924 code_ += " {{NAME}} type;"; 925 code_ += " void *value;"; 926 code_ += ""; 927 code_ += " {{NAME}}Union() : type({{NONE}}), value(nullptr) {}"; 928 code_ += " {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :"; 929 code_ += " type({{NONE}}), value(nullptr)"; 930 code_ += " { std::swap(type, u.type); std::swap(value, u.value); }"; 931 code_ += " {{NAME}}Union(const {{NAME}}Union &) FLATBUFFERS_NOEXCEPT;"; 932 code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &u) FLATBUFFERS_NOEXCEPT"; 933 code_ += " { {{NAME}}Union t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }"; 934 code_ += " {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT"; 935 code_ += " { std::swap(type, u.type); std::swap(value, u.value); return *this; }"; 936 code_ += " ~{{NAME}}Union() { Reset(); }"; 937 code_ += ""; 938 code_ += " void Reset();"; 939 code_ += ""; 940 if (!enum_def.uses_type_aliases) { 941 code_ += "#ifndef FLATBUFFERS_CPP98_STL"; 942 code_ += " template <typename T>"; 943 code_ += " void Set(T&& val) {"; 944 code_ += " Reset();"; 945 code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;"; 946 code_ += " if (type != {{NONE}}) {"; 947 code_ += " value = new T(std::forward<T>(val));"; 948 code_ += " }"; 949 code_ += " }"; 950 code_ += "#endif // FLATBUFFERS_CPP98_STL"; 951 code_ += ""; 952 } 953 code_ += " " + UnionUnPackSignature(enum_def, true) + ";"; 954 code_ += " " + UnionPackSignature(enum_def, true) + ";"; 955 code_ += ""; 956 957 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 958 ++it) { 959 const auto &ev = **it; 960 if (!ev.value) { 961 continue; 962 } 963 964 const auto native_type = 965 NativeName(GetUnionElement(ev, true, true, true), 966 ev.union_type.struct_def, parser_.opts); 967 code_.SetValue("NATIVE_TYPE", native_type); 968 code_.SetValue("NATIVE_NAME", Name(ev)); 969 code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev)); 970 971 code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {"; 972 code_ += " return type == {{NATIVE_ID}} ?"; 973 code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(value) : nullptr;"; 974 code_ += " }"; 975 976 code_ += " const {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() const {"; 977 code_ += " return type == {{NATIVE_ID}} ?"; 978 code_ += " reinterpret_cast<const {{NATIVE_TYPE}} *>(value) : nullptr;"; 979 code_ += " }"; 980 } 981 code_ += "};"; 982 code_ += ""; 983 } 984 985 if (enum_def.is_union) { 986 code_ += UnionVerifySignature(enum_def) + ";"; 987 code_ += UnionVectorVerifySignature(enum_def) + ";"; 988 code_ += ""; 989 } 990 } 991 992 void GenUnionPost(const EnumDef &enum_def) { 993 // Generate a verifier function for this union that can be called by the 994 // table verifier functions. It uses a switch case to select a specific 995 // verifier function to call, this should be safe even if the union type 996 // has been corrupted, since the verifiers will simply fail when called 997 // on the wrong type. 998 code_.SetValue("ENUM_NAME", Name(enum_def)); 999 1000 code_ += "inline " + UnionVerifySignature(enum_def) + " {"; 1001 code_ += " switch (type) {"; 1002 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1003 ++it) { 1004 const auto &ev = **it; 1005 code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); 1006 1007 if (ev.value) { 1008 code_.SetValue("TYPE", GetUnionElement(ev, true, true)); 1009 code_ += " case {{LABEL}}: {"; 1010 auto getptr = 1011 " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);"; 1012 if (ev.union_type.base_type == BASE_TYPE_STRUCT) { 1013 if (ev.union_type.struct_def->fixed) { 1014 code_ += " return true;"; 1015 } else { 1016 code_ += getptr; 1017 code_ += " return verifier.VerifyTable(ptr);"; 1018 } 1019 } else if (ev.union_type.base_type == BASE_TYPE_STRING) { 1020 code_ += getptr; 1021 code_ += " return verifier.Verify(ptr);"; 1022 } else { 1023 assert(false); 1024 } 1025 code_ += " }"; 1026 } else { 1027 code_ += " case {{LABEL}}: {"; 1028 code_ += " return true;"; // "NONE" enum value. 1029 code_ += " }"; 1030 } 1031 } 1032 code_ += " default: return false;"; 1033 code_ += " }"; 1034 code_ += "}"; 1035 code_ += ""; 1036 1037 code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {"; 1038 code_ += " if (values->size() != types->size()) return false;"; 1039 code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {"; 1040 code_ += " if (!Verify" + Name(enum_def) + "("; 1041 code_ += " verifier, values->Get(i), types->GetEnum<" + Name(enum_def) + ">(i))) {"; 1042 code_ += " return false;"; 1043 code_ += " }"; 1044 code_ += " }"; 1045 code_ += " return true;"; 1046 code_ += "}"; 1047 code_ += ""; 1048 1049 if (parser_.opts.generate_object_based_api) { 1050 // Generate union Unpack() and Pack() functions. 1051 code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {"; 1052 code_ += " switch (type) {"; 1053 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1054 ++it) { 1055 const auto &ev = **it; 1056 if (!ev.value) { 1057 continue; 1058 } 1059 1060 code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); 1061 code_.SetValue("TYPE", GetUnionElement(ev, true, true)); 1062 code_ += " case {{LABEL}}: {"; 1063 code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);"; 1064 if (ev.union_type.base_type == BASE_TYPE_STRUCT) { 1065 if (ev.union_type.struct_def->fixed) { 1066 code_ += " return new " + 1067 WrapInNameSpace(*ev.union_type.struct_def) + "(*ptr);"; 1068 } else { 1069 code_ += " return ptr->UnPack(resolver);"; 1070 } 1071 } else if (ev.union_type.base_type == BASE_TYPE_STRING) { 1072 code_ += " return new std::string(ptr->c_str(), ptr->size());"; 1073 } else { 1074 assert(false); 1075 } 1076 code_ += " }"; 1077 } 1078 code_ += " default: return nullptr;"; 1079 code_ += " }"; 1080 code_ += "}"; 1081 code_ += ""; 1082 1083 code_ += "inline " + UnionPackSignature(enum_def, false) + " {"; 1084 code_ += " switch (type) {"; 1085 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1086 ++it) { 1087 auto &ev = **it; 1088 if (!ev.value) { 1089 continue; 1090 } 1091 1092 code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); 1093 code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true), 1094 ev.union_type.struct_def, parser_.opts)); 1095 code_.SetValue("NAME", GetUnionElement(ev, false, true)); 1096 code_ += " case {{LABEL}}: {"; 1097 code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(value);"; 1098 if (ev.union_type.base_type == BASE_TYPE_STRUCT) { 1099 if (ev.union_type.struct_def->fixed) { 1100 code_ += " return _fbb.CreateStruct(*ptr).Union();"; 1101 } else { 1102 code_ += 1103 " return Create{{NAME}}(_fbb, ptr, _rehasher).Union();"; 1104 } 1105 } else if (ev.union_type.base_type == BASE_TYPE_STRING) { 1106 code_ += " return _fbb.CreateString(*ptr).Union();"; 1107 } else { 1108 assert(false); 1109 } 1110 code_ += " }"; 1111 } 1112 code_ += " default: return 0;"; 1113 code_ += " }"; 1114 code_ += "}"; 1115 code_ += ""; 1116 1117 // Union copy constructor 1118 code_ += "inline {{ENUM_NAME}}Union::{{ENUM_NAME}}Union(const " 1119 "{{ENUM_NAME}}Union &u) FLATBUFFERS_NOEXCEPT : type(u.type), " 1120 "value(nullptr) {"; 1121 code_ += " switch (type) {"; 1122 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1123 ++it) { 1124 const auto &ev = **it; 1125 if (!ev.value) { 1126 continue; 1127 } 1128 code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); 1129 code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true), 1130 ev.union_type.struct_def, parser_.opts)); 1131 code_ += " case {{LABEL}}: {"; 1132 bool copyable = true; 1133 if (ev.union_type.base_type == BASE_TYPE_STRUCT) { 1134 // Don't generate code to copy if table is not copyable. 1135 // TODO(wvo): make tables copyable instead. 1136 for (auto fit = ev.union_type.struct_def->fields.vec.begin(); 1137 fit != ev.union_type.struct_def->fields.vec.end(); ++fit) { 1138 const auto &field = **fit; 1139 if (!field.deprecated && field.value.type.struct_def) { 1140 copyable = false; 1141 break; 1142 } 1143 } 1144 } 1145 if (copyable) { 1146 code_ += " value = new {{TYPE}}(*reinterpret_cast<{{TYPE}} *>" 1147 "(u.value));"; 1148 } else { 1149 code_ += " assert(false); // {{TYPE}} not copyable."; 1150 } 1151 code_ += " break;"; 1152 code_ += " }"; 1153 } 1154 code_ += " default:"; 1155 code_ += " break;"; 1156 code_ += " }"; 1157 code_ += "}"; 1158 code_ += ""; 1159 1160 // Union Reset() function. 1161 code_.SetValue("NONE", 1162 GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"))); 1163 1164 code_ += "inline void {{ENUM_NAME}}Union::Reset() {"; 1165 code_ += " switch (type) {"; 1166 for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1167 ++it) { 1168 const auto &ev = **it; 1169 if (!ev.value) { 1170 continue; 1171 } 1172 code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); 1173 code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true), 1174 ev.union_type.struct_def, parser_.opts)); 1175 code_ += " case {{LABEL}}: {"; 1176 code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(value);"; 1177 code_ += " delete ptr;"; 1178 code_ += " break;"; 1179 code_ += " }"; 1180 } 1181 code_ += " default: break;"; 1182 code_ += " }"; 1183 code_ += " value = nullptr;"; 1184 code_ += " type = {{NONE}};"; 1185 code_ += "}"; 1186 code_ += ""; 1187 } 1188 } 1189 1190 // Generates a value with optionally a cast applied if the field has a 1191 // different underlying type from its interface type (currently only the 1192 // case for enums. "from" specify the direction, true meaning from the 1193 // underlying type to the interface type. 1194 std::string GenUnderlyingCast(const FieldDef &field, bool from, 1195 const std::string &val) { 1196 if (from && field.value.type.base_type == BASE_TYPE_BOOL) { 1197 return val + " != 0"; 1198 } else if ((field.value.type.enum_def && 1199 IsScalar(field.value.type.base_type)) || 1200 field.value.type.base_type == BASE_TYPE_BOOL) { 1201 return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" + 1202 val + ")"; 1203 } else { 1204 return val; 1205 } 1206 } 1207 1208 std::string GenFieldOffsetName(const FieldDef &field) { 1209 std::string uname = Name(field); 1210 std::transform(uname.begin(), uname.end(), uname.begin(), ToUpper); 1211 return "VT_" + uname; 1212 } 1213 1214 void GenFullyQualifiedNameGetter(const StructDef &struct_def, 1215 const std::string &name) { 1216 if (!parser_.opts.generate_name_strings) { 1217 return; 1218 } 1219 auto fullname = struct_def.defined_namespace->GetFullyQualifiedName(name); 1220 code_.SetValue("NAME", fullname); 1221 code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR"); 1222 code_ += " static {{CONSTEXPR}} const char *GetFullyQualifiedName() {"; 1223 code_ += " return \"{{NAME}}\";"; 1224 code_ += " }"; 1225 } 1226 1227 std::string GenDefaultConstant(const FieldDef &field) { 1228 return field.value.type.base_type == BASE_TYPE_FLOAT 1229 ? field.value.constant + "f" 1230 : field.value.constant; 1231 } 1232 1233 std::string GetDefaultScalarValue(const FieldDef &field) { 1234 if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) { 1235 auto ev = field.value.type.enum_def->ReverseLookup( 1236 static_cast<int>(StringToInt(field.value.constant.c_str())), false); 1237 if (ev) { 1238 return WrapInNameSpace( 1239 field.value.type.enum_def->defined_namespace, 1240 GetEnumValUse(*field.value.type.enum_def, *ev)); 1241 } else { 1242 return GenUnderlyingCast(field, true, field.value.constant); 1243 } 1244 } else if (field.value.type.base_type == BASE_TYPE_BOOL) { 1245 return field.value.constant == "0" ? "false" : "true"; 1246 } else { 1247 return GenDefaultConstant(field); 1248 } 1249 } 1250 1251 void GenParam(const FieldDef &field, bool direct, const char *prefix) { 1252 code_.SetValue("PRE", prefix); 1253 code_.SetValue("PARAM_NAME", Name(field)); 1254 if (direct && field.value.type.base_type == BASE_TYPE_STRING) { 1255 code_.SetValue("PARAM_TYPE", "const char *"); 1256 code_.SetValue("PARAM_VALUE", "nullptr"); 1257 } else if (direct && field.value.type.base_type == BASE_TYPE_VECTOR) { 1258 auto type = GenTypeWire(field.value.type.VectorType(), "", false); 1259 code_.SetValue("PARAM_TYPE", "const std::vector<" + type + "> *"); 1260 code_.SetValue("PARAM_VALUE", "nullptr"); 1261 } else { 1262 code_.SetValue("PARAM_TYPE", GenTypeWire(field.value.type, " ", true)); 1263 code_.SetValue("PARAM_VALUE", GetDefaultScalarValue(field)); 1264 } 1265 code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\"; 1266 } 1267 1268 // Generate a member, including a default value for scalars and raw pointers. 1269 void GenMember(const FieldDef &field) { 1270 if (!field.deprecated && // Deprecated fields won't be accessible. 1271 field.value.type.base_type != BASE_TYPE_UTYPE && 1272 (field.value.type.base_type != BASE_TYPE_VECTOR || 1273 field.value.type.element != BASE_TYPE_UTYPE)) { 1274 auto type = GenTypeNative(field.value.type, false, field); 1275 auto cpp_type = field.attributes.Lookup("cpp_type"); 1276 auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " "); 1277 code_.SetValue("FIELD_TYPE", full_type); 1278 code_.SetValue("FIELD_NAME", Name(field)); 1279 code_ += " {{FIELD_TYPE}}{{FIELD_NAME}};"; 1280 } 1281 } 1282 1283 // Generate the default constructor for this struct. Properly initialize all 1284 // scalar members with default values. 1285 void GenDefaultConstructor(const StructDef& struct_def) { 1286 std::string initializer_list; 1287 for (auto it = struct_def.fields.vec.begin(); 1288 it != struct_def.fields.vec.end(); ++it) { 1289 const auto &field = **it; 1290 if (!field.deprecated && // Deprecated fields won't be accessible. 1291 field.value.type.base_type != BASE_TYPE_UTYPE) { 1292 auto cpp_type = field.attributes.Lookup("cpp_type"); 1293 // Scalar types get parsed defaults, raw pointers get nullptrs. 1294 if (IsScalar(field.value.type.base_type)) { 1295 if (!initializer_list.empty()) { 1296 initializer_list += ",\n "; 1297 } 1298 initializer_list += Name(field); 1299 initializer_list += "(" + GetDefaultScalarValue(field) + ")"; 1300 } else if (field.value.type.base_type == BASE_TYPE_STRUCT) { 1301 if (IsStruct(field.value.type)) { 1302 auto native_default = field.attributes.Lookup("native_default"); 1303 if (native_default) { 1304 if (!initializer_list.empty()) { 1305 initializer_list += ",\n "; 1306 } 1307 initializer_list += 1308 Name(field) + "(" + native_default->constant + ")"; 1309 } 1310 } 1311 } else if (cpp_type) { 1312 if (!initializer_list.empty()) { 1313 initializer_list += ",\n "; 1314 } 1315 initializer_list += Name(field) + "(0)"; 1316 } 1317 } 1318 } 1319 if (!initializer_list.empty()) { 1320 initializer_list = "\n : " + initializer_list; 1321 } 1322 1323 code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, parser_.opts)); 1324 code_.SetValue("INIT_LIST", initializer_list); 1325 1326 code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {"; 1327 code_ += " }"; 1328 } 1329 1330 void GenOperatorNewDelete(const StructDef & struct_def) { 1331 if (auto native_custom_alloc = struct_def.attributes.Lookup("native_custom_alloc")) { 1332 code_ += " inline void *operator new (std::size_t count) {"; 1333 code_ += " return " + native_custom_alloc->constant + "<{{NATIVE_NAME}}>().allocate(count / sizeof({{NATIVE_NAME}}));"; 1334 code_ += " }"; 1335 code_ += " inline void operator delete (void *ptr) {"; 1336 code_ += " return " + native_custom_alloc->constant + "<{{NATIVE_NAME}}>().deallocate(static_cast<{{NATIVE_NAME}}*>(ptr),1);"; 1337 code_ += " }"; 1338 } 1339 } 1340 1341 void GenNativeTable(const StructDef &struct_def) { 1342 const auto native_name = NativeName(Name(struct_def), &struct_def, parser_.opts); 1343 code_.SetValue("STRUCT_NAME", Name(struct_def)); 1344 code_.SetValue("NATIVE_NAME", native_name); 1345 1346 // Generate a C++ object that can hold an unpacked version of this table. 1347 code_ += "struct {{NATIVE_NAME}} : public flatbuffers::NativeTable {"; 1348 code_ += " typedef {{STRUCT_NAME}} TableType;"; 1349 GenFullyQualifiedNameGetter(struct_def, native_name); 1350 for (auto it = struct_def.fields.vec.begin(); 1351 it != struct_def.fields.vec.end(); ++it) { 1352 GenMember(**it); 1353 } 1354 GenOperatorNewDelete(struct_def); 1355 GenDefaultConstructor(struct_def); 1356 code_ += "};"; 1357 code_ += ""; 1358 } 1359 1360 // Generate the code to call the appropriate Verify function(s) for a field. 1361 void GenVerifyCall(const FieldDef &field, const char* prefix) { 1362 code_.SetValue("PRE", prefix); 1363 code_.SetValue("NAME", Name(field)); 1364 code_.SetValue("REQUIRED", field.required ? "Required" : ""); 1365 code_.SetValue("SIZE", GenTypeSize(field.value.type)); 1366 code_.SetValue("OFFSET", GenFieldOffsetName(field)); 1367 if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) { 1368 code_ += 1369 "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\"; 1370 } else { 1371 code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\"; 1372 } 1373 1374 switch (field.value.type.base_type) { 1375 case BASE_TYPE_UNION: { 1376 code_.SetValue("ENUM_NAME", field.value.type.enum_def->name); 1377 code_.SetValue("SUFFIX", UnionTypeFieldSuffix()); 1378 code_ += "{{PRE}}Verify{{ENUM_NAME}}(verifier, {{NAME}}(), " 1379 "{{NAME}}{{SUFFIX}}())\\"; 1380 break; 1381 } 1382 case BASE_TYPE_STRUCT: { 1383 if (!field.value.type.struct_def->fixed) { 1384 code_ += "{{PRE}}verifier.VerifyTable({{NAME}}())\\"; 1385 } 1386 break; 1387 } 1388 case BASE_TYPE_STRING: { 1389 code_ += "{{PRE}}verifier.Verify({{NAME}}())\\"; 1390 break; 1391 } 1392 case BASE_TYPE_VECTOR: { 1393 code_ += "{{PRE}}verifier.Verify({{NAME}}())\\"; 1394 1395 switch (field.value.type.element) { 1396 case BASE_TYPE_STRING: { 1397 code_ += "{{PRE}}verifier.VerifyVectorOfStrings({{NAME}}())\\"; 1398 break; 1399 } 1400 case BASE_TYPE_STRUCT: { 1401 if (!field.value.type.struct_def->fixed) { 1402 code_ += "{{PRE}}verifier.VerifyVectorOfTables({{NAME}}())\\"; 1403 } 1404 break; 1405 } 1406 case BASE_TYPE_UNION: { 1407 code_.SetValue("ENUM_NAME", field.value.type.enum_def->name); 1408 code_ += "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), {{NAME}}_type())\\"; 1409 break; 1410 } 1411 default: 1412 break; 1413 } 1414 break; 1415 } 1416 default: { 1417 break; 1418 } 1419 } 1420 } 1421 1422 // Generate an accessor struct, builder structs & function for a table. 1423 void GenTable(const StructDef &struct_def) { 1424 if (parser_.opts.generate_object_based_api) { 1425 GenNativeTable(struct_def); 1426 } 1427 1428 // Generate an accessor struct, with methods of the form: 1429 // type name() const { return GetField<type>(offset, defaultval); } 1430 GenComment(struct_def.doc_comment); 1431 1432 code_.SetValue("STRUCT_NAME", Name(struct_def)); 1433 code_ += "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS" 1434 " : private flatbuffers::Table {"; 1435 if (parser_.opts.generate_object_based_api) { 1436 code_ += " typedef {{NATIVE_NAME}} NativeTableType;"; 1437 } 1438 1439 GenFullyQualifiedNameGetter(struct_def, Name(struct_def)); 1440 1441 // Generate field id constants. 1442 if (struct_def.fields.vec.size() > 0) { 1443 // We need to add a trailing comma to all elements except the last one as 1444 // older versions of gcc complain about this. 1445 code_.SetValue("SEP", ""); 1446 code_ += " enum {"; 1447 for (auto it = struct_def.fields.vec.begin(); 1448 it != struct_def.fields.vec.end(); ++it) { 1449 const auto &field = **it; 1450 if (field.deprecated) { 1451 // Deprecated fields won't be accessible. 1452 continue; 1453 } 1454 1455 code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field)); 1456 code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset)); 1457 code_ += "{{SEP}} {{OFFSET_NAME}} = {{OFFSET_VALUE}}\\"; 1458 code_.SetValue("SEP", ",\n"); 1459 } 1460 code_ += ""; 1461 code_ += " };"; 1462 } 1463 1464 // Generate the accessors. 1465 for (auto it = struct_def.fields.vec.begin(); 1466 it != struct_def.fields.vec.end(); ++it) { 1467 const auto &field = **it; 1468 if (field.deprecated) { 1469 // Deprecated fields won't be accessible. 1470 continue; 1471 } 1472 1473 const bool is_struct = IsStruct(field.value.type); 1474 const bool is_scalar = IsScalar(field.value.type.base_type); 1475 code_.SetValue("FIELD_NAME", Name(field)); 1476 1477 // Call a different accessor for pointers, that indirects. 1478 std::string accessor = ""; 1479 if (is_scalar) { 1480 accessor = "GetField<"; 1481 } else if (is_struct) { 1482 accessor = "GetStruct<"; 1483 } else { 1484 accessor = "GetPointer<"; 1485 } 1486 auto offset_str = GenFieldOffsetName(field); 1487 auto offset_type = 1488 GenTypeGet(field.value.type, "", "const ", " *", false); 1489 1490 auto call = accessor + offset_type + ">(" + offset_str; 1491 // Default value as second arg for non-pointer types. 1492 if (is_scalar) { 1493 call += ", " + GenDefaultConstant(field); 1494 } 1495 call += ")"; 1496 1497 std::string afterptr = " *" + NullableExtension(); 1498 GenComment(field.doc_comment, " "); 1499 code_.SetValue("FIELD_TYPE", 1500 GenTypeGet(field.value.type, " ", "const ", afterptr.c_str(), true)); 1501 code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call)); 1502 code_.SetValue("NULLABLE_EXT", NullableExtension()); 1503 1504 code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {"; 1505 code_ += " return {{FIELD_VALUE}};"; 1506 code_ += " }"; 1507 1508 if (field.value.type.base_type == BASE_TYPE_UNION) { 1509 auto u = field.value.type.enum_def; 1510 1511 code_ += " template<typename T> " 1512 "const T *{{NULLABLE_EXT}}{{FIELD_NAME}}_as() const;"; 1513 1514 for (auto u_it = u->vals.vec.begin(); 1515 u_it != u->vals.vec.end(); ++u_it) { 1516 auto &ev = **u_it; 1517 if (ev.union_type.base_type == BASE_TYPE_NONE) { 1518 continue; 1519 } 1520 auto full_struct_name = GetUnionElement(ev, true, true); 1521 1522 // @TODO: Mby make this decisions more universal? How? 1523 code_.SetValue("U_GET_TYPE", Name(field) + UnionTypeFieldSuffix()); 1524 code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace( 1525 u->defined_namespace, GetEnumValUse(*u, ev))); 1526 code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); 1527 code_.SetValue("U_FIELD_NAME", 1528 Name(field) + "_as_" + Name(ev)); 1529 code_.SetValue("U_NULLABLE", NullableExtension()); 1530 1531 // `const Type *union_name_asType() const` accessor. 1532 code_ += " {{U_FIELD_TYPE}}{{U_NULLABLE}}{{U_FIELD_NAME}}() const {"; 1533 code_ += " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? " 1534 "static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) " 1535 ": nullptr;"; 1536 code_ += " }"; 1537 } 1538 } 1539 1540 if (parser_.opts.mutable_buffer) { 1541 if (is_scalar) { 1542 const auto type = GenTypeWire(field.value.type, "", false); 1543 code_.SetValue("SET_FN", "SetField<" + type + ">"); 1544 code_.SetValue("OFFSET_NAME", offset_str); 1545 code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true)); 1546 code_.SetValue("FIELD_VALUE", 1547 GenUnderlyingCast(field, false, "_" + Name(field))); 1548 code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field)); 1549 1550 code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} " 1551 "_{{FIELD_NAME}}) {"; 1552 code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, {{DEFAULT_VALUE}});"; 1553 code_ += " }"; 1554 } else { 1555 auto postptr = " *" + NullableExtension(); 1556 auto type = GenTypeGet(field.value.type, " ", "", postptr.c_str(), true); 1557 auto underlying = accessor + type + ">(" + offset_str + ")"; 1558 code_.SetValue("FIELD_TYPE", type); 1559 code_.SetValue("FIELD_VALUE", 1560 GenUnderlyingCast(field, true, underlying)); 1561 1562 code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {"; 1563 code_ += " return {{FIELD_VALUE}};"; 1564 code_ += " }"; 1565 } 1566 } 1567 1568 auto nested = field.attributes.Lookup("nested_flatbuffer"); 1569 if (nested) { 1570 std::string qualified_name = 1571 parser_.current_namespace_->GetFullyQualifiedName( 1572 nested->constant); 1573 auto nested_root = parser_.LookupStruct(qualified_name); 1574 assert(nested_root); // Guaranteed to exist by parser. 1575 (void)nested_root; 1576 code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name)); 1577 1578 code_ += " const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {"; 1579 code_ += " auto data = {{FIELD_NAME}}()->Data();"; 1580 code_ += " return flatbuffers::GetRoot<{{CPP_NAME}}>(data);"; 1581 code_ += " }"; 1582 } 1583 1584 if (field.flexbuffer) { 1585 code_ += " flexbuffers::Reference {{FIELD_NAME}}_flexbuffer_root()" 1586 " const {"; 1587 code_ += " auto v = {{FIELD_NAME}}();"; 1588 code_ += " return flexbuffers::GetRoot(v->Data(), v->size());"; 1589 code_ += " }"; 1590 } 1591 1592 // Generate a comparison function for this field if it is a key. 1593 if (field.key) { 1594 const bool is_string = (field.value.type.base_type == BASE_TYPE_STRING); 1595 1596 code_ += " bool KeyCompareLessThan(const {{STRUCT_NAME}} *o) const {"; 1597 if (is_string) { 1598 code_ += " return *{{FIELD_NAME}}() < *o->{{FIELD_NAME}}();"; 1599 } else { 1600 code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();"; 1601 } 1602 code_ += " }"; 1603 1604 if (is_string) { 1605 code_ += " int KeyCompareWithValue(const char *val) const {"; 1606 code_ += " return strcmp({{FIELD_NAME}}()->c_str(), val);"; 1607 code_ += " }"; 1608 } else { 1609 auto type = GenTypeBasic(field.value.type, false); 1610 if (parser_.opts.scoped_enums && field.value.type.enum_def && 1611 IsScalar(field.value.type.base_type)) { 1612 type = GenTypeGet(field.value.type, " ", "const ", " *", true); 1613 } 1614 1615 code_.SetValue("KEY_TYPE", type); 1616 code_ += " int KeyCompareWithValue({{KEY_TYPE}} val) const {"; 1617 code_ += " const auto key = {{FIELD_NAME}}();"; 1618 code_ += " if (key < val) {"; 1619 code_ += " return -1;"; 1620 code_ += " } else if (key > val) {"; 1621 code_ += " return 1;"; 1622 code_ += " } else {"; 1623 code_ += " return 0;"; 1624 code_ += " }"; 1625 code_ += " }"; 1626 } 1627 } 1628 } 1629 1630 // Generate a verifier function that can check a buffer from an untrusted 1631 // source will never cause reads outside the buffer. 1632 code_ += " bool Verify(flatbuffers::Verifier &verifier) const {"; 1633 code_ += " return VerifyTableStart(verifier)\\"; 1634 for (auto it = struct_def.fields.vec.begin(); 1635 it != struct_def.fields.vec.end(); ++it) { 1636 const auto &field = **it; 1637 if (field.deprecated) { 1638 continue; 1639 } 1640 GenVerifyCall(field, " &&\n "); 1641 } 1642 1643 code_ += " &&\n verifier.EndTable();"; 1644 code_ += " }"; 1645 1646 if (parser_.opts.generate_object_based_api) { 1647 // Generate the UnPack() pre declaration. 1648 code_ += " " + TableUnPackSignature(struct_def, true, parser_.opts) + ";"; 1649 code_ += " " + TableUnPackToSignature(struct_def, true, parser_.opts) + ";"; 1650 code_ += " " + TablePackSignature(struct_def, true, parser_.opts) + ";"; 1651 } 1652 1653 code_ += "};"; // End of table. 1654 code_ += ""; 1655 1656 // Explicit specializations for union accessors 1657 for (auto it = struct_def.fields.vec.begin(); 1658 it != struct_def.fields.vec.end(); ++it) { 1659 const auto &field = **it; 1660 if (field.deprecated || 1661 field.value.type.base_type != BASE_TYPE_UNION) { 1662 continue; 1663 } 1664 1665 auto u = field.value.type.enum_def; 1666 if (u->uses_type_aliases) continue; 1667 1668 code_.SetValue("FIELD_NAME", Name(field)); 1669 1670 for (auto u_it = u->vals.vec.begin(); 1671 u_it != u->vals.vec.end(); ++u_it) { 1672 auto &ev = **u_it; 1673 if (ev.union_type.base_type == BASE_TYPE_NONE) { 1674 continue; 1675 } 1676 1677 auto full_struct_name = GetUnionElement(ev, true, true); 1678 1679 code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace( 1680 u->defined_namespace, GetEnumValUse(*u, ev))); 1681 code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); 1682 code_.SetValue("U_ELEMENT_NAME", full_struct_name); 1683 code_.SetValue("U_FIELD_NAME", 1684 Name(field) + "_as_" + Name(ev)); 1685 1686 // `template<> const T *union_name_as<T>() const` accessor. 1687 code_ += "template<> " 1688 "inline {{U_FIELD_TYPE}}{{STRUCT_NAME}}::{{FIELD_NAME}}_as" 1689 "<{{U_ELEMENT_NAME}}>() const {"; 1690 code_ += " return {{U_FIELD_NAME}}();"; 1691 code_ += "}"; 1692 code_ += ""; 1693 } 1694 } 1695 1696 GenBuilders(struct_def); 1697 1698 if (parser_.opts.generate_object_based_api) { 1699 // Generate a pre-declaration for a CreateX method that works with an 1700 // unpacked C++ object. 1701 code_ += TableCreateSignature(struct_def, true, parser_.opts) + ";"; 1702 code_ += ""; 1703 } 1704 } 1705 1706 void GenBuilders(const StructDef &struct_def) { 1707 code_.SetValue("STRUCT_NAME", Name(struct_def)); 1708 1709 // Generate a builder struct: 1710 code_ += "struct {{STRUCT_NAME}}Builder {"; 1711 code_ += " flatbuffers::FlatBufferBuilder &fbb_;"; 1712 code_ += " flatbuffers::uoffset_t start_;"; 1713 1714 bool has_string_or_vector_fields = false; 1715 for (auto it = struct_def.fields.vec.begin(); 1716 it != struct_def.fields.vec.end(); ++it) { 1717 const auto &field = **it; 1718 if (!field.deprecated) { 1719 const bool is_scalar = IsScalar(field.value.type.base_type); 1720 const bool is_string = field.value.type.base_type == BASE_TYPE_STRING; 1721 const bool is_vector = field.value.type.base_type == BASE_TYPE_VECTOR; 1722 if (is_string || is_vector) { 1723 has_string_or_vector_fields = true; 1724 } 1725 1726 std::string offset = GenFieldOffsetName(field); 1727 std::string name = GenUnderlyingCast(field, false, Name(field)); 1728 std::string value = is_scalar ? GenDefaultConstant(field) : ""; 1729 1730 // Generate accessor functions of the form: 1731 // void add_name(type name) { 1732 // fbb_.AddElement<type>(offset, name, default); 1733 // } 1734 code_.SetValue("FIELD_NAME", Name(field)); 1735 code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true)); 1736 code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset); 1737 code_.SetValue("ADD_NAME", name); 1738 code_.SetValue("ADD_VALUE", value); 1739 if (is_scalar) { 1740 const auto type = GenTypeWire(field.value.type, "", false); 1741 code_.SetValue("ADD_FN", "AddElement<" + type + ">"); 1742 } else if (IsStruct(field.value.type)) { 1743 code_.SetValue("ADD_FN", "AddStruct"); 1744 } else { 1745 code_.SetValue("ADD_FN", "AddOffset"); 1746 } 1747 1748 code_ += " void add_{{FIELD_NAME}}({{FIELD_TYPE}}{{FIELD_NAME}}) {"; 1749 code_ += " fbb_.{{ADD_FN}}(\\"; 1750 if (is_scalar) { 1751 code_ += "{{ADD_OFFSET}}, {{ADD_NAME}}, {{ADD_VALUE}});"; 1752 } else { 1753 code_ += "{{ADD_OFFSET}}, {{ADD_NAME}});"; 1754 } 1755 code_ += " }"; 1756 } 1757 } 1758 1759 // Builder constructor 1760 code_ += " explicit {{STRUCT_NAME}}Builder(flatbuffers::FlatBufferBuilder &_fbb)"; 1761 code_ += " : fbb_(_fbb) {"; 1762 code_ += " start_ = fbb_.StartTable();"; 1763 code_ += " }"; 1764 1765 // Assignment operator; 1766 code_ += " {{STRUCT_NAME}}Builder &operator=" 1767 "(const {{STRUCT_NAME}}Builder &);"; 1768 1769 // Finish() function. 1770 code_ += " flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {"; 1771 code_ += " const auto end = fbb_.EndTable(start_);"; 1772 code_ += " auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);"; 1773 1774 for (auto it = struct_def.fields.vec.begin(); 1775 it != struct_def.fields.vec.end(); ++it) { 1776 const auto &field = **it; 1777 if (!field.deprecated && field.required) { 1778 code_.SetValue("FIELD_NAME", Name(field)); 1779 code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field)); 1780 code_ += " fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});"; 1781 } 1782 } 1783 code_ += " return o;"; 1784 code_ += " }"; 1785 code_ += "};"; 1786 code_ += ""; 1787 1788 // Generate a convenient CreateX function that uses the above builder 1789 // to create a table in one go. 1790 code_ += "inline flatbuffers::Offset<{{STRUCT_NAME}}> " 1791 "Create{{STRUCT_NAME}}("; 1792 code_ += " flatbuffers::FlatBufferBuilder &_fbb\\"; 1793 for (auto it = struct_def.fields.vec.begin(); 1794 it != struct_def.fields.vec.end(); ++it) { 1795 const auto &field = **it; 1796 if (!field.deprecated) { 1797 GenParam(field, false, ",\n "); 1798 } 1799 } 1800 code_ += ") {"; 1801 1802 code_ += " {{STRUCT_NAME}}Builder builder_(_fbb);"; 1803 for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 1804 size; size /= 2) { 1805 for (auto it = struct_def.fields.vec.rbegin(); 1806 it != struct_def.fields.vec.rend(); ++it) { 1807 const auto &field = **it; 1808 if (!field.deprecated && (!struct_def.sortbysize || 1809 size == SizeOf(field.value.type.base_type))) { 1810 code_.SetValue("FIELD_NAME", Name(field)); 1811 code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});"; 1812 } 1813 } 1814 } 1815 code_ += " return builder_.Finish();"; 1816 code_ += "}"; 1817 code_ += ""; 1818 1819 // Generate a CreateXDirect function with vector types as parameters 1820 if (has_string_or_vector_fields) { 1821 code_ += "inline flatbuffers::Offset<{{STRUCT_NAME}}> " 1822 "Create{{STRUCT_NAME}}Direct("; 1823 code_ += " flatbuffers::FlatBufferBuilder &_fbb\\"; 1824 for (auto it = struct_def.fields.vec.begin(); 1825 it != struct_def.fields.vec.end(); ++it) { 1826 const auto &field = **it; 1827 if (!field.deprecated) { 1828 GenParam(field, true, ",\n "); 1829 } 1830 } 1831 1832 // Need to call "Create" with the struct namespace. 1833 const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create"); 1834 code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name)); 1835 1836 code_ += ") {"; 1837 code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}("; 1838 code_ += " _fbb\\"; 1839 for (auto it = struct_def.fields.vec.begin(); 1840 it != struct_def.fields.vec.end(); ++it) { 1841 const auto &field = **it; 1842 if (!field.deprecated) { 1843 code_.SetValue("FIELD_NAME", Name(field)); 1844 1845 if (field.value.type.base_type == BASE_TYPE_STRING) { 1846 code_ += ",\n {{FIELD_NAME}} ? " 1847 "_fbb.CreateString({{FIELD_NAME}}) : 0\\"; 1848 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) { 1849 auto type = GenTypeWire(field.value.type.VectorType(), "", false); 1850 code_ += ",\n {{FIELD_NAME}} ? " 1851 "_fbb.CreateVector<" + type + ">(*{{FIELD_NAME}}) : 0\\"; 1852 } else { 1853 code_ += ",\n {{FIELD_NAME}}\\"; 1854 } 1855 } 1856 } 1857 code_ += ");"; 1858 code_ += "}"; 1859 code_ += ""; 1860 } 1861 } 1862 1863 std::string GenUnionUnpackVal(const FieldDef &afield, 1864 const char *vec_elem_access, 1865 const char *vec_type_access) { 1866 return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" + 1867 vec_elem_access + ", " + Name(afield) + UnionTypeFieldSuffix() + 1868 "()" + vec_type_access + ", _resolver)"; 1869 } 1870 1871 std::string GenUnpackVal(const Type &type, const std::string &val, 1872 bool invector, const FieldDef &afield) { 1873 switch (type.base_type) { 1874 case BASE_TYPE_STRING: { 1875 return val + "->str()"; 1876 } 1877 case BASE_TYPE_STRUCT: { 1878 const auto name = WrapInNameSpace(*type.struct_def); 1879 if (IsStruct(type)) { 1880 auto native_type = type.struct_def->attributes.Lookup("native_type"); 1881 if (native_type) { 1882 return "flatbuffers::UnPack(*" + val + ")"; 1883 } else if (invector || afield.native_inline) { 1884 return "*" + val; 1885 } else { 1886 const auto ptype = GenTypeNativePtr(name, &afield, true); 1887 return ptype + "(new " + name + "(*" + val + "))"; 1888 } 1889 } else { 1890 const auto ptype = GenTypeNativePtr(NativeName(name, type.struct_def, parser_.opts), 1891 &afield, true); 1892 return ptype + "(" + val + "->UnPack(_resolver))"; 1893 } 1894 } 1895 case BASE_TYPE_UNION: { 1896 return GenUnionUnpackVal(afield, 1897 invector ? "->Get(_i)" : "", 1898 invector ? ("->GetEnum<" + 1899 type.enum_def->name + 1900 ">(_i)").c_str() : ""); 1901 } 1902 default: { 1903 return val; 1904 break; 1905 } 1906 } 1907 }; 1908 1909 std::string GenUnpackFieldStatement(const FieldDef &field, 1910 const FieldDef *union_field) { 1911 std::string code; 1912 switch (field.value.type.base_type) { 1913 case BASE_TYPE_VECTOR: { 1914 std::string indexing; 1915 if (field.value.type.enum_def) { 1916 indexing += "(" + field.value.type.enum_def->name + ")"; 1917 } 1918 indexing += "_e->Get(_i)"; 1919 if (field.value.type.element == BASE_TYPE_BOOL) { 1920 indexing += " != 0"; 1921 } 1922 1923 // Generate code that pushes data from _e to _o in the form: 1924 // for (uoffset_t i = 0; i < _e->size(); ++i) { 1925 // _o->field.push_back(_e->Get(_i)); 1926 // } 1927 auto name = Name(field); 1928 if (field.value.type.element == BASE_TYPE_UTYPE) { 1929 name = StripUnionType(Name(field)); 1930 } 1931 auto access = field.value.type.element == BASE_TYPE_UTYPE 1932 ? ".type" 1933 : (field.value.type.element == BASE_TYPE_UNION 1934 ? ".value" 1935 : ""); 1936 code += "{ _o->" + name + ".resize(_e->size()); "; 1937 code += "for (flatbuffers::uoffset_t _i = 0;"; 1938 code += " _i < _e->size(); _i++) { "; 1939 code += "_o->" + name + "[_i]" + access + " = "; 1940 code += GenUnpackVal(field.value.type.VectorType(), 1941 indexing, true, field); 1942 code += "; } }"; 1943 break; 1944 } 1945 case BASE_TYPE_UTYPE: { 1946 assert(union_field->value.type.base_type == BASE_TYPE_UNION); 1947 // Generate code that sets the union type, of the form: 1948 // _o->field.type = _e; 1949 code += "_o->" + union_field->name + ".type = _e;"; 1950 break; 1951 } 1952 case BASE_TYPE_UNION: { 1953 // Generate code that sets the union value, of the form: 1954 // _o->field.value = Union::Unpack(_e, field_type(), resolver); 1955 code += "_o->" + Name(field) + ".value = "; 1956 code += GenUnionUnpackVal(field, "", ""); 1957 code += ";"; 1958 break; 1959 } 1960 default: { 1961 auto cpp_type = field.attributes.Lookup("cpp_type"); 1962 if (cpp_type) { 1963 // Generate code that resolves the cpp pointer type, of the form: 1964 // if (resolver) 1965 // (*resolver)(&_o->field, (hash_value_t)(_e)); 1966 // else 1967 // _o->field = nullptr; 1968 code += "if (_resolver) "; 1969 code += "(*_resolver)"; 1970 code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), "; 1971 code += "static_cast<flatbuffers::hash_value_t>(_e));"; 1972 code += " else "; 1973 code += "_o->" + Name(field) + " = nullptr;"; 1974 } else { 1975 // Generate code for assigning the value, of the form: 1976 // _o->field = value; 1977 code += "_o->" + Name(field) + " = "; 1978 code += GenUnpackVal(field.value.type, "_e", false, field) + ";"; 1979 } 1980 break; 1981 } 1982 } 1983 return code; 1984 } 1985 1986 std::string GenCreateParam(const FieldDef &field) { 1987 std::string value = "_o->"; 1988 if (field.value.type.base_type == BASE_TYPE_UTYPE) { 1989 value += StripUnionType(Name(field)); 1990 value += ".type"; 1991 } else { 1992 value += Name(field); 1993 } 1994 if (field.attributes.Lookup("cpp_type")) { 1995 auto type = GenTypeBasic(field.value.type, false); 1996 value = "_rehasher ? " 1997 "static_cast<" + type + ">((*_rehasher)(" + value + ")) : 0"; 1998 } 1999 2000 std::string code; 2001 switch (field.value.type.base_type) { 2002 // String fields are of the form: 2003 // _fbb.CreateString(_o->field) 2004 case BASE_TYPE_STRING: { 2005 code += "_fbb.CreateString(" + value + ")"; 2006 2007 // For optional fields, check to see if there actually is any data 2008 // in _o->field before attempting to access it. 2009 if (!field.required) { 2010 code = value + ".empty() ? 0 : " + code; 2011 } 2012 break; 2013 } 2014 // Vector fields come in several flavours, of the forms: 2015 // _fbb.CreateVector(_o->field); 2016 // _fbb.CreateVector((const utype*)_o->field.data(), _o->field.size()); 2017 // _fbb.CreateVectorOfStrings(_o->field) 2018 // _fbb.CreateVectorOfStructs(_o->field) 2019 // _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) { 2020 // return CreateT(_fbb, _o->Get(i), rehasher); 2021 // }); 2022 case BASE_TYPE_VECTOR: { 2023 auto vector_type = field.value.type.VectorType(); 2024 switch (vector_type.base_type) { 2025 case BASE_TYPE_STRING: { 2026 code += "_fbb.CreateVectorOfStrings(" + value + ")"; 2027 break; 2028 } 2029 case BASE_TYPE_STRUCT: { 2030 if (IsStruct(vector_type)) { 2031 auto native_type = 2032 field.value.type.struct_def->attributes.Lookup("native_type"); 2033 if (native_type) { 2034 code += "_fbb.CreateVectorOfNativeStructs<"; 2035 code += WrapInNameSpace(*vector_type.struct_def) + ">"; 2036 } else { 2037 code += "_fbb.CreateVectorOfStructs"; 2038 } 2039 code += "(" + value + ")"; 2040 } else { 2041 code += "_fbb.CreateVector<flatbuffers::Offset<"; 2042 code += WrapInNameSpace(*vector_type.struct_def) + ">> "; 2043 code += "(" + value + ".size(), "; 2044 code += "[](size_t i, _VectorArgs *__va) { "; 2045 code += "return Create" + vector_type.struct_def->name; 2046 code += "(*__va->__fbb, __va->_" + value + "[i]" + 2047 GenPtrGet(field) + ", "; 2048 code += "__va->__rehasher); }, &_va )"; 2049 } 2050 break; 2051 } 2052 case BASE_TYPE_BOOL: { 2053 code += "_fbb.CreateVector(" + value + ")"; 2054 break; 2055 } 2056 case BASE_TYPE_UNION: { 2057 code += "_fbb.CreateVector<flatbuffers::" 2058 "Offset<void>>(" + value + 2059 ".size(), [](size_t i, _VectorArgs *__va) { " 2060 "return __va->_" + value + 2061 "[i].Pack(*__va->__fbb, __va->__rehasher); }, &_va)"; 2062 break; 2063 } 2064 case BASE_TYPE_UTYPE: { 2065 value = StripUnionType(value); 2066 code += "_fbb.CreateVector<uint8_t>(" + value + 2067 ".size(), [](size_t i, _VectorArgs *__va) { " 2068 "return static_cast<uint8_t>(__va->_" + value + 2069 "[i].type); }, &_va)"; 2070 break; 2071 } 2072 default: { 2073 if (field.value.type.enum_def) { 2074 // For enumerations, we need to get access to the array data for 2075 // the underlying storage type (eg. uint8_t). 2076 const auto basetype = GenTypeBasic( 2077 field.value.type.enum_def->underlying_type, false); 2078 code += "_fbb.CreateVector((const " + basetype + "*)" + value + 2079 ".data(), " + value + ".size())"; 2080 } else { 2081 code += "_fbb.CreateVector(" + value + ")"; 2082 } 2083 break; 2084 } 2085 } 2086 2087 // For optional fields, check to see if there actually is any data 2088 // in _o->field before attempting to access it. 2089 if (!field.required) { 2090 code = value + ".size() ? " + code + " : 0"; 2091 } 2092 break; 2093 } 2094 case BASE_TYPE_UNION: { 2095 // _o->field.Pack(_fbb); 2096 code += value + ".Pack(_fbb)"; 2097 break; 2098 } 2099 case BASE_TYPE_STRUCT: { 2100 if (IsStruct(field.value.type)) { 2101 auto native_type = 2102 field.value.type.struct_def->attributes.Lookup("native_type"); 2103 if (native_type) { 2104 code += "flatbuffers::Pack(" + value + ")"; 2105 } else if (field.native_inline) { 2106 code += "&" + value; 2107 } else { 2108 code += value + " ? " + value + GenPtrGet(field) + " : 0"; 2109 } 2110 } else { 2111 // _o->field ? CreateT(_fbb, _o->field.get(), _rehasher); 2112 const auto type = field.value.type.struct_def->name; 2113 code += value + " ? Create" + type; 2114 code += "(_fbb, " + value + GenPtrGet(field) + ", _rehasher)"; 2115 code += " : 0"; 2116 } 2117 break; 2118 } 2119 default: { 2120 code += value; 2121 break; 2122 } 2123 } 2124 return code; 2125 } 2126 2127 // Generate code for tables that needs to come after the regular definition. 2128 void GenTablePost(const StructDef &struct_def) { 2129 code_.SetValue("STRUCT_NAME", Name(struct_def)); 2130 code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, parser_.opts)); 2131 2132 if (parser_.opts.generate_object_based_api) { 2133 // Generate the X::UnPack() method. 2134 code_ += "inline " + TableUnPackSignature(struct_def, false, parser_.opts) + " {"; 2135 code_ += " auto _o = new {{NATIVE_NAME}}();"; 2136 code_ += " UnPackTo(_o, _resolver);"; 2137 code_ += " return _o;"; 2138 code_ += "}"; 2139 code_ += ""; 2140 2141 code_ += "inline " + TableUnPackToSignature(struct_def, false, parser_.opts) + " {"; 2142 code_ += " (void)_o;"; 2143 code_ += " (void)_resolver;"; 2144 2145 for (auto it = struct_def.fields.vec.begin(); 2146 it != struct_def.fields.vec.end(); ++it) { 2147 const auto &field = **it; 2148 if (field.deprecated) { 2149 continue; 2150 } 2151 2152 // Assign a value from |this| to |_o|. Values from |this| are stored 2153 // in a variable |_e| by calling this->field_type(). The value is then 2154 // assigned to |_o| using the GenUnpackFieldStatement. 2155 const bool is_union = field.value.type.base_type == BASE_TYPE_UTYPE; 2156 const auto statement = 2157 GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr); 2158 2159 code_.SetValue("FIELD_NAME", Name(field)); 2160 auto prefix = " { auto _e = {{FIELD_NAME}}(); "; 2161 auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) "; 2162 auto postfix = " };"; 2163 code_ += std::string(prefix) + check + statement + postfix; 2164 } 2165 code_ += "}"; 2166 code_ += ""; 2167 2168 // Generate the X::Pack member function that simply calls the global 2169 // CreateX function. 2170 code_ += "inline " + TablePackSignature(struct_def, false, parser_.opts) + " {"; 2171 code_ += " return Create{{STRUCT_NAME}}(_fbb, _o, _rehasher);"; 2172 code_ += "}"; 2173 code_ += ""; 2174 2175 // Generate a CreateX method that works with an unpacked C++ object. 2176 code_ += "inline " + TableCreateSignature(struct_def, false, parser_.opts) + " {"; 2177 code_ += " (void)_rehasher;"; 2178 code_ += " (void)_o;"; 2179 2180 code_ += 2181 " struct _VectorArgs " 2182 "{ flatbuffers::FlatBufferBuilder *__fbb; " 2183 "const " + 2184 NativeName(Name(struct_def), &struct_def, parser_.opts) + 2185 "* __o; " 2186 "const flatbuffers::rehasher_function_t *__rehasher; } _va = { " 2187 "&_fbb, _o, _rehasher}; (void)_va;"; 2188 2189 for (auto it = struct_def.fields.vec.begin(); 2190 it != struct_def.fields.vec.end(); ++it) { 2191 auto &field = **it; 2192 if (field.deprecated) { 2193 continue; 2194 } 2195 code_ += " auto _" + Name(field) + " = " + GenCreateParam(field) + ";"; 2196 } 2197 // Need to call "Create" with the struct namespace. 2198 const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create"); 2199 code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name)); 2200 2201 code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}("; 2202 code_ += " _fbb\\"; 2203 for (auto it = struct_def.fields.vec.begin(); 2204 it != struct_def.fields.vec.end(); ++it) { 2205 auto &field = **it; 2206 if (field.deprecated) { 2207 continue; 2208 } 2209 2210 bool pass_by_address = false; 2211 if (field.value.type.base_type == BASE_TYPE_STRUCT) { 2212 if (IsStruct(field.value.type)) { 2213 auto native_type = 2214 field.value.type.struct_def->attributes.Lookup("native_type"); 2215 if (native_type) { 2216 pass_by_address = true; 2217 } 2218 } 2219 } 2220 2221 // Call the CreateX function using values from |_o|. 2222 if (pass_by_address) { 2223 code_ += ",\n &_" + Name(field) + "\\"; 2224 } else { 2225 code_ += ",\n _" + Name(field) + "\\"; 2226 } 2227 } 2228 code_ += ");"; 2229 code_ += "}"; 2230 code_ += ""; 2231 } 2232 } 2233 2234 static void GenPadding( 2235 const FieldDef &field, std::string *code_ptr, int *id, 2236 const std::function<void(int bits, std::string *code_ptr, int *id)> &f) { 2237 if (field.padding) { 2238 for (int i = 0; i < 4; i++) { 2239 if (static_cast<int>(field.padding) & (1 << i)) { 2240 f((1 << i) * 8, code_ptr, id); 2241 } 2242 } 2243 assert(!(field.padding & ~0xF)); 2244 } 2245 } 2246 2247 static void PaddingDefinition(int bits, std::string *code_ptr, int *id) { 2248 *code_ptr += " int" + NumToString(bits) + "_t padding" + 2249 NumToString((*id)++) + "__;"; 2250 } 2251 2252 static void PaddingInitializer(int bits, std::string *code_ptr, int *id) { 2253 (void)bits; 2254 *code_ptr += ",\n padding" + NumToString((*id)++) + "__(0)"; 2255 } 2256 2257 static void PaddingNoop(int bits, std::string *code_ptr, int *id) { 2258 (void)bits; 2259 *code_ptr += " (void)padding" + NumToString((*id)++) + "__;"; 2260 } 2261 2262 // Generate an accessor struct with constructor for a flatbuffers struct. 2263 void GenStruct(const StructDef &struct_def) { 2264 // Generate an accessor struct, with private variables of the form: 2265 // type name_; 2266 // Generates manual padding and alignment. 2267 // Variables are private because they contain little endian data on all 2268 // platforms. 2269 GenComment(struct_def.doc_comment); 2270 code_.SetValue("ALIGN", NumToString(struct_def.minalign)); 2271 code_.SetValue("STRUCT_NAME", Name(struct_def)); 2272 2273 code_ += "MANUALLY_ALIGNED_STRUCT({{ALIGN}}) " 2274 "{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {"; 2275 code_ += " private:"; 2276 2277 int padding_id = 0; 2278 for (auto it = struct_def.fields.vec.begin(); 2279 it != struct_def.fields.vec.end(); ++it) { 2280 const auto &field = **it; 2281 code_.SetValue("FIELD_TYPE", 2282 GenTypeGet(field.value.type, " ", "", " ", false)); 2283 code_.SetValue("FIELD_NAME", Name(field)); 2284 code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;"; 2285 2286 if (field.padding) { 2287 std::string padding; 2288 GenPadding(field, &padding, &padding_id, PaddingDefinition); 2289 code_ += padding; 2290 } 2291 } 2292 2293 // Generate GetFullyQualifiedName 2294 code_ += ""; 2295 code_ += " public:"; 2296 GenFullyQualifiedNameGetter(struct_def, Name(struct_def)); 2297 2298 // Generate a default constructor. 2299 code_ += " {{STRUCT_NAME}}() {"; 2300 code_ += " memset(this, 0, sizeof({{STRUCT_NAME}}));"; 2301 code_ += " }"; 2302 2303 // Generate a constructor that takes all fields as arguments. 2304 std::string arg_list; 2305 std::string init_list; 2306 padding_id = 0; 2307 for (auto it = struct_def.fields.vec.begin(); 2308 it != struct_def.fields.vec.end(); ++it) { 2309 const auto &field = **it; 2310 const auto member_name = Name(field) + "_"; 2311 const auto arg_name = "_" + Name(field); 2312 const auto arg_type = 2313 GenTypeGet(field.value.type, " ", "const ", " &", true); 2314 2315 if (it != struct_def.fields.vec.begin()) { 2316 arg_list += ", "; 2317 init_list += ",\n "; 2318 } 2319 arg_list += arg_type; 2320 arg_list += arg_name; 2321 init_list += member_name; 2322 if (IsScalar(field.value.type.base_type)) { 2323 auto type = GenUnderlyingCast(field, false, arg_name); 2324 init_list += "(flatbuffers::EndianScalar(" + type + "))"; 2325 } else { 2326 init_list += "(" + arg_name + ")"; 2327 } 2328 if (field.padding) { 2329 GenPadding(field, &init_list, &padding_id, PaddingInitializer); 2330 } 2331 } 2332 2333 code_.SetValue("ARG_LIST", arg_list); 2334 code_.SetValue("INIT_LIST", init_list); 2335 code_ += " {{STRUCT_NAME}}({{ARG_LIST}})"; 2336 code_ += " : {{INIT_LIST}} {"; 2337 padding_id = 0; 2338 for (auto it = struct_def.fields.vec.begin(); 2339 it != struct_def.fields.vec.end(); ++it) { 2340 const auto &field = **it; 2341 if (field.padding) { 2342 std::string padding; 2343 GenPadding(field, &padding, &padding_id, PaddingNoop); 2344 code_ += padding; 2345 } 2346 } 2347 code_ += " }"; 2348 2349 // Generate accessor methods of the form: 2350 // type name() const { return flatbuffers::EndianScalar(name_); } 2351 for (auto it = struct_def.fields.vec.begin(); 2352 it != struct_def.fields.vec.end(); ++it) { 2353 const auto &field = **it; 2354 2355 auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true); 2356 auto is_scalar = IsScalar(field.value.type.base_type); 2357 auto member = Name(field) + "_"; 2358 auto value = is_scalar ? "flatbuffers::EndianScalar(" + member + ")" 2359 : member; 2360 2361 code_.SetValue("FIELD_NAME", Name(field)); 2362 code_.SetValue("FIELD_TYPE", field_type); 2363 code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value)); 2364 2365 GenComment(field.doc_comment, " "); 2366 code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {"; 2367 code_ += " return {{FIELD_VALUE}};"; 2368 code_ += " }"; 2369 2370 if (parser_.opts.mutable_buffer) { 2371 auto mut_field_type = GenTypeGet(field.value.type, " ", "", " &", true); 2372 code_.SetValue("FIELD_TYPE", mut_field_type); 2373 if (is_scalar) { 2374 code_.SetValue("ARG", GenTypeBasic(field.value.type, true)); 2375 code_.SetValue("FIELD_VALUE", 2376 GenUnderlyingCast(field, false, "_" + Name(field))); 2377 2378 code_ += " void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {"; 2379 code_ += " flatbuffers::WriteScalar(&{{FIELD_NAME}}_, " 2380 "{{FIELD_VALUE}});"; 2381 code_ += " }"; 2382 } else { 2383 code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {"; 2384 code_ += " return {{FIELD_NAME}}_;"; 2385 code_ += " }"; 2386 } 2387 } 2388 2389 // Generate a comparison function for this field if it is a key. 2390 if (field.key) { 2391 code_ += " bool KeyCompareLessThan(const {{STRUCT_NAME}} *o) const {"; 2392 code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();"; 2393 code_ += " }"; 2394 auto type = GenTypeBasic(field.value.type, false); 2395 if (parser_.opts.scoped_enums && field.value.type.enum_def && 2396 IsScalar(field.value.type.base_type)) { 2397 type = GenTypeGet(field.value.type, " ", "const ", " *", true); 2398 } 2399 2400 code_.SetValue("KEY_TYPE", type); 2401 code_ += " int KeyCompareWithValue({{KEY_TYPE}} val) const {"; 2402 code_ += " const auto key = {{FIELD_NAME}}();"; 2403 code_ += " return static_cast<int>(key > val) - static_cast<int>(key < val);"; 2404 code_ += " }"; 2405 } 2406 } 2407 code_.SetValue("NATIVE_NAME", Name(struct_def)); 2408 GenOperatorNewDelete(struct_def); 2409 code_ += "};"; 2410 2411 code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize)); 2412 code_ += "STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});"; 2413 code_ += ""; 2414 } 2415 2416 // Set up the correct namespace. Only open a namespace if the existing one is 2417 // different (closing/opening only what is necessary). 2418 // 2419 // The file must start and end with an empty (or null) namespace so that 2420 // namespaces are properly opened and closed. 2421 void SetNameSpace(const Namespace *ns) { 2422 if (cur_name_space_ == ns) { 2423 return; 2424 } 2425 2426 // Compute the size of the longest common namespace prefix. 2427 // If cur_name_space is A::B::C::D and ns is A::B::E::F::G, 2428 // the common prefix is A::B:: and we have old_size = 4, new_size = 5 2429 // and common_prefix_size = 2 2430 size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0; 2431 size_t new_size = ns ? ns->components.size() : 0; 2432 2433 size_t common_prefix_size = 0; 2434 while (common_prefix_size < old_size && common_prefix_size < new_size && 2435 ns->components[common_prefix_size] == 2436 cur_name_space_->components[common_prefix_size]) { 2437 common_prefix_size++; 2438 } 2439 2440 // Close cur_name_space in reverse order to reach the common prefix. 2441 // In the previous example, D then C are closed. 2442 for (size_t j = old_size; j > common_prefix_size; --j) { 2443 code_ += "} // namespace " + cur_name_space_->components[j - 1]; 2444 } 2445 if (old_size != common_prefix_size) { 2446 code_ += ""; 2447 } 2448 2449 // open namespace parts to reach the ns namespace 2450 // in the previous example, E, then F, then G are opened 2451 for (auto j = common_prefix_size; j != new_size; ++j) { 2452 code_ += "namespace " + ns->components[j] + " {"; 2453 } 2454 if (new_size != common_prefix_size) { 2455 code_ += ""; 2456 } 2457 2458 cur_name_space_ = ns; 2459 } 2460 }; 2461 2462 } // namespace cpp 2463 2464 bool GenerateCPP(const Parser &parser, const std::string &path, 2465 const std::string &file_name) { 2466 cpp::CppGenerator generator(parser, path, file_name); 2467 return generator.generate(); 2468 } 2469 2470 std::string CPPMakeRule(const Parser &parser, const std::string &path, 2471 const std::string &file_name) { 2472 const auto filebase = 2473 flatbuffers::StripPath(flatbuffers::StripExtension(file_name)); 2474 const auto included_files = parser.GetIncludedFilesRecursive(file_name); 2475 std::string make_rule = GeneratedFileName(path, filebase) + ": "; 2476 for (auto it = included_files.begin(); it != included_files.end(); ++it) { 2477 make_rule += " " + *it; 2478 } 2479 return make_rule; 2480 } 2481 2482 } // namespace flatbuffers 2483