Home | History | Annotate | Download | only in src
      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 static std::string GeneratedFileName(const std::string &path,
     27                                      const std::string &file_name) {
     28   return path + file_name + "_generated.h";
     29 }
     30 
     31 namespace cpp {
     32 class CppGenerator : public BaseGenerator {
     33  public:
     34   CppGenerator(const Parser &parser, const std::string &path,
     35                const std::string &file_name)
     36       : BaseGenerator(parser, path, file_name, "", "::"),
     37         cur_name_space_(nullptr) {}
     38 
     39   std::string GenIncludeGuard() const {
     40     // Generate include guard.
     41     std::string guard = file_name_;
     42     // Remove any non-alpha-numeric characters that may appear in a filename.
     43     struct IsAlnum {
     44       bool operator()(char c) { return !isalnum(c); }
     45     };
     46     guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()),
     47                 guard.end());
     48     guard = "FLATBUFFERS_GENERATED_" + guard;
     49     guard += "_";
     50     // For further uniqueness, also add the namespace.
     51     auto name_space = parser_.namespaces_.back();
     52     for (auto it = name_space->components.begin();
     53          it != name_space->components.end(); ++it) {
     54       guard += *it + "_";
     55     }
     56     guard += "H_";
     57     std::transform(guard.begin(), guard.end(), guard.begin(), ::toupper);
     58     return guard;
     59   }
     60 
     61   void GenIncludeDependencies() {
     62     int num_includes = 0;
     63     for (auto it = parser_.native_included_files_.begin();
     64          it != parser_.native_included_files_.end(); ++it) {
     65       code_ += "#include \"" + *it + "\"";
     66       num_includes++;
     67     }
     68     for (auto it = parser_.included_files_.begin();
     69          it != parser_.included_files_.end(); ++it) {
     70       const auto basename =
     71           flatbuffers::StripPath(flatbuffers::StripExtension(it->first));
     72       if (basename != file_name_) {
     73         code_ += "#include \"" + parser_.opts.include_prefix + basename +
     74                  "_generated.h\"";
     75         num_includes++;
     76       }
     77     }
     78     if (num_includes) code_ += "";
     79   }
     80 
     81   // Iterate through all definitions we haven't generate code for (enums,
     82   // structs, and tables) and output them to a single file.
     83   bool generate() {
     84     if (IsEverythingGenerated()) return true;
     85 
     86     code_.Clear();
     87     code_ += "// " + std::string(FlatBuffersGeneratedWarning());
     88 
     89     const auto include_guard = GenIncludeGuard();
     90     code_ += "#ifndef " + include_guard;
     91     code_ += "#define " + include_guard;
     92     code_ += "";
     93 
     94     code_ += "#include \"flatbuffers/flatbuffers.h\"";
     95     code_ += "";
     96 
     97     if (parser_.opts.include_dependence_headers) {
     98       GenIncludeDependencies();
     99     }
    100 
    101     assert(!cur_name_space_);
    102 
    103     // Generate forward declarations for all structs/tables, since they may
    104     // have circular references.
    105     for (auto it = parser_.structs_.vec.begin();
    106          it != parser_.structs_.vec.end(); ++it) {
    107       const auto &struct_def = **it;
    108       if (!struct_def.generated) {
    109         SetNameSpace(struct_def.defined_namespace);
    110         code_ += "struct " + struct_def.name + ";";
    111         if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
    112           code_ += "struct " + NativeName(struct_def.name) + ";";
    113         }
    114         code_ += "";
    115       }
    116     }
    117 
    118     // Generate code for all the enum declarations.
    119     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
    120          ++it) {
    121       const auto &enum_def = **it;
    122       if (!enum_def.generated) {
    123         SetNameSpace(enum_def.defined_namespace);
    124         GenEnum(enum_def);
    125       }
    126     }
    127 
    128     // Generate code for all structs, then all tables.
    129     for (auto it = parser_.structs_.vec.begin();
    130          it != parser_.structs_.vec.end(); ++it) {
    131       const auto &struct_def = **it;
    132       if (struct_def.fixed && !struct_def.generated) {
    133         SetNameSpace(struct_def.defined_namespace);
    134         GenStruct(struct_def);
    135       }
    136     }
    137     for (auto it = parser_.structs_.vec.begin();
    138          it != parser_.structs_.vec.end(); ++it) {
    139       const auto &struct_def = **it;
    140       if (!struct_def.fixed && !struct_def.generated) {
    141         SetNameSpace(struct_def.defined_namespace);
    142         GenTable(struct_def);
    143       }
    144     }
    145     for (auto it = parser_.structs_.vec.begin();
    146          it != parser_.structs_.vec.end(); ++it) {
    147       const auto &struct_def = **it;
    148       if (!struct_def.fixed && !struct_def.generated) {
    149         SetNameSpace(struct_def.defined_namespace);
    150         GenTablePost(struct_def);
    151       }
    152     }
    153 
    154     // Generate code for union verifiers.
    155     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
    156          ++it) {
    157       const auto &enum_def = **it;
    158       if (enum_def.is_union && !enum_def.generated) {
    159         SetNameSpace(enum_def.defined_namespace);
    160         GenUnionPost(enum_def);
    161       }
    162     }
    163 
    164     // Generate convenient global helper functions:
    165     if (parser_.root_struct_def_) {
    166       auto &struct_def = *parser_.root_struct_def_;
    167       SetNameSpace(struct_def.defined_namespace);
    168       const auto &name = struct_def.name;
    169       const auto qualified_name =
    170           parser_.namespaces_.back()->GetFullyQualifiedName(name);
    171       const auto cpp_name = TranslateNameSpace(qualified_name);
    172 
    173       code_.SetValue("STRUCT_NAME", name);
    174       code_.SetValue("CPP_NAME", cpp_name);
    175 
    176       // The root datatype accessor:
    177       code_ += "inline \\";
    178       code_ += "const {{CPP_NAME}} *Get{{STRUCT_NAME}}(const void *buf) {";
    179       code_ += "  return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
    180       code_ += "}";
    181       code_ += "";
    182 
    183       if (parser_.opts.mutable_buffer) {
    184         code_ += "inline \\";
    185         code_ += "{{STRUCT_NAME}} *GetMutable{{STRUCT_NAME}}(void *buf) {";
    186         code_ += "  return flatbuffers::GetMutableRoot<{{STRUCT_NAME}}>(buf);";
    187         code_ += "}";
    188         code_ += "";
    189       }
    190 
    191       if (parser_.file_identifier_.length()) {
    192         // Return the identifier
    193         code_ += "inline const char *{{STRUCT_NAME}}Identifier() {";
    194         code_ += "  return \"" + parser_.file_identifier_ + "\";";
    195         code_ += "}";
    196         code_ += "";
    197 
    198         // Check if a buffer has the identifier.
    199         code_ += "inline \\";
    200         code_ += "bool {{STRUCT_NAME}}BufferHasIdentifier(const void *buf) {";
    201         code_ += "  return flatbuffers::BufferHasIdentifier(";
    202         code_ += "      buf, {{STRUCT_NAME}}Identifier());";
    203         code_ += "}";
    204         code_ += "";
    205       }
    206 
    207       // The root verifier.
    208       if (parser_.file_identifier_.length()) {
    209         code_.SetValue("ID", name + "Identifier()");
    210       } else {
    211         code_.SetValue("ID", "nullptr");
    212       }
    213 
    214       code_ += "inline bool Verify{{STRUCT_NAME}}Buffer(";
    215       code_ += "    flatbuffers::Verifier &verifier) {";
    216       code_ += "  return verifier.VerifyBuffer<{{CPP_NAME}}>({{ID}});";
    217       code_ += "}";
    218       code_ += "";
    219 
    220       if (parser_.file_extension_.length()) {
    221         // Return the extension
    222         code_ += "inline const char *{{STRUCT_NAME}}Extension() {";
    223         code_ += "  return \"" + parser_.file_extension_ + "\";";
    224         code_ += "}";
    225         code_ += "";
    226       }
    227 
    228       // Finish a buffer with a given root object:
    229       code_ += "inline void Finish{{STRUCT_NAME}}Buffer(";
    230       code_ += "    flatbuffers::FlatBufferBuilder &fbb,";
    231       code_ += "    flatbuffers::Offset<{{CPP_NAME}}> root) {";
    232       if (parser_.file_identifier_.length())
    233         code_ += "  fbb.Finish(root, {{STRUCT_NAME}}Identifier());";
    234       else
    235         code_ += "  fbb.Finish(root);";
    236       code_ += "}";
    237       code_ += "";
    238 
    239       if (parser_.opts.generate_object_based_api) {
    240         // A convenient root unpack function.
    241         auto native_name =
    242             NativeName(WrapInNameSpace(struct_def));
    243         code_.SetValue("UNPACK_RETURN",
    244                        GenTypeNativePtr(native_name, nullptr, false));
    245         code_.SetValue("UNPACK_TYPE",
    246                        GenTypeNativePtr(native_name, nullptr, true));
    247 
    248         code_ += "inline {{UNPACK_RETURN}} UnPack{{STRUCT_NAME}}(";
    249         code_ += "    const void *buf,";
    250         code_ += "    const flatbuffers::resolver_function_t *res = nullptr) {";
    251         code_ += "  return {{UNPACK_TYPE}}\\";
    252         code_ += "(Get{{STRUCT_NAME}}(buf)->UnPack(res));";
    253         code_ += "}";
    254         code_ += "";
    255       }
    256     }
    257 
    258     assert(cur_name_space_);
    259     SetNameSpace(nullptr);
    260 
    261     // Close the include guard.
    262     code_ += "#endif  // " + include_guard;
    263 
    264     const auto file_path = GeneratedFileName(path_, file_name_);
    265     const auto final_code = code_.ToString();
    266     return SaveFile(file_path.c_str(), final_code, false);
    267   }
    268 
    269  private:
    270   CodeWriter code_;
    271 
    272   // This tracks the current namespace so we can insert namespace declarations.
    273   const Namespace *cur_name_space_;
    274 
    275   const Namespace *CurrentNameSpace() const { return cur_name_space_; }
    276 
    277   // Translates a qualified name in flatbuffer text format to the same name in
    278   // the equivalent C++ namespace.
    279   static std::string TranslateNameSpace(const std::string &qualified_name) {
    280     std::string cpp_qualified_name = qualified_name;
    281     size_t start_pos = 0;
    282     while ((start_pos = cpp_qualified_name.find(".", start_pos)) !=
    283            std::string::npos) {
    284       cpp_qualified_name.replace(start_pos, 1, "::");
    285     }
    286     return cpp_qualified_name;
    287   }
    288 
    289   void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
    290     std::string text;
    291     ::flatbuffers::GenComment(dc, &text, nullptr, prefix);
    292     code_ += text + "\\";
    293   }
    294 
    295   // Return a C++ type from the table in idl.h
    296   std::string GenTypeBasic(const Type &type, bool user_facing_type) const {
    297     static const char *ctypename[] = {
    298     #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
    299             #CTYPE,
    300         FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
    301     #undef FLATBUFFERS_TD
    302     };
    303     if (user_facing_type) {
    304       if (type.enum_def) return WrapInNameSpace(*type.enum_def);
    305       if (type.base_type == BASE_TYPE_BOOL) return "bool";
    306     }
    307     return ctypename[type.base_type];
    308   }
    309 
    310   // Return a C++ pointer type, specialized to the actual struct/table types,
    311   // and vector element types.
    312   std::string GenTypePointer(const Type &type) const {
    313     switch (type.base_type) {
    314       case BASE_TYPE_STRING: {
    315         return "flatbuffers::String";
    316       }
    317       case BASE_TYPE_VECTOR: {
    318         const auto type_name = GenTypeWire(type.VectorType(), "", false);
    319         return "flatbuffers::Vector<" + type_name + ">";
    320       }
    321       case BASE_TYPE_STRUCT: {
    322         return WrapInNameSpace(*type.struct_def);
    323       }
    324       case BASE_TYPE_UNION:
    325       // fall through
    326       default: {
    327         return "void";
    328       }
    329     }
    330   }
    331 
    332   // Return a C++ type for any type (scalar/pointer) specifically for
    333   // building a flatbuffer.
    334   std::string GenTypeWire(const Type &type, const char *postfix,
    335                           bool user_facing_type) const {
    336     if (IsScalar(type.base_type)) {
    337       return GenTypeBasic(type, user_facing_type) + postfix;
    338     } else if (IsStruct(type)) {
    339       return "const " + GenTypePointer(type) + " *";
    340     } else {
    341       return "flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix;
    342     }
    343   }
    344 
    345   // Return a C++ type for any type (scalar/pointer) that reflects its
    346   // serialized size.
    347   std::string GenTypeSize(const Type &type) const {
    348     if (IsScalar(type.base_type)) {
    349       return GenTypeBasic(type, false);
    350     } else if (IsStruct(type)) {
    351       return GenTypePointer(type);
    352     } else {
    353       return "flatbuffers::uoffset_t";
    354     }
    355   }
    356 
    357   // TODO(wvo): make this configurable.
    358   static std::string NativeName(const std::string &name) { return name + "T"; }
    359 
    360   const std::string &PtrType(const FieldDef *field) {
    361     auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
    362     return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type;
    363   }
    364 
    365   std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
    366                                bool is_constructor) {
    367     auto &ptr_type = PtrType(field);
    368     if (ptr_type != "naked") {
    369       return ptr_type + "<" + type + ">";
    370     } else if (is_constructor) {
    371       return "";
    372     } else {
    373       return type + " *";
    374     }
    375   }
    376 
    377   std::string GenPtrGet(const FieldDef &field) {
    378     auto &ptr_type = PtrType(&field);
    379     return ptr_type == "naked" ? "" : ".get()";
    380   }
    381 
    382   std::string GenTypeNative(const Type &type, bool invector,
    383                             const FieldDef &field) {
    384     switch (type.base_type) {
    385       case BASE_TYPE_STRING: {
    386         return "std::string";
    387       }
    388       case BASE_TYPE_VECTOR: {
    389         const auto type_name = GenTypeNative(type.VectorType(), true, field);
    390         return "std::vector<" + type_name + ">";
    391       }
    392       case BASE_TYPE_STRUCT: {
    393         auto type_name = WrapInNameSpace(*type.struct_def);
    394         if (IsStruct(type)) {
    395           auto native_type = type.struct_def->attributes.Lookup("native_type");
    396           if (native_type) {
    397             type_name = native_type->constant;
    398           }
    399           if (invector || field.native_inline) {
    400             return type_name;
    401           } else {
    402             return GenTypeNativePtr(type_name, &field, false);
    403           }
    404         } else {
    405           return GenTypeNativePtr(NativeName(type_name), &field, false);
    406         }
    407       }
    408       case BASE_TYPE_UNION: {
    409         return type.enum_def->name + "Union";
    410       }
    411       default: {
    412         return GenTypeBasic(type, true);
    413       }
    414     }
    415   }
    416 
    417   // Return a C++ type for any type (scalar/pointer) specifically for
    418   // using a flatbuffer.
    419   std::string GenTypeGet(const Type &type, const char *afterbasic,
    420                          const char *beforeptr, const char *afterptr,
    421                          bool user_facing_type) {
    422     if (IsScalar(type.base_type)) {
    423       return GenTypeBasic(type, user_facing_type) + afterbasic;
    424     } else {
    425       return beforeptr + GenTypePointer(type) + afterptr;
    426     }
    427   }
    428 
    429   std::string GenEnumDecl(const EnumDef &enum_def) const {
    430     const IDLOptions &opts = parser_.opts;
    431     return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name;
    432   }
    433 
    434   std::string GenEnumValDecl(const EnumDef &enum_def,
    435                              const std::string &enum_val) const {
    436     const IDLOptions &opts = parser_.opts;
    437     return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val;
    438   }
    439 
    440   std::string GetEnumValUse(const EnumDef &enum_def,
    441                             const EnumVal &enum_val) const {
    442     const IDLOptions &opts = parser_.opts;
    443     if (opts.scoped_enums) {
    444       return enum_def.name + "::" + enum_val.name;
    445     } else if (opts.prefixed_enums) {
    446       return enum_def.name + "_" + enum_val.name;
    447     } else {
    448       return enum_val.name;
    449     }
    450   }
    451 
    452   static std::string UnionVerifySignature(const EnumDef &enum_def) {
    453     return "bool Verify" + enum_def.name +
    454            "(flatbuffers::Verifier &verifier, const void *obj, " +
    455            enum_def.name + " type)";
    456   }
    457 
    458   static std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
    459     return "bool Verify" + enum_def.name + "Vector" +
    460            "(flatbuffers::Verifier &verifier, " +
    461            "const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " +
    462            "const flatbuffers::Vector<uint8_t> *types)";
    463   }
    464 
    465   static std::string UnionUnPackSignature(const EnumDef &enum_def,
    466                                           bool inclass) {
    467     return (inclass ? "static " : "") +
    468            std::string("flatbuffers::NativeTable *") +
    469            (inclass ? "" : enum_def.name + "Union::") +
    470            "UnPack(const void *obj, " + enum_def.name +
    471            " type, const flatbuffers::resolver_function_t *resolver)";
    472   }
    473 
    474   static std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) {
    475     return "flatbuffers::Offset<void> " +
    476            (inclass ? "" : enum_def.name + "Union::") +
    477            "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
    478            "const flatbuffers::rehasher_function_t *_rehasher" +
    479            (inclass ? " = nullptr" : "") + ") const";
    480   }
    481 
    482   static std::string TableCreateSignature(const StructDef &struct_def,
    483                                           bool predecl) {
    484     return "flatbuffers::Offset<" + struct_def.name + "> Create" +
    485            struct_def.name  +
    486            "(flatbuffers::FlatBufferBuilder &_fbb, const " +
    487            NativeName(struct_def.name) +
    488            " *_o, const flatbuffers::rehasher_function_t *_rehasher" +
    489            (predecl ? " = nullptr" : "") + ")";
    490   }
    491 
    492   static std::string TablePackSignature(const StructDef &struct_def,
    493                                         bool inclass) {
    494     return std::string(inclass ? "static " : "") +
    495            "flatbuffers::Offset<" + struct_def.name + "> " +
    496            (inclass ? "" : struct_def.name + "::") +
    497            "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
    498            "const " + NativeName(struct_def.name) + "* _o, " +
    499            "const flatbuffers::rehasher_function_t *_rehasher" +
    500            (inclass ? " = nullptr" : "") + ")";
    501   }
    502 
    503   static std::string TableUnPackSignature(const StructDef &struct_def,
    504                                           bool inclass) {
    505     return NativeName(struct_def.name) + " *" +
    506            (inclass ? "" : struct_def.name + "::") +
    507            "UnPack(const flatbuffers::resolver_function_t *_resolver" +
    508            (inclass ? " = nullptr" : "") + ") const";
    509   }
    510 
    511   static std::string TableUnPackToSignature(const StructDef &struct_def,
    512                                             bool inclass) {
    513     return "void " + (inclass ? "" : struct_def.name + "::") +
    514            "UnPackTo(" + NativeName(struct_def.name) + " *" + "_o, " +
    515            "const flatbuffers::resolver_function_t *_resolver" +
    516            (inclass ? " = nullptr" : "") + ") const";
    517   }
    518 
    519   // Generate an enum declaration and an enum string lookup table.
    520   void GenEnum(const EnumDef &enum_def) {
    521     code_.SetValue("ENUM_NAME", enum_def.name);
    522     code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
    523     code_.SetValue("SEP", "");
    524 
    525     GenComment(enum_def.doc_comment);
    526     code_ += GenEnumDecl(enum_def) + "\\";
    527     if (parser_.opts.scoped_enums)
    528       code_ += " : {{BASE_TYPE}}\\";
    529     code_ += " {";
    530 
    531     int64_t anyv = 0;
    532     const EnumVal *minv = nullptr, *maxv = nullptr;
    533     for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    534          ++it) {
    535       const auto &ev = **it;
    536 
    537       GenComment(ev.doc_comment, "  ");
    538       code_.SetValue("KEY", GenEnumValDecl(enum_def, ev.name));
    539       code_.SetValue("VALUE", NumToString(ev.value));
    540       code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
    541       code_.SetValue("SEP", ",\n");
    542 
    543       minv = !minv || minv->value > ev.value ? &ev : minv;
    544       maxv = !maxv || maxv->value < ev.value ? &ev : maxv;
    545       anyv |= ev.value;
    546     }
    547 
    548     if (parser_.opts.scoped_enums || parser_.opts.prefixed_enums) {
    549       assert(minv && maxv);
    550 
    551       code_.SetValue("SEP", ",\n");
    552       if (enum_def.attributes.Lookup("bit_flags")) {
    553         code_.SetValue("KEY", GenEnumValDecl(enum_def, "NONE"));
    554         code_.SetValue("VALUE", "0");
    555         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
    556 
    557         code_.SetValue("KEY", GenEnumValDecl(enum_def, "ANY"));
    558         code_.SetValue("VALUE", NumToString(anyv));
    559         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
    560       } else {  // MIN & MAX are useless for bit_flags
    561         code_.SetValue("KEY",GenEnumValDecl(enum_def, "MIN"));
    562         code_.SetValue("VALUE", GenEnumValDecl(enum_def, minv->name));
    563         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
    564 
    565         code_.SetValue("KEY",GenEnumValDecl(enum_def, "MAX"));
    566         code_.SetValue("VALUE", GenEnumValDecl(enum_def, maxv->name));
    567         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
    568       }
    569     }
    570     code_ += "";
    571     code_ += "};";
    572 
    573     if (parser_.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags")) {
    574       code_ += "DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})";
    575     }
    576     code_ += "";
    577 
    578     // Generate a generate string table for enum values.
    579     // Problem is, if values are very sparse that could generate really big
    580     // tables. Ideally in that case we generate a map lookup instead, but for
    581     // the moment we simply don't output a table at all.
    582     auto range =
    583         enum_def.vals.vec.back()->value - enum_def.vals.vec.front()->value + 1;
    584     // Average distance between values above which we consider a table
    585     // "too sparse". Change at will.
    586     static const int kMaxSparseness = 5;
    587     if (range / static_cast<int64_t>(enum_def.vals.vec.size()) <
    588         kMaxSparseness) {
    589       code_ += "inline const char **EnumNames{{ENUM_NAME}}() {";
    590       code_ += "  static const char *names[] = {";
    591 
    592       auto val = enum_def.vals.vec.front()->value;
    593       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    594            ++it) {
    595         const auto &ev = **it;
    596         while (val++ != ev.value) {
    597           code_ += "    \"\",";
    598         }
    599         code_ += "    \"" + ev.name + "\",";
    600       }
    601       code_ += "    nullptr";
    602       code_ += "  };";
    603 
    604       code_ += "  return names;";
    605       code_ += "}";
    606       code_ += "";
    607 
    608       code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
    609 
    610       code_ += "  const size_t index = static_cast<int>(e)\\";
    611       if (enum_def.vals.vec.front()->value) {
    612         auto vals = GetEnumValUse(enum_def, *enum_def.vals.vec.front());
    613         code_ += " - static_cast<int>(" + vals + ")\\";
    614       }
    615       code_ += ";";
    616 
    617       code_ += "  return EnumNames{{ENUM_NAME}}()[index];";
    618       code_ += "}";
    619       code_ += "";
    620     }
    621 
    622     // Generate type traits for unions to map from a type to union enum value.
    623     if (enum_def.is_union) {
    624       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    625         ++it) {
    626         const auto &ev = **it;
    627 
    628         if (it == enum_def.vals.vec.begin()) {
    629           code_ += "template<typename T> struct {{ENUM_NAME}}Traits {";
    630         }
    631         else {
    632           auto name = WrapInNameSpace(*ev.struct_def);
    633           code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {";
    634         }
    635 
    636         auto value = GetEnumValUse(enum_def, ev);
    637         code_ += "  static const {{ENUM_NAME}} enum_value = " + value + ";";
    638         code_ += "};";
    639         code_ += "";
    640       }
    641     }
    642 
    643     if (parser_.opts.generate_object_based_api && enum_def.is_union) {
    644       // Generate a union type
    645       code_.SetValue("NAME", enum_def.name);
    646       code_.SetValue("NONE",
    647           GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE")));
    648 
    649       code_ += "struct {{NAME}}Union {";
    650       code_ += "  {{NAME}} type;";
    651       code_ += "  flatbuffers::NativeTable *table;";
    652       code_ += "";
    653       code_ += "  {{NAME}}Union() : type({{NONE}}), table(nullptr) {}";
    654       code_ += "  {{NAME}}Union({{NAME}}Union&& u):";
    655       code_ += "    type(std::move(u.type)), table(std::move(u.table)) {}";
    656       code_ += "  {{NAME}}Union(const {{NAME}}Union &);";
    657       code_ += "  {{NAME}}Union &operator=(const {{NAME}}Union &);";
    658       code_ += "  ~{{NAME}}Union() { Reset(); }";
    659       code_ += "";
    660       code_ += "  void Reset();";
    661       code_ += "";
    662       code_ += "  template <typename T>";
    663       code_ += "  void Set(T&& value) {";
    664       code_ += "    Reset();";
    665       code_ += "    type = {{NAME}}Traits<typename T::TableType>::enum_value;";
    666       code_ += "    if (type != {{NONE}}) {";
    667       code_ += "      table = new T(std::forward<T>(value));";
    668       code_ += "    }";
    669       code_ += "  }";
    670       code_ += "";
    671       code_ += "  " + UnionUnPackSignature(enum_def, true) + ";";
    672       code_ += "  " + UnionPackSignature(enum_def, true) + ";";
    673       code_ += "";
    674 
    675       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    676            ++it) {
    677         const auto &ev = **it;
    678         if (!ev.value) {
    679           continue;
    680         }
    681 
    682         const auto native_type = NativeName(WrapInNameSpace(*ev.struct_def));
    683         code_.SetValue("NATIVE_TYPE", native_type);
    684         code_.SetValue("NATIVE_NAME", ev.name);
    685         code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
    686 
    687         code_ += "  {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
    688         code_ += "    return type == {{NATIVE_ID}} ?";
    689         code_ += "      reinterpret_cast<{{NATIVE_TYPE}} *>(table) : nullptr;";
    690         code_ += "  }";
    691       }
    692       code_ += "};";
    693       code_ += "";
    694     }
    695 
    696     if (enum_def.is_union) {
    697       code_ += UnionVerifySignature(enum_def) + ";";
    698       code_ += UnionVectorVerifySignature(enum_def) + ";";
    699       code_ += "";
    700     }
    701   }
    702 
    703   void GenUnionPost(const EnumDef &enum_def) {
    704     // Generate a verifier function for this union that can be called by the
    705     // table verifier functions. It uses a switch case to select a specific
    706     // verifier function to call, this should be safe even if the union type
    707     // has been corrupted, since the verifiers will simply fail when called
    708     // on the wrong type.
    709     code_.SetValue("ENUM_NAME", enum_def.name);
    710 
    711     code_ += "inline " + UnionVerifySignature(enum_def) + " {";
    712     code_ += "  switch (type) {";
    713     for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    714          ++it) {
    715       const auto &ev = **it;
    716       code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
    717 
    718       if (ev.value) {
    719         code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def));
    720         code_ += "    case {{LABEL}}: {";
    721         code_ += "      auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
    722         code_ += "      return verifier.VerifyTable(ptr);";
    723         code_ += "    }";
    724       } else {
    725         code_ += "    case {{LABEL}}: {";
    726         code_ += "      return true;";  // "NONE" enum value.
    727         code_ += "    }";
    728       }
    729     }
    730     code_ += "    default: return false;";
    731     code_ += "  }";
    732     code_ += "}";
    733     code_ += "";
    734 
    735     code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
    736     code_ += "  if (values->size() != types->size()) return false;";
    737     code_ += "  for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {";
    738     code_ += "    if (!Verify" + enum_def.name + "(";
    739     code_ += "        verifier,  values->Get(i), types->GetEnum<" + enum_def.name + ">(i))) {";
    740     code_ += "      return false;";
    741     code_ += "    }";
    742     code_ += "  }";
    743     code_ += "  return true;";
    744     code_ += "}";
    745     code_ += "";
    746 
    747     if (parser_.opts.generate_object_based_api) {
    748       // Generate union Unpack() and Pack() functions.
    749       code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {";
    750       code_ += "  switch (type) {";
    751       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    752            ++it) {
    753         const auto &ev = **it;
    754         if (!ev.value) {
    755           continue;
    756         }
    757 
    758         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
    759         code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def));
    760         code_ += "    case {{LABEL}}: {";
    761         code_ += "      auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
    762         code_ += "      return ptr->UnPack(resolver);";
    763         code_ += "    }";
    764       }
    765       code_ += "    default: return nullptr;";
    766       code_ += "  }";
    767       code_ += "}";
    768       code_ += "";
    769 
    770       code_ += "inline " + UnionPackSignature(enum_def, false) + " {";
    771       code_ += "  switch (type) {";
    772       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    773            ++it) {
    774         auto &ev = **it;
    775         if (!ev.value) {
    776           continue;
    777         }
    778 
    779         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
    780         code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def)));
    781         code_.SetValue("NAME", ev.struct_def->name);
    782         code_ += "    case {{LABEL}}: {";
    783         code_ += "      auto ptr = reinterpret_cast<const {{TYPE}} *>(table);";
    784         code_ += "      return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
    785         code_ += "    }";
    786       }
    787       code_ += "    default: return 0;";
    788       code_ += "  }";
    789       code_ += "}";
    790       code_ += "";
    791 
    792       // Union Reset() function.
    793       code_.SetValue("NONE",
    794           GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE")));
    795 
    796       code_ += "inline void {{ENUM_NAME}}Union::Reset() {";
    797       code_ += "  switch (type) {";
    798       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
    799            ++it) {
    800         const auto &ev = **it;
    801         if (!ev.value) {
    802           continue;
    803         }
    804 
    805         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
    806         code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def)));
    807 
    808         code_ += "    case {{LABEL}}: {";
    809         code_ += "      auto ptr = reinterpret_cast<{{TYPE}} *>(table);";
    810         code_ += "      delete ptr;";
    811         code_ += "      break;";
    812         code_ += "    }";
    813       }
    814       code_ += "    default: break;";
    815       code_ += "  }";
    816       code_ += "  table = nullptr;";
    817       code_ += "  type = {{NONE}};";
    818       code_ += "}";
    819       code_ += "";
    820     }
    821   }
    822 
    823   // Generates a value with optionally a cast applied if the field has a
    824   // different underlying type from its interface type (currently only the
    825   // case for enums. "from" specify the direction, true meaning from the
    826   // underlying type to the interface type.
    827   std::string GenUnderlyingCast(const FieldDef &field, bool from,
    828                                 const std::string &val) {
    829     if (from && field.value.type.base_type == BASE_TYPE_BOOL) {
    830       return val + " != 0";
    831     } else if ((field.value.type.enum_def &&
    832                 IsScalar(field.value.type.base_type)) ||
    833                field.value.type.base_type == BASE_TYPE_BOOL) {
    834       return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" +
    835              val + ")";
    836     } else {
    837       return val;
    838     }
    839   }
    840 
    841   std::string GenFieldOffsetName(const FieldDef &field) {
    842     std::string uname = field.name;
    843     std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper);
    844     return "VT_" + uname;
    845   }
    846 
    847   void GenFullyQualifiedNameGetter(const std::string &name) {
    848     if (!parser_.opts.generate_name_strings) {
    849       return;
    850     }
    851 
    852     auto fullname = parser_.namespaces_.back()->GetFullyQualifiedName(name);
    853     code_.SetValue("NAME", fullname);
    854     code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR");
    855 
    856     code_ += "  static {{CONSTEXPR}} const char *GetFullyQualifiedName() {";
    857     code_ += "    return \"{{NAME}}\";";
    858     code_ += "  }";
    859   }
    860 
    861   std::string GenDefaultConstant(const FieldDef &field) {
    862     return field.value.type.base_type == BASE_TYPE_FLOAT
    863                ? field.value.constant + "f"
    864                : field.value.constant;
    865   }
    866 
    867   std::string GetDefaultScalarValue(const FieldDef &field) {
    868     if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) {
    869       auto ev = field.value.type.enum_def->ReverseLookup(
    870           static_cast<int>(StringToInt(field.value.constant.c_str())), false);
    871       if (ev) {
    872         return WrapInNameSpace(
    873             field.value.type.enum_def->defined_namespace,
    874             GetEnumValUse(*field.value.type.enum_def, *ev));
    875       } else {
    876         return GenUnderlyingCast(field, true, field.value.constant);
    877       }
    878     } else if (field.value.type.base_type == BASE_TYPE_BOOL) {
    879       return field.value.constant == "0" ? "false" : "true";
    880     } else {
    881       return GenDefaultConstant(field);
    882     }
    883   }
    884 
    885   void GenParam(const FieldDef &field, bool direct, const char *prefix) {
    886     code_.SetValue("PRE", prefix);
    887     code_.SetValue("PARAM_NAME", field.name);
    888     if (direct && field.value.type.base_type == BASE_TYPE_STRING) {
    889       code_.SetValue("PARAM_TYPE", "const char *");
    890       code_.SetValue("PARAM_VALUE", "nullptr");
    891     } else if (direct && field.value.type.base_type == BASE_TYPE_VECTOR) {
    892       auto type = GenTypeWire(field.value.type.VectorType(), "", false);
    893       code_.SetValue("PARAM_TYPE", "const std::vector<" + type + "> *");
    894       code_.SetValue("PARAM_VALUE", "nullptr");
    895     } else {
    896       code_.SetValue("PARAM_TYPE", GenTypeWire(field.value.type, " ", true));
    897       code_.SetValue("PARAM_VALUE", GetDefaultScalarValue(field));
    898     }
    899     code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\";
    900   }
    901 
    902   // Generate a member, including a default value for scalars and raw pointers.
    903   void GenMember(const FieldDef &field) {
    904     if (!field.deprecated &&  // Deprecated fields won't be accessible.
    905         field.value.type.base_type != BASE_TYPE_UTYPE) {
    906       auto type = GenTypeNative(field.value.type, false, field);
    907       auto cpp_type = field.attributes.Lookup("cpp_type");
    908       auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " ");
    909       code_.SetValue("FIELD_TYPE", full_type);
    910       code_.SetValue("FIELD_NAME", field.name);
    911       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}};";
    912     }
    913   }
    914 
    915   // Generate the default constructor for this struct. Properly initialize all
    916   // scalar members with default values.
    917   void GenDefaultConstructor(const StructDef& struct_def) {
    918     std::string initializer_list;
    919     for (auto it = struct_def.fields.vec.begin();
    920          it != struct_def.fields.vec.end(); ++it) {
    921       const auto &field = **it;
    922       if (!field.deprecated &&  // Deprecated fields won't be accessible.
    923           field.value.type.base_type != BASE_TYPE_UTYPE) {
    924         auto cpp_type = field.attributes.Lookup("cpp_type");
    925         // Scalar types get parsed defaults, raw pointers get nullptrs.
    926         if (IsScalar(field.value.type.base_type)) {
    927           if (!initializer_list.empty()) {
    928             initializer_list += ",\n        ";
    929           }
    930           initializer_list += field.name;
    931           initializer_list += "(" + GetDefaultScalarValue(field) + ")";
    932         } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
    933           if (IsStruct(field.value.type)) {
    934             auto native_default = field.attributes.Lookup("native_default");
    935             if (native_default) {
    936               if (!initializer_list.empty()) {
    937                 initializer_list += ",\n        ";
    938               }
    939               initializer_list +=
    940                   field.name + "(" + native_default->constant + ")";
    941             }
    942           }
    943         } else if (cpp_type) {
    944           if (!initializer_list.empty()) {
    945             initializer_list += ",\n        ";
    946           }
    947           initializer_list += field.name + "(0)";
    948         }
    949       }
    950     }
    951     if (!initializer_list.empty()) {
    952       initializer_list = "\n      : " + initializer_list;
    953     }
    954 
    955     code_.SetValue("NATIVE_NAME", NativeName(struct_def.name));
    956     code_.SetValue("INIT_LIST", initializer_list);
    957 
    958     code_ += "  {{NATIVE_NAME}}(){{INIT_LIST}} {";
    959     code_ += "  }";
    960   }
    961 
    962   void GenNativeTable(const StructDef &struct_def) {
    963     const auto native_name = NativeName(struct_def.name);
    964     code_.SetValue("STRUCT_NAME", struct_def.name);
    965     code_.SetValue("NATIVE_NAME", native_name);
    966 
    967     // Generate a C++ object that can hold an unpacked version of this table.
    968     code_ += "struct {{NATIVE_NAME}} : public flatbuffers::NativeTable {";
    969     code_ += "  typedef {{STRUCT_NAME}} TableType;";
    970     GenFullyQualifiedNameGetter(native_name);
    971     for (auto it = struct_def.fields.vec.begin();
    972          it != struct_def.fields.vec.end(); ++it) {
    973       GenMember(**it);
    974     }
    975     GenDefaultConstructor(struct_def);
    976     code_ += "};";
    977     code_ += "";
    978   }
    979 
    980   // Generate the code to call the appropriate Verify function(s) for a field.
    981   void GenVerifyCall(const FieldDef &field, const char* prefix) {
    982     code_.SetValue("PRE", prefix);
    983     code_.SetValue("NAME", field.name);
    984     code_.SetValue("REQUIRED", field.required ? "Required" : "");
    985     code_.SetValue("SIZE", GenTypeSize(field.value.type));
    986     code_.SetValue("OFFSET", GenFieldOffsetName(field));
    987     code_ += "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\";
    988 
    989     switch (field.value.type.base_type) {
    990       case BASE_TYPE_UNION: {
    991         code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
    992         code_.SetValue("SUFFIX", UnionTypeFieldSuffix());
    993         code_ += "{{PRE}}Verify{{ENUM_NAME}}(verifier, {{NAME}}(), "
    994                 "{{NAME}}{{SUFFIX}}())\\";
    995         break;
    996       }
    997       case BASE_TYPE_STRUCT: {
    998         if (!field.value.type.struct_def->fixed) {
    999           code_ += "{{PRE}}verifier.VerifyTable({{NAME}}())\\";
   1000         }
   1001         break;
   1002       }
   1003       case BASE_TYPE_STRING: {
   1004         code_ += "{{PRE}}verifier.Verify({{NAME}}())\\";
   1005         break;
   1006       }
   1007       case BASE_TYPE_VECTOR: {
   1008         code_ += "{{PRE}}verifier.Verify({{NAME}}())\\";
   1009 
   1010         switch (field.value.type.element) {
   1011           case BASE_TYPE_STRING: {
   1012             code_ += "{{PRE}}verifier.VerifyVectorOfStrings({{NAME}}())\\";
   1013             break;
   1014           }
   1015           case BASE_TYPE_STRUCT: {
   1016             if (!field.value.type.struct_def->fixed) {
   1017               code_ += "{{PRE}}verifier.VerifyVectorOfTables({{NAME}}())\\";
   1018             }
   1019             break;
   1020           }
   1021           case BASE_TYPE_UNION: {
   1022             code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
   1023             code_ += "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), {{NAME}}_type())\\";
   1024             break;
   1025           }
   1026           default:
   1027             break;
   1028         }
   1029         break;
   1030       }
   1031       default: {
   1032         break;
   1033       }
   1034     }
   1035   }
   1036 
   1037   // Generate an accessor struct, builder structs & function for a table.
   1038   void GenTable(const StructDef &struct_def) {
   1039     if (parser_.opts.generate_object_based_api) {
   1040       GenNativeTable(struct_def);
   1041     }
   1042 
   1043     // Generate an accessor struct, with methods of the form:
   1044     // type name() const { return GetField<type>(offset, defaultval); }
   1045     GenComment(struct_def.doc_comment);
   1046 
   1047     code_.SetValue("STRUCT_NAME", struct_def.name);
   1048     code_ += "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS"
   1049             " : private flatbuffers::Table {";
   1050     if (parser_.opts.generate_object_based_api) {
   1051       code_ += "  typedef {{NATIVE_NAME}} NativeTableType;";
   1052     }
   1053 
   1054     GenFullyQualifiedNameGetter(struct_def.name);
   1055 
   1056     // Generate field id constants.
   1057     if (struct_def.fields.vec.size() > 0) {
   1058       // We need to add a trailing comma to all elements except the last one as
   1059       // older versions of gcc complain about this.
   1060       code_.SetValue("SEP", "");
   1061       code_ += "  enum {";
   1062       for (auto it = struct_def.fields.vec.begin();
   1063            it != struct_def.fields.vec.end(); ++it) {
   1064         const auto &field = **it;
   1065         if (field.deprecated) {
   1066           // Deprecated fields won't be accessible.
   1067           continue;
   1068         }
   1069 
   1070         code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
   1071         code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
   1072         code_ += "{{SEP}}    {{OFFSET_NAME}} = {{OFFSET_VALUE}}\\";
   1073         code_.SetValue("SEP", ",\n");
   1074       }
   1075       code_ += "";
   1076       code_ += "  };";
   1077     }
   1078 
   1079     // Generate the accessors.
   1080     for (auto it = struct_def.fields.vec.begin();
   1081          it != struct_def.fields.vec.end(); ++it) {
   1082       const auto &field = **it;
   1083       if (field.deprecated) {
   1084         // Deprecated fields won't be accessible.
   1085         continue;
   1086       }
   1087 
   1088       const bool is_struct = IsStruct(field.value.type);
   1089       const bool is_scalar = IsScalar(field.value.type.base_type);
   1090       code_.SetValue("FIELD_NAME", field.name);
   1091 
   1092       // Call a different accessor for pointers, that indirects.
   1093       std::string accessor = "";
   1094       if (is_scalar) {
   1095         accessor = "GetField<";
   1096       } else if (is_struct) {
   1097         accessor = "GetStruct<";
   1098       } else {
   1099         accessor = "GetPointer<";
   1100       }
   1101       auto offset_str = GenFieldOffsetName(field);
   1102       auto offset_type =
   1103           GenTypeGet(field.value.type, "", "const ", " *", false);
   1104 
   1105       auto call = accessor + offset_type + ">(" + offset_str;
   1106       // Default value as second arg for non-pointer types.
   1107       if (is_scalar) {
   1108         call += ", " + GenDefaultConstant(field);
   1109       }
   1110       call += ")";
   1111 
   1112       GenComment(field.doc_comment, "  ");
   1113       code_.SetValue("FIELD_TYPE",
   1114           GenTypeGet(field.value.type, " ", "const ", " *", true));
   1115       code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call));
   1116 
   1117       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
   1118       code_ += "    return {{FIELD_VALUE}};";
   1119       code_ += "  }";
   1120 
   1121       if (parser_.opts.mutable_buffer) {
   1122         if (is_scalar) {
   1123           code_.SetValue("OFFSET_NAME", offset_str);
   1124           code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true));
   1125           code_.SetValue("FIELD_VALUE",
   1126                         GenUnderlyingCast(field, false, "_" + field.name));
   1127 
   1128           code_ += "  bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} "
   1129                   "_{{FIELD_NAME}}) {";
   1130           code_ += "    return SetField({{OFFSET_NAME}}, {{FIELD_VALUE}});";
   1131           code_ += "  }";
   1132         } else {
   1133           auto type = GenTypeGet(field.value.type, " ", "", " *", true);
   1134           auto underlying = accessor + type + ">(" + offset_str + ")";
   1135           code_.SetValue("FIELD_TYPE", type);
   1136           code_.SetValue("FIELD_VALUE",
   1137                         GenUnderlyingCast(field, true, underlying));
   1138 
   1139           code_ += "  {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
   1140           code_ += "    return {{FIELD_VALUE}};";
   1141           code_ += "  }";
   1142         }
   1143       }
   1144 
   1145       auto nested = field.attributes.Lookup("nested_flatbuffer");
   1146       if (nested) {
   1147         std::string qualified_name =
   1148             parser_.namespaces_.back()->GetFullyQualifiedName(
   1149                 nested->constant);
   1150         auto nested_root = parser_.structs_.Lookup(qualified_name);
   1151         assert(nested_root);  // Guaranteed to exist by parser.
   1152         (void)nested_root;
   1153         code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name));
   1154 
   1155         code_ += "  const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
   1156         code_ += "    const uint8_t* data = {{FIELD_NAME}}()->Data();";
   1157         code_ += "    return flatbuffers::GetRoot<{{CPP_NAME}}>(data);";
   1158         code_ += "  }";
   1159       }
   1160 
   1161       // Generate a comparison function for this field if it is a key.
   1162       if (field.key) {
   1163         const bool is_string = (field.value.type.base_type == BASE_TYPE_STRING);
   1164 
   1165         code_ += "  bool KeyCompareLessThan(const {{STRUCT_NAME}} *o) const {";
   1166         if (is_string) {
   1167           code_ += "    return *{{FIELD_NAME}}() < *o->{{FIELD_NAME}}();";
   1168         } else {
   1169           code_ += "    return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
   1170         }
   1171         code_ += "  }";
   1172 
   1173         if (is_string) {
   1174           code_ += "  int KeyCompareWithValue(const char *val) const {";
   1175           code_ += "    return strcmp({{FIELD_NAME}}()->c_str(), val);";
   1176           code_ += "  }";
   1177         } else {
   1178           auto type = GenTypeBasic(field.value.type, false);
   1179           if (parser_.opts.scoped_enums && field.value.type.enum_def &&
   1180               IsScalar(field.value.type.base_type)) {
   1181             type = GenTypeGet(field.value.type, " ", "const ", " *", true);
   1182           }
   1183 
   1184           code_.SetValue("KEY_TYPE", type);
   1185           code_ += "  int KeyCompareWithValue({{KEY_TYPE}} val) const {";
   1186           code_ += "    const auto key = {{FIELD_NAME}}();";
   1187           code_ += "    if (key < val) {";
   1188           code_ += "      return -1;";
   1189           code_ += "    } else if (key > val) {";
   1190           code_ += "      return 1;";
   1191           code_ += "    } else {";
   1192           code_ += "      return 0;";
   1193           code_ += "    }";
   1194           code_ += "  }";
   1195         }
   1196       }
   1197     }
   1198 
   1199     // Generate a verifier function that can check a buffer from an untrusted
   1200     // source will never cause reads outside the buffer.
   1201     code_ += "  bool Verify(flatbuffers::Verifier &verifier) const {";
   1202     code_ += "    return VerifyTableStart(verifier)\\";
   1203     for (auto it = struct_def.fields.vec.begin();
   1204          it != struct_def.fields.vec.end(); ++it) {
   1205       const auto &field = **it;
   1206       if (field.deprecated) {
   1207         continue;
   1208       }
   1209       GenVerifyCall(field, " &&\n           ");
   1210     }
   1211 
   1212     code_ += " &&\n           verifier.EndTable();";
   1213     code_ += "  }";
   1214 
   1215     if (parser_.opts.generate_object_based_api) {
   1216       // Generate the UnPack() pre declaration.
   1217       code_ += "  " + TableUnPackSignature(struct_def, true) + ";";
   1218       code_ += "  " + TableUnPackToSignature(struct_def, true) + ";";
   1219       code_ += "  " + TablePackSignature(struct_def, true) + ";";
   1220     }
   1221 
   1222     code_ += "};";  // End of table.
   1223     code_ += "";
   1224 
   1225     GenBuilders(struct_def);
   1226 
   1227     if (parser_.opts.generate_object_based_api) {
   1228       // Generate a pre-declaration for a CreateX method that works with an
   1229       // unpacked C++ object.
   1230       code_ += TableCreateSignature(struct_def, true) + ";";
   1231       code_ += "";
   1232     }
   1233   }
   1234 
   1235   void GenBuilders(const StructDef &struct_def) {
   1236     code_.SetValue("STRUCT_NAME", struct_def.name);
   1237 
   1238     // Generate a builder struct:
   1239     code_ += "struct {{STRUCT_NAME}}Builder {";
   1240     code_ += "  flatbuffers::FlatBufferBuilder &fbb_;";
   1241     code_ += "  flatbuffers::uoffset_t start_;";
   1242 
   1243     bool has_string_or_vector_fields = false;
   1244     for (auto it = struct_def.fields.vec.begin();
   1245          it != struct_def.fields.vec.end(); ++it) {
   1246       const auto &field = **it;
   1247       if (!field.deprecated) {
   1248         const bool is_scalar = IsScalar(field.value.type.base_type);
   1249         const bool is_string = field.value.type.base_type == BASE_TYPE_STRING;
   1250         const bool is_vector = field.value.type.base_type == BASE_TYPE_VECTOR;
   1251         if (is_string || is_vector) {
   1252           has_string_or_vector_fields = true;
   1253         }
   1254 
   1255         std::string offset = GenFieldOffsetName(field);
   1256         std::string name = GenUnderlyingCast(field, false, field.name);
   1257         std::string value = is_scalar ? GenDefaultConstant(field) : "";
   1258 
   1259         // Generate accessor functions of the form:
   1260         // void add_name(type name) {
   1261         //   fbb_.AddElement<type>(offset, name, default);
   1262         // }
   1263         code_.SetValue("FIELD_NAME", field.name);
   1264         code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true));
   1265         code_.SetValue("ADD_OFFSET", struct_def.name + "::" + offset);
   1266         code_.SetValue("ADD_NAME", name);
   1267         code_.SetValue("ADD_VALUE", value);
   1268         if (is_scalar) {
   1269           const auto type = GenTypeWire(field.value.type, "", false);
   1270           code_.SetValue("ADD_FN", "AddElement<" + type + ">");
   1271         } else if (IsStruct(field.value.type)) {
   1272           code_.SetValue("ADD_FN", "AddStruct");
   1273         } else {
   1274           code_.SetValue("ADD_FN", "AddOffset");
   1275         }
   1276 
   1277         code_ += "  void add_{{FIELD_NAME}}({{FIELD_TYPE}}{{FIELD_NAME}}) {";
   1278           code_ += "    fbb_.{{ADD_FN}}(\\";
   1279         if (is_scalar) {
   1280           code_ += "{{ADD_OFFSET}}, {{ADD_NAME}}, {{ADD_VALUE}});";
   1281         } else {
   1282           code_ += "{{ADD_OFFSET}}, {{ADD_NAME}});";
   1283         }
   1284         code_ += "  }";
   1285       }
   1286     }
   1287 
   1288     // Builder constructor
   1289     code_ += "  {{STRUCT_NAME}}Builder(flatbuffers::FlatBufferBuilder &_fbb)";
   1290     code_ += "        : fbb_(_fbb) {";
   1291     code_ += "    start_ = fbb_.StartTable();";
   1292     code_ += "  }";
   1293 
   1294     // Assignment operator;
   1295     code_ += "  {{STRUCT_NAME}}Builder &operator="
   1296              "(const {{STRUCT_NAME}}Builder &);";
   1297 
   1298     // Finish() function.
   1299     auto num_fields = NumToString(struct_def.fields.vec.size());
   1300     code_ += "  flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
   1301     code_ += "    const auto end = fbb_.EndTable(start_, " + num_fields + ");";
   1302     code_ += "    auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);";
   1303 
   1304     for (auto it = struct_def.fields.vec.begin();
   1305          it != struct_def.fields.vec.end(); ++it) {
   1306       const auto &field = **it;
   1307       if (!field.deprecated && field.required) {
   1308         code_.SetValue("FIELD_NAME", field.name);
   1309         code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
   1310         code_ += "    fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});";
   1311       }
   1312     }
   1313     code_ += "    return o;";
   1314     code_ += "  }";
   1315     code_ += "};";
   1316     code_ += "";
   1317 
   1318     // Generate a convenient CreateX function that uses the above builder
   1319     // to create a table in one go.
   1320     code_ += "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
   1321             "Create{{STRUCT_NAME}}(";
   1322     code_ += "    flatbuffers::FlatBufferBuilder &_fbb\\";
   1323     for (auto it = struct_def.fields.vec.begin();
   1324          it != struct_def.fields.vec.end(); ++it) {
   1325       const auto &field = **it;
   1326       if (!field.deprecated) {
   1327         GenParam(field, false, ",\n    ");
   1328       }
   1329     }
   1330     code_ += ") {";
   1331 
   1332     code_ += "  {{STRUCT_NAME}}Builder builder_(_fbb);";
   1333     for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
   1334          size; size /= 2) {
   1335       for (auto it = struct_def.fields.vec.rbegin();
   1336            it != struct_def.fields.vec.rend(); ++it) {
   1337         const auto &field = **it;
   1338         if (!field.deprecated && (!struct_def.sortbysize ||
   1339                                   size == SizeOf(field.value.type.base_type))) {
   1340           code_.SetValue("FIELD_NAME", field.name);
   1341           code_ += "  builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});";
   1342         }
   1343       }
   1344     }
   1345     code_ += "  return builder_.Finish();";
   1346     code_ += "}";
   1347     code_ += "";
   1348 
   1349     // Generate a CreateXDirect function with vector types as parameters
   1350     if (has_string_or_vector_fields) {
   1351       code_ += "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
   1352               "Create{{STRUCT_NAME}}Direct(";
   1353       code_ += "    flatbuffers::FlatBufferBuilder &_fbb\\";
   1354       for (auto it = struct_def.fields.vec.begin();
   1355            it != struct_def.fields.vec.end(); ++it) {
   1356         const auto &field = **it;
   1357         if (!field.deprecated) {
   1358           GenParam(field, true, ",\n    ");
   1359         }
   1360       }
   1361 
   1362       // Need to call "Create" with the struct namespace.
   1363       const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create");
   1364       code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
   1365 
   1366       code_ += ") {";
   1367       code_ += "  return {{CREATE_NAME}}{{STRUCT_NAME}}(";
   1368       code_ += "      _fbb\\";
   1369       for (auto it = struct_def.fields.vec.begin();
   1370            it != struct_def.fields.vec.end(); ++it) {
   1371         const auto &field = **it;
   1372         if (!field.deprecated) {
   1373           code_.SetValue("FIELD_NAME", field.name);
   1374 
   1375           if (field.value.type.base_type == BASE_TYPE_STRING) {
   1376             code_ += ",\n      {{FIELD_NAME}} ? "
   1377                     "_fbb.CreateString({{FIELD_NAME}}) : 0\\";
   1378           } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
   1379             auto type = GenTypeWire(field.value.type.VectorType(), "", false);
   1380             code_ += ",\n      {{FIELD_NAME}} ? "
   1381                     "_fbb.CreateVector<" + type + ">(*{{FIELD_NAME}}) : 0\\";
   1382           } else {
   1383             code_ += ",\n      {{FIELD_NAME}}\\";
   1384           }
   1385         }
   1386       }
   1387       code_ += ");";
   1388       code_ += "}";
   1389       code_ += "";
   1390     }
   1391   }
   1392 
   1393   std::string GenUnpackVal(const Type &type, const std::string &val,
   1394                            bool invector, const FieldDef &afield) {
   1395     switch (type.base_type) {
   1396       case BASE_TYPE_STRING: {
   1397         return val + "->str()";
   1398       }
   1399       case BASE_TYPE_STRUCT: {
   1400         const auto name = WrapInNameSpace(*type.struct_def);
   1401         if (IsStruct(type)) {
   1402           auto native_type = type.struct_def->attributes.Lookup("native_type");
   1403           if (native_type) {
   1404             return "flatbuffers::UnPack(*" + val + ")";
   1405           } else if (invector || afield.native_inline) {
   1406             return "*" + val;
   1407           } else {
   1408             const auto ptype = GenTypeNativePtr(name, &afield, true);
   1409             return ptype + "(new " + name + "(*" + val + "))";
   1410           }
   1411         } else {
   1412           const auto ptype = GenTypeNativePtr(NativeName(name), &afield, true);
   1413           return ptype + "(" + val + "->UnPack(_resolver))";
   1414         }
   1415       }
   1416       default: {
   1417         return val;
   1418         break;
   1419       }
   1420     }
   1421   };
   1422 
   1423   std::string GenUnpackFieldStatement(const FieldDef &field,
   1424                                       const FieldDef *union_field) {
   1425     std::string code;
   1426     switch (field.value.type.base_type) {
   1427       case BASE_TYPE_VECTOR: {
   1428         std::string indexing;
   1429         if (field.value.type.enum_def) {
   1430           indexing += "(" + field.value.type.enum_def->name + ")";
   1431         }
   1432         indexing += "_e->Get(_i)";
   1433         if (field.value.type.element == BASE_TYPE_BOOL) {
   1434           indexing += " != 0";
   1435         }
   1436 
   1437         // Generate code that pushes data from _e to _o in the form:
   1438         //   for (uoffset_t i = 0; i < _e->size(); ++i) {
   1439         //     _o->field.push_back(_e->Get(_i));
   1440         //   }
   1441         code += "for (flatbuffers::uoffset_t _i = 0;";
   1442         code += " _i < _e->size(); _i++) { ";
   1443         code += "_o->" + field.name + ".push_back(";
   1444         code += GenUnpackVal(field.value.type.VectorType(),
   1445                                   indexing, true, field);
   1446         code += "); }";
   1447         break;
   1448       }
   1449       case BASE_TYPE_UTYPE: {
   1450         assert(union_field->value.type.base_type == BASE_TYPE_UNION);
   1451         // Generate code that sets the union type, of the form:
   1452         //   _o->field.type = _e;
   1453         code += "_o->" + union_field->name + ".type = _e;";
   1454         break;
   1455       }
   1456       case BASE_TYPE_UNION: {
   1457         // Generate code that sets the union table, of the form:
   1458         //   _o->field.table = Union::Unpack(_e, field_type(), resolver);
   1459         code += "_o->" + field.name + ".table = ";
   1460         code += field.value.type.enum_def->name + "Union::UnPack(";
   1461         code += "_e, " + field.name + UnionTypeFieldSuffix() + "(),";
   1462         code += "_resolver);";
   1463         break;
   1464       }
   1465       default: {
   1466         auto cpp_type = field.attributes.Lookup("cpp_type");
   1467         if (cpp_type) {
   1468           // Generate code that resolves the cpp pointer type, of the form:
   1469           //  if (resolver)
   1470           //    (*resolver)(&_o->field, (hash_value_t)(_e));
   1471           //  else
   1472           //    _o->field = nullptr;
   1473           code += "if (_resolver) ";
   1474           code += "(*_resolver)";
   1475           code += "(reinterpret_cast<void **>(&_o->" + field.name + "), ";
   1476           code += "static_cast<flatbuffers::hash_value_t>(_e));";
   1477           code += " else ";
   1478           code += "_o->" + field.name + " = nullptr;";
   1479         } else {
   1480           // Generate code for assigning the value, of the form:
   1481           //  _o->field = value;
   1482           code += "_o->" + field.name + " = ";
   1483           code += GenUnpackVal(field.value.type, "_e", false, field) + ";";
   1484         }
   1485         break;
   1486       }
   1487     }
   1488     return code;
   1489   }
   1490 
   1491   std::string GenCreateParam(const FieldDef &field) {
   1492     std::string value = "_o->";
   1493     if (field.value.type.base_type == BASE_TYPE_UTYPE) {
   1494       value += field.name.substr(0, field.name.size() -
   1495                                  strlen(UnionTypeFieldSuffix()));
   1496       value += ".type";
   1497     } else {
   1498       value += field.name;
   1499     }
   1500     if (field.attributes.Lookup("cpp_type")) {
   1501       auto type = GenTypeBasic(field.value.type, false);
   1502       value = "_rehasher ? "
   1503               "static_cast<" + type + ">((*_rehasher)(" + value + ")) : 0";
   1504     }
   1505 
   1506     std::string code;
   1507     switch (field.value.type.base_type) {
   1508       // String fields are of the form:
   1509       //   _fbb.CreateString(_o->field)
   1510       case BASE_TYPE_STRING: {
   1511         code += "_fbb.CreateString(" + value + ")";
   1512 
   1513         // For optional fields, check to see if there actually is any data
   1514         // in _o->field before attempting to access it.
   1515         if (!field.required) {
   1516           code = value + ".size() ? " + code + " : 0";
   1517         }
   1518         break;
   1519       }
   1520       // Vector fields come in several flavours, of the forms:
   1521       //   _fbb.CreateVector(_o->field);
   1522       //   _fbb.CreateVector((const utype*)_o->field.data(), _o->field.size());
   1523       //   _fbb.CreateVectorOfStrings(_o->field)
   1524       //   _fbb.CreateVectorOfStructs(_o->field)
   1525       //   _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) {
   1526       //     return CreateT(_fbb, _o->Get(i), rehasher);
   1527       //   });
   1528       case BASE_TYPE_VECTOR: {
   1529         auto vector_type = field.value.type.VectorType();
   1530         switch (vector_type.base_type) {
   1531           case BASE_TYPE_STRING: {
   1532             code += "_fbb.CreateVectorOfStrings(" + value + ")";
   1533             break;
   1534           }
   1535           case BASE_TYPE_STRUCT: {
   1536             if (IsStruct(vector_type)) {
   1537               code += "_fbb.CreateVectorOfStructs(" + value + ")";
   1538             } else {
   1539               code += "_fbb.CreateVector<flatbuffers::Offset<";
   1540               code += WrapInNameSpace(*vector_type.struct_def) + ">>";
   1541               code += "(" + value + ".size(), [&](size_t i) {";
   1542               code += " return Create" + vector_type.struct_def->name;
   1543               code += "(_fbb, " + value + "[i]" + GenPtrGet(field) + ", ";
   1544               code += "_rehasher); })";
   1545             }
   1546             break;
   1547           }
   1548           case BASE_TYPE_BOOL: {
   1549             code += "_fbb.CreateVector(" + value + ")";
   1550             break;
   1551           }
   1552           default: {
   1553             if (field.value.type.enum_def) {
   1554               // For enumerations, we need to get access to the array data for
   1555               // the underlying storage type (eg. uint8_t).
   1556               const auto basetype = GenTypeBasic(
   1557                   field.value.type.enum_def->underlying_type, false);
   1558               code += "_fbb.CreateVector((const " + basetype + "*)" + value +
   1559                       ".data(), " + value + ".size())";
   1560             } else {
   1561               code += "_fbb.CreateVector(" + value + ")";
   1562             }
   1563             break;
   1564           }
   1565         }
   1566 
   1567         // For optional fields, check to see if there actually is any data
   1568         // in _o->field before attempting to access it.
   1569         if (!field.required) {
   1570           code = value + ".size() ? " + code + " : 0";
   1571         }
   1572         break;
   1573       }
   1574       case BASE_TYPE_UNION: {
   1575         // _o->field.Pack(_fbb);
   1576         code += value + ".Pack(_fbb)";
   1577         break;
   1578       }
   1579       case BASE_TYPE_STRUCT: {
   1580         if (IsStruct(field.value.type)) {
   1581           auto native_type =
   1582               field.value.type.struct_def->attributes.Lookup("native_type");
   1583           if (native_type) {
   1584             code += "flatbuffers::Pack(" + value + ")";
   1585           } else if (field.native_inline) {
   1586             code += "&" + value;
   1587           } else {
   1588             code += value + " ? " + value + GenPtrGet(field) + " : 0";
   1589           }
   1590         } else {
   1591           // _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
   1592           const auto type = field.value.type.struct_def->name;
   1593           code += value + " ? Create" + type;
   1594           code += "(_fbb, " + value + GenPtrGet(field) + ", _rehasher)";
   1595           code += " : 0";
   1596         }
   1597         break;
   1598       }
   1599       default: {
   1600         code += value;
   1601         break;
   1602       }
   1603     }
   1604     return code;
   1605   }
   1606 
   1607   // Generate code for tables that needs to come after the regular definition.
   1608   void GenTablePost(const StructDef &struct_def) {
   1609     code_.SetValue("STRUCT_NAME", struct_def.name);
   1610     code_.SetValue("NATIVE_NAME", NativeName(struct_def.name));
   1611 
   1612     if (parser_.opts.generate_object_based_api) {
   1613       // Generate the X::UnPack() method.
   1614       code_ += "inline " + TableUnPackSignature(struct_def, false) + " {";
   1615       code_ += "  auto _o = new {{NATIVE_NAME}}();";
   1616       code_ += "  UnPackTo(_o, _resolver);";
   1617       code_ += "  return _o;";
   1618       code_ += "}";
   1619       code_ += "";
   1620 
   1621       code_ += "inline " + TableUnPackToSignature(struct_def, false) + " {";
   1622       code_ += "  (void)_o;";
   1623       code_ += "  (void)_resolver;";
   1624 
   1625       for (auto it = struct_def.fields.vec.begin();
   1626            it != struct_def.fields.vec.end(); ++it) {
   1627         const auto &field = **it;
   1628         if (field.deprecated) {
   1629           continue;
   1630         }
   1631 
   1632         // Assign a value from |this| to |_o|.   Values from |this| are stored
   1633         // in a variable |_e| by calling this->field_type().  The value is then
   1634         // assigned to |_o| using the GenUnpackFieldStatement.
   1635         const bool is_union = field.value.type.base_type == BASE_TYPE_UTYPE;
   1636         const auto statement =
   1637             GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr);
   1638 
   1639         code_.SetValue("FIELD_NAME", field.name);
   1640         auto prefix = "  { auto _e = {{FIELD_NAME}}(); ";
   1641         auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) ";
   1642         auto postfix = " };";
   1643         code_ += std::string(prefix) + check + statement + postfix;
   1644       }
   1645       code_ += "}";
   1646       code_ += "";
   1647 
   1648       // Generate the X::Pack member function that simply calls the global
   1649       // CreateX function.
   1650       code_ += "inline " + TablePackSignature(struct_def, false) + " {";
   1651       code_ += "  return Create{{STRUCT_NAME}}(_fbb, _o, _rehasher);";
   1652       code_ += "}";
   1653       code_ += "";
   1654 
   1655       // Generate a CreateX method that works with an unpacked C++ object.
   1656       code_ += "inline " + TableCreateSignature(struct_def, false) + " {";
   1657       code_ += "  (void)_rehasher;";
   1658       code_ += "  (void)_o;";
   1659 
   1660       for (auto it = struct_def.fields.vec.begin();
   1661            it != struct_def.fields.vec.end(); ++it) {
   1662         auto &field = **it;
   1663         if (field.deprecated) {
   1664           continue;
   1665         }
   1666         code_ += "  auto _" + field.name + " = " + GenCreateParam(field) + ";";
   1667       }
   1668       // Need to call "Create" with the struct namespace.
   1669       const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create");
   1670       code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
   1671 
   1672       code_ += "  return {{CREATE_NAME}}{{STRUCT_NAME}}(";
   1673       code_ += "      _fbb\\";
   1674       for (auto it = struct_def.fields.vec.begin();
   1675            it != struct_def.fields.vec.end(); ++it) {
   1676         auto &field = **it;
   1677         if (field.deprecated) {
   1678           continue;
   1679         }
   1680 
   1681         bool pass_by_address = false;
   1682         if (field.value.type.base_type == BASE_TYPE_STRUCT) {
   1683           if (IsStruct(field.value.type)) {
   1684             auto native_type =
   1685                 field.value.type.struct_def->attributes.Lookup("native_type");
   1686             if (native_type) {
   1687               pass_by_address = true;
   1688             }
   1689           }
   1690         }
   1691 
   1692         // Call the CreateX function using values from |_o|.
   1693         if (pass_by_address) {
   1694           code_ += ",\n      &_" + field.name + "\\";
   1695         } else {
   1696           code_ += ",\n      _" + field.name + "\\";
   1697         }
   1698       }
   1699       code_ += ");";
   1700       code_ += "}";
   1701       code_ += "";
   1702     }
   1703   }
   1704 
   1705   static void GenPadding(
   1706       const FieldDef &field, std::string *code_ptr, int *id,
   1707       const std::function<void(int bits, std::string *code_ptr, int *id)> &f) {
   1708     if (field.padding) {
   1709       for (int i = 0; i < 4; i++) {
   1710         if (static_cast<int>(field.padding) & (1 << i)) {
   1711           f((1 << i) * 8, code_ptr, id);
   1712         }
   1713       }
   1714       assert(!(field.padding & ~0xF));
   1715     }
   1716   }
   1717 
   1718   static void PaddingDefinition(int bits, std::string *code_ptr, int *id) {
   1719     *code_ptr += "  int" + NumToString(bits) + "_t padding" +
   1720         NumToString((*id)++) + "__;";
   1721   }
   1722 
   1723   static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
   1724     (void)bits;
   1725     *code_ptr += ",\n        padding" + NumToString((*id)++) + "__(0)";
   1726   }
   1727 
   1728   static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
   1729     (void)bits;
   1730     *code_ptr += "    (void)padding" + NumToString((*id)++) + "__;";
   1731   }
   1732 
   1733   // Generate an accessor struct with constructor for a flatbuffers struct.
   1734   void GenStruct(const StructDef &struct_def) {
   1735     // Generate an accessor struct, with private variables of the form:
   1736     // type name_;
   1737     // Generates manual padding and alignment.
   1738     // Variables are private because they contain little endian data on all
   1739     // platforms.
   1740     GenComment(struct_def.doc_comment);
   1741     code_.SetValue("ALIGN", NumToString(struct_def.minalign));
   1742     code_.SetValue("STRUCT_NAME", struct_def.name);
   1743 
   1744     code_ += "MANUALLY_ALIGNED_STRUCT({{ALIGN}}) "
   1745             "{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {";
   1746     code_ += " private:";
   1747 
   1748     int padding_id = 0;
   1749     for (auto it = struct_def.fields.vec.begin();
   1750          it != struct_def.fields.vec.end(); ++it) {
   1751       const auto &field = **it;
   1752       code_.SetValue("FIELD_TYPE",
   1753           GenTypeGet(field.value.type, " ", "", " ", false));
   1754       code_.SetValue("FIELD_NAME", field.name);
   1755       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}_;";
   1756 
   1757       if (field.padding) {
   1758         std::string padding;
   1759         GenPadding(field, &padding, &padding_id, PaddingDefinition);
   1760         code_ += padding;
   1761       }
   1762     }
   1763 
   1764     // Generate GetFullyQualifiedName
   1765     code_ += "";
   1766     code_ += " public:";
   1767     GenFullyQualifiedNameGetter(struct_def.name);
   1768 
   1769     // Generate a default constructor.
   1770     code_ += "  {{STRUCT_NAME}}() {";
   1771     code_ += "    memset(this, 0, sizeof({{STRUCT_NAME}}));";
   1772     code_ += "  }";
   1773 
   1774     // Generate a copy constructor.
   1775     code_ += "  {{STRUCT_NAME}}(const {{STRUCT_NAME}} &_o) {";
   1776     code_ += "    memcpy(this, &_o, sizeof({{STRUCT_NAME}}));";
   1777     code_ += "  }";
   1778 
   1779     // Generate a constructor that takes all fields as arguments.
   1780     std::string arg_list;
   1781     std::string init_list;
   1782     padding_id = 0;
   1783     for (auto it = struct_def.fields.vec.begin();
   1784          it != struct_def.fields.vec.end(); ++it) {
   1785       const auto &field = **it;
   1786       const auto member_name = field.name + "_";
   1787       const auto arg_name = "_" + field.name;
   1788       const auto arg_type =
   1789           GenTypeGet(field.value.type, " ", "const ", " &", true);
   1790 
   1791       if (it != struct_def.fields.vec.begin()) {
   1792         arg_list += ", ";
   1793         init_list += ",\n        ";
   1794       }
   1795       arg_list += arg_type;
   1796       arg_list += arg_name;
   1797       init_list += member_name;
   1798       if (IsScalar(field.value.type.base_type)) {
   1799         auto type = GenUnderlyingCast(field, false, arg_name);
   1800         init_list += "(flatbuffers::EndianScalar(" + type + "))";
   1801       } else {
   1802         init_list += "(" + arg_name + ")";
   1803       }
   1804       if (field.padding) {
   1805         GenPadding(field, &init_list, &padding_id, PaddingInitializer);
   1806       }
   1807     }
   1808 
   1809     code_.SetValue("ARG_LIST", arg_list);
   1810     code_.SetValue("INIT_LIST", init_list);
   1811     code_ += "  {{STRUCT_NAME}}({{ARG_LIST}})";
   1812     code_ += "      : {{INIT_LIST}} {";
   1813     padding_id = 0;
   1814     for (auto it = struct_def.fields.vec.begin();
   1815          it != struct_def.fields.vec.end(); ++it) {
   1816       const auto &field = **it;
   1817       if (field.padding) {
   1818         std::string padding;
   1819         GenPadding(field, &padding, &padding_id, PaddingNoop);
   1820         code_ += padding;
   1821       }
   1822     }
   1823     code_ += "  }";
   1824 
   1825     // Generate accessor methods of the form:
   1826     // type name() const { return flatbuffers::EndianScalar(name_); }
   1827     for (auto it = struct_def.fields.vec.begin();
   1828          it != struct_def.fields.vec.end(); ++it) {
   1829       const auto &field = **it;
   1830 
   1831       auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true);
   1832       auto is_scalar = IsScalar(field.value.type.base_type);
   1833       auto member = field.name + "_";
   1834       auto value = is_scalar ? "flatbuffers::EndianScalar(" + member + ")"
   1835                              : member;
   1836 
   1837       code_.SetValue("FIELD_NAME", field.name);
   1838       code_.SetValue("FIELD_TYPE", field_type);
   1839       code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
   1840 
   1841       GenComment(field.doc_comment, "  ");
   1842       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
   1843       code_ += "    return {{FIELD_VALUE}};";
   1844       code_ += "  }";
   1845 
   1846       if (parser_.opts.mutable_buffer) {
   1847         if (is_scalar) {
   1848           code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
   1849           code_.SetValue("FIELD_VALUE",
   1850                         GenUnderlyingCast(field, false, "_" + field.name));
   1851 
   1852           code_ += "  void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {";
   1853           code_ += "    flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
   1854                   "{{FIELD_VALUE}});";
   1855           code_ += "  }";
   1856         } else {
   1857           code_ += "  {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
   1858           code_ += "    return {{FIELD_NAME}}_;";
   1859           code_ += "  }";
   1860         }
   1861       }
   1862     }
   1863     code_ += "};";
   1864 
   1865     code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
   1866     code_ += "STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
   1867     code_ += "";
   1868   }
   1869 
   1870   // Set up the correct namespace. Only open a namespace if the existing one is
   1871   // different (closing/opening only what is necessary).
   1872   //
   1873   // The file must start and end with an empty (or null) namespace so that
   1874   // namespaces are properly opened and closed.
   1875   void SetNameSpace(const Namespace *ns) {
   1876     if (cur_name_space_ == ns) {
   1877       return;
   1878     }
   1879 
   1880     // Compute the size of the longest common namespace prefix.
   1881     // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
   1882     // the common prefix is A::B:: and we have old_size = 4, new_size = 5
   1883     // and common_prefix_size = 2
   1884     size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
   1885     size_t new_size = ns ? ns->components.size() : 0;
   1886 
   1887     size_t common_prefix_size = 0;
   1888     while (common_prefix_size < old_size && common_prefix_size < new_size &&
   1889            ns->components[common_prefix_size] ==
   1890                cur_name_space_->components[common_prefix_size]) {
   1891       common_prefix_size++;
   1892     }
   1893 
   1894     // Close cur_name_space in reverse order to reach the common prefix.
   1895     // In the previous example, D then C are closed.
   1896     for (size_t j = old_size; j > common_prefix_size; --j) {
   1897       code_ += "}  // namespace " + cur_name_space_->components[j - 1];
   1898     }
   1899     if (old_size != common_prefix_size) {
   1900       code_ += "";
   1901     }
   1902 
   1903     // open namespace parts to reach the ns namespace
   1904     // in the previous example, E, then F, then G are opened
   1905     for (auto j = common_prefix_size; j != new_size; ++j) {
   1906       code_ += "namespace " + ns->components[j] + " {";
   1907     }
   1908     if (new_size != common_prefix_size) {
   1909       code_ += "";
   1910     }
   1911 
   1912     cur_name_space_ = ns;
   1913   }
   1914 };
   1915 
   1916 }  // namespace cpp
   1917 
   1918 bool GenerateCPP(const Parser &parser, const std::string &path,
   1919                  const std::string &file_name) {
   1920   cpp::CppGenerator generator(parser, path, file_name);
   1921   return generator.generate();
   1922 }
   1923 
   1924 std::string CPPMakeRule(const Parser &parser, const std::string &path,
   1925                         const std::string &file_name) {
   1926   const auto filebase =
   1927       flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
   1928   const auto included_files = parser.GetIncludedFilesRecursive(file_name);
   1929   std::string make_rule = GeneratedFileName(path, filebase) + ": ";
   1930   for (auto it = included_files.begin(); it != included_files.end(); ++it) {
   1931     make_rule += " " + *it;
   1932   }
   1933   return make_rule;
   1934 }
   1935 
   1936 }  // namespace flatbuffers
   1937