xref: /aosp_15_r20/external/flatbuffers/src/idl_gen_cpp.cpp (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker  * Copyright 2014 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker  *
4*890232f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker  *
8*890232f2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker  *
10*890232f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker  * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker  */
16*890232f2SAndroid Build Coastguard Worker 
17*890232f2SAndroid Build Coastguard Worker // independent from idl_parser, since this code is not needed for most clients
18*890232f2SAndroid Build Coastguard Worker 
19*890232f2SAndroid Build Coastguard Worker #include <string>
20*890232f2SAndroid Build Coastguard Worker #include <unordered_set>
21*890232f2SAndroid Build Coastguard Worker 
22*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/base.h"
23*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/code_generators.h"
24*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/flatbuffers.h"
25*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/flatc.h"
26*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/idl.h"
27*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/util.h"
28*890232f2SAndroid Build Coastguard Worker 
29*890232f2SAndroid Build Coastguard Worker #ifndef FLATBUFFERS_CPP_OBJECT_UNPACKTO
30*890232f2SAndroid Build Coastguard Worker #define FLATBUFFERS_CPP_OBJECT_UNPACKTO 0
31*890232f2SAndroid Build Coastguard Worker #endif
32*890232f2SAndroid Build Coastguard Worker 
33*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
34*890232f2SAndroid Build Coastguard Worker 
35*890232f2SAndroid Build Coastguard Worker // Make numerical literal with type-suffix.
36*890232f2SAndroid Build Coastguard Worker // This function is only needed for C++! Other languages do not need it.
NumToStringCpp(std::string val,BaseType type)37*890232f2SAndroid Build Coastguard Worker static inline std::string NumToStringCpp(std::string val, BaseType type) {
38*890232f2SAndroid Build Coastguard Worker   // Avoid issues with -2147483648, -9223372036854775808.
39*890232f2SAndroid Build Coastguard Worker   switch (type) {
40*890232f2SAndroid Build Coastguard Worker     case BASE_TYPE_INT:
41*890232f2SAndroid Build Coastguard Worker       return (val != "-2147483648") ? val : ("(-2147483647 - 1)");
42*890232f2SAndroid Build Coastguard Worker     case BASE_TYPE_ULONG: return (val == "0") ? val : (val + "ULL");
43*890232f2SAndroid Build Coastguard Worker     case BASE_TYPE_LONG:
44*890232f2SAndroid Build Coastguard Worker       if (val == "-9223372036854775808")
45*890232f2SAndroid Build Coastguard Worker         return "(-9223372036854775807LL - 1LL)";
46*890232f2SAndroid Build Coastguard Worker       else
47*890232f2SAndroid Build Coastguard Worker         return (val == "0") ? val : (val + "LL");
48*890232f2SAndroid Build Coastguard Worker     default: return val;
49*890232f2SAndroid Build Coastguard Worker   }
50*890232f2SAndroid Build Coastguard Worker }
51*890232f2SAndroid Build Coastguard Worker 
GenIncludeGuard(const std::string & file_name,const Namespace & name_space,const std::string & postfix="")52*890232f2SAndroid Build Coastguard Worker static std::string GenIncludeGuard(const std::string &file_name,
53*890232f2SAndroid Build Coastguard Worker                                    const Namespace &name_space,
54*890232f2SAndroid Build Coastguard Worker                                    const std::string &postfix = "") {
55*890232f2SAndroid Build Coastguard Worker   // Generate include guard.
56*890232f2SAndroid Build Coastguard Worker   std::string guard = file_name;
57*890232f2SAndroid Build Coastguard Worker   // Remove any non-alpha-numeric characters that may appear in a filename.
58*890232f2SAndroid Build Coastguard Worker   struct IsAlnum {
59*890232f2SAndroid Build Coastguard Worker     bool operator()(char c) const { return !is_alnum(c); }
60*890232f2SAndroid Build Coastguard Worker   };
61*890232f2SAndroid Build Coastguard Worker   guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()),
62*890232f2SAndroid Build Coastguard Worker               guard.end());
63*890232f2SAndroid Build Coastguard Worker   guard = "FLATBUFFERS_GENERATED_" + guard;
64*890232f2SAndroid Build Coastguard Worker   guard += "_";
65*890232f2SAndroid Build Coastguard Worker   // For further uniqueness, also add the namespace.
66*890232f2SAndroid Build Coastguard Worker   for (auto it = name_space.components.begin();
67*890232f2SAndroid Build Coastguard Worker        it != name_space.components.end(); ++it) {
68*890232f2SAndroid Build Coastguard Worker     guard += *it + "_";
69*890232f2SAndroid Build Coastguard Worker   }
70*890232f2SAndroid Build Coastguard Worker   // Anything extra to add to the guard?
71*890232f2SAndroid Build Coastguard Worker   if (!postfix.empty()) { guard += postfix + "_"; }
72*890232f2SAndroid Build Coastguard Worker   guard += "H_";
73*890232f2SAndroid Build Coastguard Worker   std::transform(guard.begin(), guard.end(), guard.begin(), CharToUpper);
74*890232f2SAndroid Build Coastguard Worker   return guard;
75*890232f2SAndroid Build Coastguard Worker }
76*890232f2SAndroid Build Coastguard Worker 
77*890232f2SAndroid Build Coastguard Worker namespace cpp {
78*890232f2SAndroid Build Coastguard Worker 
79*890232f2SAndroid Build Coastguard Worker enum CppStandard { CPP_STD_X0 = 0, CPP_STD_11, CPP_STD_17 };
80*890232f2SAndroid Build Coastguard Worker 
81*890232f2SAndroid Build Coastguard Worker // Define a style of 'struct' constructor if it has 'Array' fields.
82*890232f2SAndroid Build Coastguard Worker enum GenArrayArgMode {
83*890232f2SAndroid Build Coastguard Worker   kArrayArgModeNone,        // don't generate initialization args
84*890232f2SAndroid Build Coastguard Worker   kArrayArgModeSpanStatic,  // generate flatbuffers::span<T,N>
85*890232f2SAndroid Build Coastguard Worker };
86*890232f2SAndroid Build Coastguard Worker 
87*890232f2SAndroid Build Coastguard Worker // Extension of IDLOptions for cpp-generator.
88*890232f2SAndroid Build Coastguard Worker struct IDLOptionsCpp : public IDLOptions {
89*890232f2SAndroid Build Coastguard Worker   // All fields start with 'g_' prefix to distinguish from the base IDLOptions.
90*890232f2SAndroid Build Coastguard Worker   CppStandard g_cpp_std;    // Base version of C++ standard.
91*890232f2SAndroid Build Coastguard Worker   bool g_only_fixed_enums;  // Generate underlaying type for all enums.
92*890232f2SAndroid Build Coastguard Worker 
IDLOptionsCppflatbuffers::cpp::IDLOptionsCpp93*890232f2SAndroid Build Coastguard Worker   IDLOptionsCpp(const IDLOptions &opts)
94*890232f2SAndroid Build Coastguard Worker       : IDLOptions(opts), g_cpp_std(CPP_STD_11), g_only_fixed_enums(true) {}
95*890232f2SAndroid Build Coastguard Worker };
96*890232f2SAndroid Build Coastguard Worker 
97*890232f2SAndroid Build Coastguard Worker class CppGenerator : public BaseGenerator {
98*890232f2SAndroid Build Coastguard Worker  public:
CppGenerator(const Parser & parser,const std::string & path,const std::string & file_name,IDLOptionsCpp opts)99*890232f2SAndroid Build Coastguard Worker   CppGenerator(const Parser &parser, const std::string &path,
100*890232f2SAndroid Build Coastguard Worker                const std::string &file_name, IDLOptionsCpp opts)
101*890232f2SAndroid Build Coastguard Worker       : BaseGenerator(parser, path, file_name, "", "::", "h"),
102*890232f2SAndroid Build Coastguard Worker         cur_name_space_(nullptr),
103*890232f2SAndroid Build Coastguard Worker         opts_(opts),
104*890232f2SAndroid Build Coastguard Worker         float_const_gen_("std::numeric_limits<double>::",
105*890232f2SAndroid Build Coastguard Worker                          "std::numeric_limits<float>::", "quiet_NaN()",
106*890232f2SAndroid Build Coastguard Worker                          "infinity()") {
107*890232f2SAndroid Build Coastguard Worker     static const char *const keywords[] = {
108*890232f2SAndroid Build Coastguard Worker       "alignas",
109*890232f2SAndroid Build Coastguard Worker       "alignof",
110*890232f2SAndroid Build Coastguard Worker       "and",
111*890232f2SAndroid Build Coastguard Worker       "and_eq",
112*890232f2SAndroid Build Coastguard Worker       "asm",
113*890232f2SAndroid Build Coastguard Worker       "atomic_cancel",
114*890232f2SAndroid Build Coastguard Worker       "atomic_commit",
115*890232f2SAndroid Build Coastguard Worker       "atomic_noexcept",
116*890232f2SAndroid Build Coastguard Worker       "auto",
117*890232f2SAndroid Build Coastguard Worker       "bitand",
118*890232f2SAndroid Build Coastguard Worker       "bitor",
119*890232f2SAndroid Build Coastguard Worker       "bool",
120*890232f2SAndroid Build Coastguard Worker       "break",
121*890232f2SAndroid Build Coastguard Worker       "case",
122*890232f2SAndroid Build Coastguard Worker       "catch",
123*890232f2SAndroid Build Coastguard Worker       "char",
124*890232f2SAndroid Build Coastguard Worker       "char16_t",
125*890232f2SAndroid Build Coastguard Worker       "char32_t",
126*890232f2SAndroid Build Coastguard Worker       "class",
127*890232f2SAndroid Build Coastguard Worker       "compl",
128*890232f2SAndroid Build Coastguard Worker       "concept",
129*890232f2SAndroid Build Coastguard Worker       "const",
130*890232f2SAndroid Build Coastguard Worker       "constexpr",
131*890232f2SAndroid Build Coastguard Worker       "const_cast",
132*890232f2SAndroid Build Coastguard Worker       "continue",
133*890232f2SAndroid Build Coastguard Worker       "co_await",
134*890232f2SAndroid Build Coastguard Worker       "co_return",
135*890232f2SAndroid Build Coastguard Worker       "co_yield",
136*890232f2SAndroid Build Coastguard Worker       "decltype",
137*890232f2SAndroid Build Coastguard Worker       "default",
138*890232f2SAndroid Build Coastguard Worker       "delete",
139*890232f2SAndroid Build Coastguard Worker       "do",
140*890232f2SAndroid Build Coastguard Worker       "double",
141*890232f2SAndroid Build Coastguard Worker       "dynamic_cast",
142*890232f2SAndroid Build Coastguard Worker       "else",
143*890232f2SAndroid Build Coastguard Worker       "enum",
144*890232f2SAndroid Build Coastguard Worker       "explicit",
145*890232f2SAndroid Build Coastguard Worker       "export",
146*890232f2SAndroid Build Coastguard Worker       "extern",
147*890232f2SAndroid Build Coastguard Worker       "false",
148*890232f2SAndroid Build Coastguard Worker       "float",
149*890232f2SAndroid Build Coastguard Worker       "for",
150*890232f2SAndroid Build Coastguard Worker       "friend",
151*890232f2SAndroid Build Coastguard Worker       "goto",
152*890232f2SAndroid Build Coastguard Worker       "if",
153*890232f2SAndroid Build Coastguard Worker       "import",
154*890232f2SAndroid Build Coastguard Worker       "inline",
155*890232f2SAndroid Build Coastguard Worker       "int",
156*890232f2SAndroid Build Coastguard Worker       "long",
157*890232f2SAndroid Build Coastguard Worker       "module",
158*890232f2SAndroid Build Coastguard Worker       "mutable",
159*890232f2SAndroid Build Coastguard Worker       "namespace",
160*890232f2SAndroid Build Coastguard Worker       "new",
161*890232f2SAndroid Build Coastguard Worker       "noexcept",
162*890232f2SAndroid Build Coastguard Worker       "not",
163*890232f2SAndroid Build Coastguard Worker       "not_eq",
164*890232f2SAndroid Build Coastguard Worker       "nullptr",
165*890232f2SAndroid Build Coastguard Worker       "operator",
166*890232f2SAndroid Build Coastguard Worker       "or",
167*890232f2SAndroid Build Coastguard Worker       "or_eq",
168*890232f2SAndroid Build Coastguard Worker       "private",
169*890232f2SAndroid Build Coastguard Worker       "protected",
170*890232f2SAndroid Build Coastguard Worker       "public",
171*890232f2SAndroid Build Coastguard Worker       "register",
172*890232f2SAndroid Build Coastguard Worker       "reinterpret_cast",
173*890232f2SAndroid Build Coastguard Worker       "requires",
174*890232f2SAndroid Build Coastguard Worker       "return",
175*890232f2SAndroid Build Coastguard Worker       "short",
176*890232f2SAndroid Build Coastguard Worker       "signed",
177*890232f2SAndroid Build Coastguard Worker       "sizeof",
178*890232f2SAndroid Build Coastguard Worker       "static",
179*890232f2SAndroid Build Coastguard Worker       "static_assert",
180*890232f2SAndroid Build Coastguard Worker       "static_cast",
181*890232f2SAndroid Build Coastguard Worker       "struct",
182*890232f2SAndroid Build Coastguard Worker       "switch",
183*890232f2SAndroid Build Coastguard Worker       "synchronized",
184*890232f2SAndroid Build Coastguard Worker       "template",
185*890232f2SAndroid Build Coastguard Worker       "this",
186*890232f2SAndroid Build Coastguard Worker       "thread_local",
187*890232f2SAndroid Build Coastguard Worker       "throw",
188*890232f2SAndroid Build Coastguard Worker       "true",
189*890232f2SAndroid Build Coastguard Worker       "try",
190*890232f2SAndroid Build Coastguard Worker       "typedef",
191*890232f2SAndroid Build Coastguard Worker       "typeid",
192*890232f2SAndroid Build Coastguard Worker       "typename",
193*890232f2SAndroid Build Coastguard Worker       "union",
194*890232f2SAndroid Build Coastguard Worker       "unsigned",
195*890232f2SAndroid Build Coastguard Worker       "using",
196*890232f2SAndroid Build Coastguard Worker       "virtual",
197*890232f2SAndroid Build Coastguard Worker       "void",
198*890232f2SAndroid Build Coastguard Worker       "volatile",
199*890232f2SAndroid Build Coastguard Worker       "wchar_t",
200*890232f2SAndroid Build Coastguard Worker       "while",
201*890232f2SAndroid Build Coastguard Worker       "xor",
202*890232f2SAndroid Build Coastguard Worker       "xor_eq",
203*890232f2SAndroid Build Coastguard Worker       nullptr,
204*890232f2SAndroid Build Coastguard Worker     };
205*890232f2SAndroid Build Coastguard Worker     for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
206*890232f2SAndroid Build Coastguard Worker   }
207*890232f2SAndroid Build Coastguard Worker 
208*890232f2SAndroid Build Coastguard Worker   // Adds code to check that the included flatbuffers.h is of the same version
209*890232f2SAndroid Build Coastguard Worker   // as the generated code. This check currently looks for exact version match,
210*890232f2SAndroid Build Coastguard Worker   // as we would guarantee that they are compatible, but in theory a newer
211*890232f2SAndroid Build Coastguard Worker   // version of flatbuffers.h should work with a old code gen if we do proper
212*890232f2SAndroid Build Coastguard Worker   // backwards support.
GenFlatbuffersVersionCheck()213*890232f2SAndroid Build Coastguard Worker   void GenFlatbuffersVersionCheck() {
214*890232f2SAndroid Build Coastguard Worker     code_ +=
215*890232f2SAndroid Build Coastguard Worker         "// Ensure the included flatbuffers.h is the same version as when this "
216*890232f2SAndroid Build Coastguard Worker         "file was";
217*890232f2SAndroid Build Coastguard Worker     code_ += "// generated, otherwise it may not be compatible.";
218*890232f2SAndroid Build Coastguard Worker     code_ += "static_assert(FLATBUFFERS_VERSION_MAJOR == " +
219*890232f2SAndroid Build Coastguard Worker              std::to_string(FLATBUFFERS_VERSION_MAJOR) + " &&";
220*890232f2SAndroid Build Coastguard Worker     code_ += "              FLATBUFFERS_VERSION_MINOR == " +
221*890232f2SAndroid Build Coastguard Worker              std::to_string(FLATBUFFERS_VERSION_MINOR) + " &&";
222*890232f2SAndroid Build Coastguard Worker     code_ += "              FLATBUFFERS_VERSION_REVISION == " +
223*890232f2SAndroid Build Coastguard Worker              std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
224*890232f2SAndroid Build Coastguard Worker     code_ += "             \"Non-compatible flatbuffers version included\");";
225*890232f2SAndroid Build Coastguard Worker   }
226*890232f2SAndroid Build Coastguard Worker 
GenIncludeDependencies()227*890232f2SAndroid Build Coastguard Worker   void GenIncludeDependencies() {
228*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) {
229*890232f2SAndroid Build Coastguard Worker       for (auto it = parser_.native_included_files_.begin();
230*890232f2SAndroid Build Coastguard Worker            it != parser_.native_included_files_.end(); ++it) {
231*890232f2SAndroid Build Coastguard Worker         code_ += "#include \"" + *it + "\"";
232*890232f2SAndroid Build Coastguard Worker       }
233*890232f2SAndroid Build Coastguard Worker     }
234*890232f2SAndroid Build Coastguard Worker 
235*890232f2SAndroid Build Coastguard Worker     // Get the directly included file of the file being parsed.
236*890232f2SAndroid Build Coastguard Worker     std::vector<IncludedFile> included_files(parser_.GetIncludedFiles());
237*890232f2SAndroid Build Coastguard Worker 
238*890232f2SAndroid Build Coastguard Worker     // We are safe to sort them alphabetically, since there shouldn't be any
239*890232f2SAndroid Build Coastguard Worker     // interdependence between them.
240*890232f2SAndroid Build Coastguard Worker     std::stable_sort(included_files.begin(), included_files.end());
241*890232f2SAndroid Build Coastguard Worker 
242*890232f2SAndroid Build Coastguard Worker     for (const IncludedFile &included_file : included_files) {
243*890232f2SAndroid Build Coastguard Worker       // Get the name of the included file as defined by the schema, and strip
244*890232f2SAndroid Build Coastguard Worker       // the .fbs extension.
245*890232f2SAndroid Build Coastguard Worker       const std::string name_without_ext =
246*890232f2SAndroid Build Coastguard Worker           flatbuffers::StripExtension(included_file.schema_name);
247*890232f2SAndroid Build Coastguard Worker 
248*890232f2SAndroid Build Coastguard Worker       // If we are told to keep the prefix of the included schema, leave it
249*890232f2SAndroid Build Coastguard Worker       // unchanged, otherwise strip the leading path off so just the "basename"
250*890232f2SAndroid Build Coastguard Worker       // of the include is retained.
251*890232f2SAndroid Build Coastguard Worker       const std::string basename =
252*890232f2SAndroid Build Coastguard Worker           opts_.keep_prefix ? name_without_ext
253*890232f2SAndroid Build Coastguard Worker                             : flatbuffers::StripPath(name_without_ext);
254*890232f2SAndroid Build Coastguard Worker 
255*890232f2SAndroid Build Coastguard Worker       code_ += "#include \"" +
256*890232f2SAndroid Build Coastguard Worker                GeneratedFileName(opts_.include_prefix, basename, opts_) + "\"";
257*890232f2SAndroid Build Coastguard Worker     }
258*890232f2SAndroid Build Coastguard Worker 
259*890232f2SAndroid Build Coastguard Worker     if (!parser_.native_included_files_.empty() || !included_files.empty()) {
260*890232f2SAndroid Build Coastguard Worker       code_ += "";
261*890232f2SAndroid Build Coastguard Worker     }
262*890232f2SAndroid Build Coastguard Worker   }
263*890232f2SAndroid Build Coastguard Worker 
GenExtraIncludes()264*890232f2SAndroid Build Coastguard Worker   void GenExtraIncludes() {
265*890232f2SAndroid Build Coastguard Worker     for (std::size_t i = 0; i < opts_.cpp_includes.size(); ++i) {
266*890232f2SAndroid Build Coastguard Worker       code_ += "#include \"" + opts_.cpp_includes[i] + "\"";
267*890232f2SAndroid Build Coastguard Worker     }
268*890232f2SAndroid Build Coastguard Worker     if (!opts_.cpp_includes.empty()) { code_ += ""; }
269*890232f2SAndroid Build Coastguard Worker   }
270*890232f2SAndroid Build Coastguard Worker 
EscapeKeyword(const std::string & name) const271*890232f2SAndroid Build Coastguard Worker   std::string EscapeKeyword(const std::string &name) const {
272*890232f2SAndroid Build Coastguard Worker     return keywords_.find(name) == keywords_.end() ? name : name + "_";
273*890232f2SAndroid Build Coastguard Worker   }
274*890232f2SAndroid Build Coastguard Worker 
Name(const FieldDef & field) const275*890232f2SAndroid Build Coastguard Worker   std::string Name(const FieldDef &field) const {
276*890232f2SAndroid Build Coastguard Worker     // the union type field suffix is immutable.
277*890232f2SAndroid Build Coastguard Worker     static size_t union_suffix_len = strlen(UnionTypeFieldSuffix());
278*890232f2SAndroid Build Coastguard Worker     const bool is_union_type = field.value.type.base_type == BASE_TYPE_UTYPE;
279*890232f2SAndroid Build Coastguard Worker     // early return if no case transformation required
280*890232f2SAndroid Build Coastguard Worker     if (opts_.cpp_object_api_field_case_style ==
281*890232f2SAndroid Build Coastguard Worker         IDLOptions::CaseStyle_Unchanged)
282*890232f2SAndroid Build Coastguard Worker       return EscapeKeyword(field.name);
283*890232f2SAndroid Build Coastguard Worker     std::string name = field.name;
284*890232f2SAndroid Build Coastguard Worker     // do not change the case style of the union type field suffix
285*890232f2SAndroid Build Coastguard Worker     if (is_union_type) {
286*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(name.length() > union_suffix_len);
287*890232f2SAndroid Build Coastguard Worker       name.erase(name.length() - union_suffix_len, union_suffix_len);
288*890232f2SAndroid Build Coastguard Worker     }
289*890232f2SAndroid Build Coastguard Worker     if (opts_.cpp_object_api_field_case_style == IDLOptions::CaseStyle_Upper)
290*890232f2SAndroid Build Coastguard Worker       name = ConvertCase(name, Case::kUpperCamel);
291*890232f2SAndroid Build Coastguard Worker     else if (opts_.cpp_object_api_field_case_style ==
292*890232f2SAndroid Build Coastguard Worker              IDLOptions::CaseStyle_Lower)
293*890232f2SAndroid Build Coastguard Worker       name = ConvertCase(name, Case::kLowerCamel);
294*890232f2SAndroid Build Coastguard Worker     // restore the union field type suffix
295*890232f2SAndroid Build Coastguard Worker     if (is_union_type) name.append(UnionTypeFieldSuffix(), union_suffix_len);
296*890232f2SAndroid Build Coastguard Worker     return EscapeKeyword(name);
297*890232f2SAndroid Build Coastguard Worker   }
298*890232f2SAndroid Build Coastguard Worker 
Name(const Definition & def) const299*890232f2SAndroid Build Coastguard Worker   std::string Name(const Definition &def) const {
300*890232f2SAndroid Build Coastguard Worker     return EscapeKeyword(def.name);
301*890232f2SAndroid Build Coastguard Worker   }
302*890232f2SAndroid Build Coastguard Worker 
Name(const EnumVal & ev) const303*890232f2SAndroid Build Coastguard Worker   std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
304*890232f2SAndroid Build Coastguard Worker 
generate_bfbs_embed()305*890232f2SAndroid Build Coastguard Worker   bool generate_bfbs_embed() {
306*890232f2SAndroid Build Coastguard Worker     code_.Clear();
307*890232f2SAndroid Build Coastguard Worker     code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
308*890232f2SAndroid Build Coastguard Worker 
309*890232f2SAndroid Build Coastguard Worker     // If we don't have a root struct definition,
310*890232f2SAndroid Build Coastguard Worker     if (!parser_.root_struct_def_) {
311*890232f2SAndroid Build Coastguard Worker       // put a comment in the output why there is no code generated.
312*890232f2SAndroid Build Coastguard Worker       code_ += "// Binary schema not generated, no root struct found";
313*890232f2SAndroid Build Coastguard Worker     } else {
314*890232f2SAndroid Build Coastguard Worker       auto &struct_def = *parser_.root_struct_def_;
315*890232f2SAndroid Build Coastguard Worker       const auto include_guard =
316*890232f2SAndroid Build Coastguard Worker           GenIncludeGuard(file_name_, *struct_def.defined_namespace, "bfbs");
317*890232f2SAndroid Build Coastguard Worker 
318*890232f2SAndroid Build Coastguard Worker       code_ += "#ifndef " + include_guard;
319*890232f2SAndroid Build Coastguard Worker       code_ += "#define " + include_guard;
320*890232f2SAndroid Build Coastguard Worker       code_ += "";
321*890232f2SAndroid Build Coastguard Worker       if (parser_.opts.gen_nullable) {
322*890232f2SAndroid Build Coastguard Worker         code_ += "#pragma clang system_header\n\n";
323*890232f2SAndroid Build Coastguard Worker       }
324*890232f2SAndroid Build Coastguard Worker 
325*890232f2SAndroid Build Coastguard Worker       code_ += "#include \"flatbuffers/flatbuffers.h\"";
326*890232f2SAndroid Build Coastguard Worker       code_ += "";
327*890232f2SAndroid Build Coastguard Worker       GenFlatbuffersVersionCheck();
328*890232f2SAndroid Build Coastguard Worker       code_ += "";
329*890232f2SAndroid Build Coastguard Worker 
330*890232f2SAndroid Build Coastguard Worker       SetNameSpace(struct_def.defined_namespace);
331*890232f2SAndroid Build Coastguard Worker       auto name = Name(struct_def);
332*890232f2SAndroid Build Coastguard Worker       code_.SetValue("STRUCT_NAME", name);
333*890232f2SAndroid Build Coastguard Worker 
334*890232f2SAndroid Build Coastguard Worker       // Create code to return the binary schema data.
335*890232f2SAndroid Build Coastguard Worker       auto binary_schema_hex_text =
336*890232f2SAndroid Build Coastguard Worker           BufferToHexText(parser_.builder_.GetBufferPointer(),
337*890232f2SAndroid Build Coastguard Worker                           parser_.builder_.GetSize(), 105, "      ", "");
338*890232f2SAndroid Build Coastguard Worker 
339*890232f2SAndroid Build Coastguard Worker       code_ += "struct {{STRUCT_NAME}}BinarySchema {";
340*890232f2SAndroid Build Coastguard Worker       code_ += "  static const uint8_t *data() {";
341*890232f2SAndroid Build Coastguard Worker       code_ += "    // Buffer containing the binary schema.";
342*890232f2SAndroid Build Coastguard Worker       code_ += "    static const uint8_t bfbsData[" +
343*890232f2SAndroid Build Coastguard Worker                NumToString(parser_.builder_.GetSize()) + "] = {";
344*890232f2SAndroid Build Coastguard Worker       code_ += binary_schema_hex_text;
345*890232f2SAndroid Build Coastguard Worker       code_ += "    };";
346*890232f2SAndroid Build Coastguard Worker       code_ += "    return bfbsData;";
347*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
348*890232f2SAndroid Build Coastguard Worker       code_ += "  static size_t size() {";
349*890232f2SAndroid Build Coastguard Worker       code_ += "    return " + NumToString(parser_.builder_.GetSize()) + ";";
350*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
351*890232f2SAndroid Build Coastguard Worker       code_ += "  const uint8_t *begin() {";
352*890232f2SAndroid Build Coastguard Worker       code_ += "    return data();";
353*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
354*890232f2SAndroid Build Coastguard Worker       code_ += "  const uint8_t *end() {";
355*890232f2SAndroid Build Coastguard Worker       code_ += "    return data() + size();";
356*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
357*890232f2SAndroid Build Coastguard Worker       code_ += "};";
358*890232f2SAndroid Build Coastguard Worker       code_ += "";
359*890232f2SAndroid Build Coastguard Worker 
360*890232f2SAndroid Build Coastguard Worker       if (cur_name_space_) SetNameSpace(nullptr);
361*890232f2SAndroid Build Coastguard Worker 
362*890232f2SAndroid Build Coastguard Worker       // Close the include guard.
363*890232f2SAndroid Build Coastguard Worker       code_ += "#endif  // " + include_guard;
364*890232f2SAndroid Build Coastguard Worker     }
365*890232f2SAndroid Build Coastguard Worker 
366*890232f2SAndroid Build Coastguard Worker     // We are just adding "_bfbs" to the generated filename.
367*890232f2SAndroid Build Coastguard Worker     const auto file_path =
368*890232f2SAndroid Build Coastguard Worker         GeneratedFileName(path_, file_name_ + "_bfbs", opts_);
369*890232f2SAndroid Build Coastguard Worker     const auto final_code = code_.ToString();
370*890232f2SAndroid Build Coastguard Worker 
371*890232f2SAndroid Build Coastguard Worker     return SaveFile(file_path.c_str(), final_code, false);
372*890232f2SAndroid Build Coastguard Worker   }
373*890232f2SAndroid Build Coastguard Worker 
374*890232f2SAndroid Build Coastguard Worker   // Iterate through all definitions we haven't generate code for (enums,
375*890232f2SAndroid Build Coastguard Worker   // structs, and tables) and output them to a single file.
generate()376*890232f2SAndroid Build Coastguard Worker   bool generate() {
377*890232f2SAndroid Build Coastguard Worker     code_.Clear();
378*890232f2SAndroid Build Coastguard Worker     code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
379*890232f2SAndroid Build Coastguard Worker 
380*890232f2SAndroid Build Coastguard Worker     const auto include_guard =
381*890232f2SAndroid Build Coastguard Worker         GenIncludeGuard(file_name_, *parser_.current_namespace_);
382*890232f2SAndroid Build Coastguard Worker     code_ += "#ifndef " + include_guard;
383*890232f2SAndroid Build Coastguard Worker     code_ += "#define " + include_guard;
384*890232f2SAndroid Build Coastguard Worker     code_ += "";
385*890232f2SAndroid Build Coastguard Worker 
386*890232f2SAndroid Build Coastguard Worker     if (opts_.gen_nullable) { code_ += "#pragma clang system_header\n\n"; }
387*890232f2SAndroid Build Coastguard Worker 
388*890232f2SAndroid Build Coastguard Worker     code_ += "#include \"flatbuffers/flatbuffers.h\"";
389*890232f2SAndroid Build Coastguard Worker     if (parser_.uses_flexbuffers_) {
390*890232f2SAndroid Build Coastguard Worker       code_ += "#include \"flatbuffers/flexbuffers.h\"";
391*890232f2SAndroid Build Coastguard Worker       code_ += "#include \"flatbuffers/flex_flat_util.h\"";
392*890232f2SAndroid Build Coastguard Worker     }
393*890232f2SAndroid Build Coastguard Worker     code_ += "";
394*890232f2SAndroid Build Coastguard Worker     GenFlatbuffersVersionCheck();
395*890232f2SAndroid Build Coastguard Worker     code_ += "";
396*890232f2SAndroid Build Coastguard Worker 
397*890232f2SAndroid Build Coastguard Worker     if (opts_.include_dependence_headers) { GenIncludeDependencies(); }
398*890232f2SAndroid Build Coastguard Worker     GenExtraIncludes();
399*890232f2SAndroid Build Coastguard Worker 
400*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(!cur_name_space_);
401*890232f2SAndroid Build Coastguard Worker 
402*890232f2SAndroid Build Coastguard Worker     // Generate forward declarations for all structs/tables, since they may
403*890232f2SAndroid Build Coastguard Worker     // have circular references.
404*890232f2SAndroid Build Coastguard Worker     for (auto it = parser_.structs_.vec.begin();
405*890232f2SAndroid Build Coastguard Worker          it != parser_.structs_.vec.end(); ++it) {
406*890232f2SAndroid Build Coastguard Worker       const auto &struct_def = **it;
407*890232f2SAndroid Build Coastguard Worker       if (!struct_def.generated) {
408*890232f2SAndroid Build Coastguard Worker         SetNameSpace(struct_def.defined_namespace);
409*890232f2SAndroid Build Coastguard Worker         code_ += "struct " + Name(struct_def) + ";";
410*890232f2SAndroid Build Coastguard Worker         if (!struct_def.fixed) {
411*890232f2SAndroid Build Coastguard Worker           code_ += "struct " + Name(struct_def) + "Builder;";
412*890232f2SAndroid Build Coastguard Worker         }
413*890232f2SAndroid Build Coastguard Worker         if (opts_.generate_object_based_api) {
414*890232f2SAndroid Build Coastguard Worker           auto nativeName = NativeName(Name(struct_def), &struct_def, opts_);
415*890232f2SAndroid Build Coastguard Worker           if (!struct_def.fixed) { code_ += "struct " + nativeName + ";"; }
416*890232f2SAndroid Build Coastguard Worker         }
417*890232f2SAndroid Build Coastguard Worker         code_ += "";
418*890232f2SAndroid Build Coastguard Worker       }
419*890232f2SAndroid Build Coastguard Worker     }
420*890232f2SAndroid Build Coastguard Worker 
421*890232f2SAndroid Build Coastguard Worker     // Generate forward declarations for all equal operators
422*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api && opts_.gen_compare) {
423*890232f2SAndroid Build Coastguard Worker       for (auto it = parser_.structs_.vec.begin();
424*890232f2SAndroid Build Coastguard Worker            it != parser_.structs_.vec.end(); ++it) {
425*890232f2SAndroid Build Coastguard Worker         const auto &struct_def = **it;
426*890232f2SAndroid Build Coastguard Worker         if (!struct_def.generated) {
427*890232f2SAndroid Build Coastguard Worker           SetNameSpace(struct_def.defined_namespace);
428*890232f2SAndroid Build Coastguard Worker           auto nativeName = NativeName(Name(struct_def), &struct_def, opts_);
429*890232f2SAndroid Build Coastguard Worker           code_ += "bool operator==(const " + nativeName + " &lhs, const " +
430*890232f2SAndroid Build Coastguard Worker                    nativeName + " &rhs);";
431*890232f2SAndroid Build Coastguard Worker           code_ += "bool operator!=(const " + nativeName + " &lhs, const " +
432*890232f2SAndroid Build Coastguard Worker                    nativeName + " &rhs);";
433*890232f2SAndroid Build Coastguard Worker         }
434*890232f2SAndroid Build Coastguard Worker       }
435*890232f2SAndroid Build Coastguard Worker       code_ += "";
436*890232f2SAndroid Build Coastguard Worker     }
437*890232f2SAndroid Build Coastguard Worker 
438*890232f2SAndroid Build Coastguard Worker     // Generate preablmle code for mini reflection.
439*890232f2SAndroid Build Coastguard Worker     if (opts_.mini_reflect != IDLOptions::kNone) {
440*890232f2SAndroid Build Coastguard Worker       // To break cyclic dependencies, first pre-declare all tables/structs.
441*890232f2SAndroid Build Coastguard Worker       for (auto it = parser_.structs_.vec.begin();
442*890232f2SAndroid Build Coastguard Worker            it != parser_.structs_.vec.end(); ++it) {
443*890232f2SAndroid Build Coastguard Worker         const auto &struct_def = **it;
444*890232f2SAndroid Build Coastguard Worker         if (!struct_def.generated) {
445*890232f2SAndroid Build Coastguard Worker           SetNameSpace(struct_def.defined_namespace);
446*890232f2SAndroid Build Coastguard Worker           GenMiniReflectPre(&struct_def);
447*890232f2SAndroid Build Coastguard Worker         }
448*890232f2SAndroid Build Coastguard Worker       }
449*890232f2SAndroid Build Coastguard Worker     }
450*890232f2SAndroid Build Coastguard Worker 
451*890232f2SAndroid Build Coastguard Worker     // Generate code for all the enum declarations.
452*890232f2SAndroid Build Coastguard Worker     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
453*890232f2SAndroid Build Coastguard Worker          ++it) {
454*890232f2SAndroid Build Coastguard Worker       const auto &enum_def = **it;
455*890232f2SAndroid Build Coastguard Worker       if (!enum_def.generated) {
456*890232f2SAndroid Build Coastguard Worker         SetNameSpace(enum_def.defined_namespace);
457*890232f2SAndroid Build Coastguard Worker         GenEnum(enum_def);
458*890232f2SAndroid Build Coastguard Worker       }
459*890232f2SAndroid Build Coastguard Worker     }
460*890232f2SAndroid Build Coastguard Worker 
461*890232f2SAndroid Build Coastguard Worker     // Generate code for all structs, then all tables.
462*890232f2SAndroid Build Coastguard Worker     for (auto it = parser_.structs_.vec.begin();
463*890232f2SAndroid Build Coastguard Worker          it != parser_.structs_.vec.end(); ++it) {
464*890232f2SAndroid Build Coastguard Worker       const auto &struct_def = **it;
465*890232f2SAndroid Build Coastguard Worker       if (struct_def.fixed && !struct_def.generated) {
466*890232f2SAndroid Build Coastguard Worker         SetNameSpace(struct_def.defined_namespace);
467*890232f2SAndroid Build Coastguard Worker         GenStruct(struct_def);
468*890232f2SAndroid Build Coastguard Worker       }
469*890232f2SAndroid Build Coastguard Worker     }
470*890232f2SAndroid Build Coastguard Worker     for (auto it = parser_.structs_.vec.begin();
471*890232f2SAndroid Build Coastguard Worker          it != parser_.structs_.vec.end(); ++it) {
472*890232f2SAndroid Build Coastguard Worker       const auto &struct_def = **it;
473*890232f2SAndroid Build Coastguard Worker       if (!struct_def.fixed && !struct_def.generated) {
474*890232f2SAndroid Build Coastguard Worker         SetNameSpace(struct_def.defined_namespace);
475*890232f2SAndroid Build Coastguard Worker         GenTable(struct_def);
476*890232f2SAndroid Build Coastguard Worker       }
477*890232f2SAndroid Build Coastguard Worker     }
478*890232f2SAndroid Build Coastguard Worker     for (auto it = parser_.structs_.vec.begin();
479*890232f2SAndroid Build Coastguard Worker          it != parser_.structs_.vec.end(); ++it) {
480*890232f2SAndroid Build Coastguard Worker       const auto &struct_def = **it;
481*890232f2SAndroid Build Coastguard Worker       if (!struct_def.fixed && !struct_def.generated) {
482*890232f2SAndroid Build Coastguard Worker         SetNameSpace(struct_def.defined_namespace);
483*890232f2SAndroid Build Coastguard Worker         GenTablePost(struct_def);
484*890232f2SAndroid Build Coastguard Worker       }
485*890232f2SAndroid Build Coastguard Worker     }
486*890232f2SAndroid Build Coastguard Worker 
487*890232f2SAndroid Build Coastguard Worker     // Generate code for union verifiers.
488*890232f2SAndroid Build Coastguard Worker     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
489*890232f2SAndroid Build Coastguard Worker          ++it) {
490*890232f2SAndroid Build Coastguard Worker       const auto &enum_def = **it;
491*890232f2SAndroid Build Coastguard Worker       if (enum_def.is_union && !enum_def.generated) {
492*890232f2SAndroid Build Coastguard Worker         SetNameSpace(enum_def.defined_namespace);
493*890232f2SAndroid Build Coastguard Worker         GenUnionPost(enum_def);
494*890232f2SAndroid Build Coastguard Worker       }
495*890232f2SAndroid Build Coastguard Worker     }
496*890232f2SAndroid Build Coastguard Worker 
497*890232f2SAndroid Build Coastguard Worker     // Generate code for mini reflection.
498*890232f2SAndroid Build Coastguard Worker     if (opts_.mini_reflect != IDLOptions::kNone) {
499*890232f2SAndroid Build Coastguard Worker       // Then the unions/enums that may refer to them.
500*890232f2SAndroid Build Coastguard Worker       for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
501*890232f2SAndroid Build Coastguard Worker            ++it) {
502*890232f2SAndroid Build Coastguard Worker         const auto &enum_def = **it;
503*890232f2SAndroid Build Coastguard Worker         if (!enum_def.generated) {
504*890232f2SAndroid Build Coastguard Worker           SetNameSpace(enum_def.defined_namespace);
505*890232f2SAndroid Build Coastguard Worker           GenMiniReflect(nullptr, &enum_def);
506*890232f2SAndroid Build Coastguard Worker         }
507*890232f2SAndroid Build Coastguard Worker       }
508*890232f2SAndroid Build Coastguard Worker       // Then the full tables/structs.
509*890232f2SAndroid Build Coastguard Worker       for (auto it = parser_.structs_.vec.begin();
510*890232f2SAndroid Build Coastguard Worker            it != parser_.structs_.vec.end(); ++it) {
511*890232f2SAndroid Build Coastguard Worker         const auto &struct_def = **it;
512*890232f2SAndroid Build Coastguard Worker         if (!struct_def.generated) {
513*890232f2SAndroid Build Coastguard Worker           SetNameSpace(struct_def.defined_namespace);
514*890232f2SAndroid Build Coastguard Worker           GenMiniReflect(&struct_def, nullptr);
515*890232f2SAndroid Build Coastguard Worker         }
516*890232f2SAndroid Build Coastguard Worker       }
517*890232f2SAndroid Build Coastguard Worker     }
518*890232f2SAndroid Build Coastguard Worker 
519*890232f2SAndroid Build Coastguard Worker     // Generate convenient global helper functions:
520*890232f2SAndroid Build Coastguard Worker     if (parser_.root_struct_def_) {
521*890232f2SAndroid Build Coastguard Worker       auto &struct_def = *parser_.root_struct_def_;
522*890232f2SAndroid Build Coastguard Worker       SetNameSpace(struct_def.defined_namespace);
523*890232f2SAndroid Build Coastguard Worker       auto name = Name(struct_def);
524*890232f2SAndroid Build Coastguard Worker       auto qualified_name = cur_name_space_->GetFullyQualifiedName(name);
525*890232f2SAndroid Build Coastguard Worker       auto cpp_name = TranslateNameSpace(qualified_name);
526*890232f2SAndroid Build Coastguard Worker 
527*890232f2SAndroid Build Coastguard Worker       code_.SetValue("STRUCT_NAME", name);
528*890232f2SAndroid Build Coastguard Worker       code_.SetValue("CPP_NAME", cpp_name);
529*890232f2SAndroid Build Coastguard Worker       code_.SetValue("NULLABLE_EXT", NullableExtension());
530*890232f2SAndroid Build Coastguard Worker 
531*890232f2SAndroid Build Coastguard Worker       // The root datatype accessor:
532*890232f2SAndroid Build Coastguard Worker       code_ += "inline \\";
533*890232f2SAndroid Build Coastguard Worker       code_ +=
534*890232f2SAndroid Build Coastguard Worker           "const {{CPP_NAME}} *{{NULLABLE_EXT}}Get{{STRUCT_NAME}}(const void "
535*890232f2SAndroid Build Coastguard Worker           "*buf) {";
536*890232f2SAndroid Build Coastguard Worker       code_ += "  return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
537*890232f2SAndroid Build Coastguard Worker       code_ += "}";
538*890232f2SAndroid Build Coastguard Worker       code_ += "";
539*890232f2SAndroid Build Coastguard Worker 
540*890232f2SAndroid Build Coastguard Worker       code_ += "inline \\";
541*890232f2SAndroid Build Coastguard Worker       code_ +=
542*890232f2SAndroid Build Coastguard Worker           "const {{CPP_NAME}} "
543*890232f2SAndroid Build Coastguard Worker           "*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
544*890232f2SAndroid Build Coastguard Worker           "*buf) {";
545*890232f2SAndroid Build Coastguard Worker       code_ += "  return flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}>(buf);";
546*890232f2SAndroid Build Coastguard Worker       code_ += "}";
547*890232f2SAndroid Build Coastguard Worker       code_ += "";
548*890232f2SAndroid Build Coastguard Worker 
549*890232f2SAndroid Build Coastguard Worker       if (opts_.mutable_buffer) {
550*890232f2SAndroid Build Coastguard Worker         code_ += "inline \\";
551*890232f2SAndroid Build Coastguard Worker         code_ += "{{STRUCT_NAME}} *GetMutable{{STRUCT_NAME}}(void *buf) {";
552*890232f2SAndroid Build Coastguard Worker         code_ += "  return flatbuffers::GetMutableRoot<{{STRUCT_NAME}}>(buf);";
553*890232f2SAndroid Build Coastguard Worker         code_ += "}";
554*890232f2SAndroid Build Coastguard Worker         code_ += "";
555*890232f2SAndroid Build Coastguard Worker 
556*890232f2SAndroid Build Coastguard Worker         code_ += "inline \\";
557*890232f2SAndroid Build Coastguard Worker         code_ +=
558*890232f2SAndroid Build Coastguard Worker             "{{CPP_NAME}} "
559*890232f2SAndroid Build Coastguard Worker             "*{{NULLABLE_EXT}}GetMutableSizePrefixed{{STRUCT_NAME}}(void "
560*890232f2SAndroid Build Coastguard Worker             "*buf) {";
561*890232f2SAndroid Build Coastguard Worker         code_ +=
562*890232f2SAndroid Build Coastguard Worker             "  return "
563*890232f2SAndroid Build Coastguard Worker             "flatbuffers::GetMutableSizePrefixedRoot<{{CPP_NAME}}>(buf);";
564*890232f2SAndroid Build Coastguard Worker         code_ += "}";
565*890232f2SAndroid Build Coastguard Worker         code_ += "";
566*890232f2SAndroid Build Coastguard Worker       }
567*890232f2SAndroid Build Coastguard Worker 
568*890232f2SAndroid Build Coastguard Worker       if (parser_.file_identifier_.length()) {
569*890232f2SAndroid Build Coastguard Worker         // Return the identifier
570*890232f2SAndroid Build Coastguard Worker         code_ += "inline const char *{{STRUCT_NAME}}Identifier() {";
571*890232f2SAndroid Build Coastguard Worker         code_ += "  return \"" + parser_.file_identifier_ + "\";";
572*890232f2SAndroid Build Coastguard Worker         code_ += "}";
573*890232f2SAndroid Build Coastguard Worker         code_ += "";
574*890232f2SAndroid Build Coastguard Worker 
575*890232f2SAndroid Build Coastguard Worker         // Check if a buffer has the identifier.
576*890232f2SAndroid Build Coastguard Worker         code_ += "inline \\";
577*890232f2SAndroid Build Coastguard Worker         code_ += "bool {{STRUCT_NAME}}BufferHasIdentifier(const void *buf) {";
578*890232f2SAndroid Build Coastguard Worker         code_ += "  return flatbuffers::BufferHasIdentifier(";
579*890232f2SAndroid Build Coastguard Worker         code_ += "      buf, {{STRUCT_NAME}}Identifier());";
580*890232f2SAndroid Build Coastguard Worker         code_ += "}";
581*890232f2SAndroid Build Coastguard Worker         code_ += "";
582*890232f2SAndroid Build Coastguard Worker 
583*890232f2SAndroid Build Coastguard Worker         // Check if a size-prefixed buffer has the identifier.
584*890232f2SAndroid Build Coastguard Worker         code_ += "inline \\";
585*890232f2SAndroid Build Coastguard Worker         code_ +=
586*890232f2SAndroid Build Coastguard Worker             "bool SizePrefixed{{STRUCT_NAME}}BufferHasIdentifier(const void "
587*890232f2SAndroid Build Coastguard Worker             "*buf) {";
588*890232f2SAndroid Build Coastguard Worker         code_ += "  return flatbuffers::BufferHasIdentifier(";
589*890232f2SAndroid Build Coastguard Worker         code_ += "      buf, {{STRUCT_NAME}}Identifier(), true);";
590*890232f2SAndroid Build Coastguard Worker         code_ += "}";
591*890232f2SAndroid Build Coastguard Worker         code_ += "";
592*890232f2SAndroid Build Coastguard Worker       }
593*890232f2SAndroid Build Coastguard Worker 
594*890232f2SAndroid Build Coastguard Worker       // The root verifier.
595*890232f2SAndroid Build Coastguard Worker       if (parser_.file_identifier_.length()) {
596*890232f2SAndroid Build Coastguard Worker         code_.SetValue("ID", name + "Identifier()");
597*890232f2SAndroid Build Coastguard Worker       } else {
598*890232f2SAndroid Build Coastguard Worker         code_.SetValue("ID", "nullptr");
599*890232f2SAndroid Build Coastguard Worker       }
600*890232f2SAndroid Build Coastguard Worker 
601*890232f2SAndroid Build Coastguard Worker       code_ += "inline bool Verify{{STRUCT_NAME}}Buffer(";
602*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::Verifier &verifier) {";
603*890232f2SAndroid Build Coastguard Worker       code_ += "  return verifier.VerifyBuffer<{{CPP_NAME}}>({{ID}});";
604*890232f2SAndroid Build Coastguard Worker       code_ += "}";
605*890232f2SAndroid Build Coastguard Worker       code_ += "";
606*890232f2SAndroid Build Coastguard Worker 
607*890232f2SAndroid Build Coastguard Worker       code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer(";
608*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::Verifier &verifier) {";
609*890232f2SAndroid Build Coastguard Worker       code_ +=
610*890232f2SAndroid Build Coastguard Worker           "  return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});";
611*890232f2SAndroid Build Coastguard Worker       code_ += "}";
612*890232f2SAndroid Build Coastguard Worker       code_ += "";
613*890232f2SAndroid Build Coastguard Worker 
614*890232f2SAndroid Build Coastguard Worker       if (parser_.file_extension_.length()) {
615*890232f2SAndroid Build Coastguard Worker         // Return the extension
616*890232f2SAndroid Build Coastguard Worker         code_ += "inline const char *{{STRUCT_NAME}}Extension() {";
617*890232f2SAndroid Build Coastguard Worker         code_ += "  return \"" + parser_.file_extension_ + "\";";
618*890232f2SAndroid Build Coastguard Worker         code_ += "}";
619*890232f2SAndroid Build Coastguard Worker         code_ += "";
620*890232f2SAndroid Build Coastguard Worker       }
621*890232f2SAndroid Build Coastguard Worker 
622*890232f2SAndroid Build Coastguard Worker       // Finish a buffer with a given root object:
623*890232f2SAndroid Build Coastguard Worker       code_ += "inline void Finish{{STRUCT_NAME}}Buffer(";
624*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::FlatBufferBuilder &fbb,";
625*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::Offset<{{CPP_NAME}}> root) {";
626*890232f2SAndroid Build Coastguard Worker       if (parser_.file_identifier_.length())
627*890232f2SAndroid Build Coastguard Worker         code_ += "  fbb.Finish(root, {{STRUCT_NAME}}Identifier());";
628*890232f2SAndroid Build Coastguard Worker       else
629*890232f2SAndroid Build Coastguard Worker         code_ += "  fbb.Finish(root);";
630*890232f2SAndroid Build Coastguard Worker       code_ += "}";
631*890232f2SAndroid Build Coastguard Worker       code_ += "";
632*890232f2SAndroid Build Coastguard Worker 
633*890232f2SAndroid Build Coastguard Worker       code_ += "inline void FinishSizePrefixed{{STRUCT_NAME}}Buffer(";
634*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::FlatBufferBuilder &fbb,";
635*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::Offset<{{CPP_NAME}}> root) {";
636*890232f2SAndroid Build Coastguard Worker       if (parser_.file_identifier_.length())
637*890232f2SAndroid Build Coastguard Worker         code_ += "  fbb.FinishSizePrefixed(root, {{STRUCT_NAME}}Identifier());";
638*890232f2SAndroid Build Coastguard Worker       else
639*890232f2SAndroid Build Coastguard Worker         code_ += "  fbb.FinishSizePrefixed(root);";
640*890232f2SAndroid Build Coastguard Worker       code_ += "}";
641*890232f2SAndroid Build Coastguard Worker       code_ += "";
642*890232f2SAndroid Build Coastguard Worker 
643*890232f2SAndroid Build Coastguard Worker       if (opts_.generate_object_based_api) {
644*890232f2SAndroid Build Coastguard Worker         // A convenient root unpack function.
645*890232f2SAndroid Build Coastguard Worker         auto native_name = WrapNativeNameInNameSpace(struct_def, opts_);
646*890232f2SAndroid Build Coastguard Worker         code_.SetValue("UNPACK_RETURN",
647*890232f2SAndroid Build Coastguard Worker                        GenTypeNativePtr(native_name, nullptr, false));
648*890232f2SAndroid Build Coastguard Worker         code_.SetValue("UNPACK_TYPE",
649*890232f2SAndroid Build Coastguard Worker                        GenTypeNativePtr(native_name, nullptr, true));
650*890232f2SAndroid Build Coastguard Worker 
651*890232f2SAndroid Build Coastguard Worker         code_ += "inline {{UNPACK_RETURN}} UnPack{{STRUCT_NAME}}(";
652*890232f2SAndroid Build Coastguard Worker         code_ += "    const void *buf,";
653*890232f2SAndroid Build Coastguard Worker         code_ += "    const flatbuffers::resolver_function_t *res = nullptr) {";
654*890232f2SAndroid Build Coastguard Worker         code_ += "  return {{UNPACK_TYPE}}\\";
655*890232f2SAndroid Build Coastguard Worker         code_ += "(Get{{STRUCT_NAME}}(buf)->UnPack(res));";
656*890232f2SAndroid Build Coastguard Worker         code_ += "}";
657*890232f2SAndroid Build Coastguard Worker         code_ += "";
658*890232f2SAndroid Build Coastguard Worker 
659*890232f2SAndroid Build Coastguard Worker         code_ += "inline {{UNPACK_RETURN}} UnPackSizePrefixed{{STRUCT_NAME}}(";
660*890232f2SAndroid Build Coastguard Worker         code_ += "    const void *buf,";
661*890232f2SAndroid Build Coastguard Worker         code_ += "    const flatbuffers::resolver_function_t *res = nullptr) {";
662*890232f2SAndroid Build Coastguard Worker         code_ += "  return {{UNPACK_TYPE}}\\";
663*890232f2SAndroid Build Coastguard Worker         code_ += "(GetSizePrefixed{{STRUCT_NAME}}(buf)->UnPack(res));";
664*890232f2SAndroid Build Coastguard Worker         code_ += "}";
665*890232f2SAndroid Build Coastguard Worker         code_ += "";
666*890232f2SAndroid Build Coastguard Worker       }
667*890232f2SAndroid Build Coastguard Worker     }
668*890232f2SAndroid Build Coastguard Worker 
669*890232f2SAndroid Build Coastguard Worker     if (cur_name_space_) SetNameSpace(nullptr);
670*890232f2SAndroid Build Coastguard Worker 
671*890232f2SAndroid Build Coastguard Worker     // Close the include guard.
672*890232f2SAndroid Build Coastguard Worker     code_ += "#endif  // " + include_guard;
673*890232f2SAndroid Build Coastguard Worker 
674*890232f2SAndroid Build Coastguard Worker     const auto file_path = GeneratedFileName(path_, file_name_, opts_);
675*890232f2SAndroid Build Coastguard Worker     const auto final_code = code_.ToString();
676*890232f2SAndroid Build Coastguard Worker 
677*890232f2SAndroid Build Coastguard Worker     // Save the file and optionally generate the binary schema code.
678*890232f2SAndroid Build Coastguard Worker     return SaveFile(file_path.c_str(), final_code, false) &&
679*890232f2SAndroid Build Coastguard Worker            (!parser_.opts.binary_schema_gen_embed || generate_bfbs_embed());
680*890232f2SAndroid Build Coastguard Worker   }
681*890232f2SAndroid Build Coastguard Worker 
682*890232f2SAndroid Build Coastguard Worker  private:
683*890232f2SAndroid Build Coastguard Worker   CodeWriter code_;
684*890232f2SAndroid Build Coastguard Worker 
685*890232f2SAndroid Build Coastguard Worker   std::unordered_set<std::string> keywords_;
686*890232f2SAndroid Build Coastguard Worker 
687*890232f2SAndroid Build Coastguard Worker   // This tracks the current namespace so we can insert namespace declarations.
688*890232f2SAndroid Build Coastguard Worker   const Namespace *cur_name_space_;
689*890232f2SAndroid Build Coastguard Worker 
690*890232f2SAndroid Build Coastguard Worker   const IDLOptionsCpp opts_;
691*890232f2SAndroid Build Coastguard Worker   const TypedFloatConstantGenerator float_const_gen_;
692*890232f2SAndroid Build Coastguard Worker 
CurrentNameSpace() const693*890232f2SAndroid Build Coastguard Worker   const Namespace *CurrentNameSpace() const { return cur_name_space_; }
694*890232f2SAndroid Build Coastguard Worker 
695*890232f2SAndroid Build Coastguard Worker   // Translates a qualified name in flatbuffer text format to the same name in
696*890232f2SAndroid Build Coastguard Worker   // the equivalent C++ namespace.
TranslateNameSpace(const std::string & qualified_name)697*890232f2SAndroid Build Coastguard Worker   static std::string TranslateNameSpace(const std::string &qualified_name) {
698*890232f2SAndroid Build Coastguard Worker     std::string cpp_qualified_name = qualified_name;
699*890232f2SAndroid Build Coastguard Worker     size_t start_pos = 0;
700*890232f2SAndroid Build Coastguard Worker     while ((start_pos = cpp_qualified_name.find('.', start_pos)) !=
701*890232f2SAndroid Build Coastguard Worker            std::string::npos) {
702*890232f2SAndroid Build Coastguard Worker       cpp_qualified_name.replace(start_pos, 1, "::");
703*890232f2SAndroid Build Coastguard Worker     }
704*890232f2SAndroid Build Coastguard Worker     return cpp_qualified_name;
705*890232f2SAndroid Build Coastguard Worker   }
706*890232f2SAndroid Build Coastguard Worker 
TypeHasKey(const Type & type)707*890232f2SAndroid Build Coastguard Worker   bool TypeHasKey(const Type &type) {
708*890232f2SAndroid Build Coastguard Worker     if (type.base_type != BASE_TYPE_STRUCT) { return false; }
709*890232f2SAndroid Build Coastguard Worker     for (auto it = type.struct_def->fields.vec.begin();
710*890232f2SAndroid Build Coastguard Worker          it != type.struct_def->fields.vec.end(); ++it) {
711*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
712*890232f2SAndroid Build Coastguard Worker       if (field.key) { return true; }
713*890232f2SAndroid Build Coastguard Worker     }
714*890232f2SAndroid Build Coastguard Worker     return false;
715*890232f2SAndroid Build Coastguard Worker   }
716*890232f2SAndroid Build Coastguard Worker 
VectorElementUserFacing(const Type & type) const717*890232f2SAndroid Build Coastguard Worker   bool VectorElementUserFacing(const Type &type) const {
718*890232f2SAndroid Build Coastguard Worker     return (opts_.scoped_enums && IsEnum(type)) ||
719*890232f2SAndroid Build Coastguard Worker            (opts_.g_cpp_std >= cpp::CPP_STD_17 && opts_.g_only_fixed_enums &&
720*890232f2SAndroid Build Coastguard Worker             IsEnum(type));
721*890232f2SAndroid Build Coastguard Worker   }
722*890232f2SAndroid Build Coastguard Worker 
GenComment(const std::vector<std::string> & dc,const char * prefix="")723*890232f2SAndroid Build Coastguard Worker   void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
724*890232f2SAndroid Build Coastguard Worker     std::string text;
725*890232f2SAndroid Build Coastguard Worker     ::flatbuffers::GenComment(dc, &text, nullptr, prefix);
726*890232f2SAndroid Build Coastguard Worker     code_ += text + "\\";
727*890232f2SAndroid Build Coastguard Worker   }
728*890232f2SAndroid Build Coastguard Worker 
729*890232f2SAndroid Build Coastguard Worker   // Return a C++ type from the table in idl.h
GenTypeBasic(const Type & type,bool user_facing_type) const730*890232f2SAndroid Build Coastguard Worker   std::string GenTypeBasic(const Type &type, bool user_facing_type) const {
731*890232f2SAndroid Build Coastguard Worker     // clang-format off
732*890232f2SAndroid Build Coastguard Worker     static const char *const ctypename[] = {
733*890232f2SAndroid Build Coastguard Worker       #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
734*890232f2SAndroid Build Coastguard Worker         #CTYPE,
735*890232f2SAndroid Build Coastguard Worker         FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
736*890232f2SAndroid Build Coastguard Worker       #undef FLATBUFFERS_TD
737*890232f2SAndroid Build Coastguard Worker     };
738*890232f2SAndroid Build Coastguard Worker     // clang-format on
739*890232f2SAndroid Build Coastguard Worker     if (user_facing_type) {
740*890232f2SAndroid Build Coastguard Worker       if (type.enum_def) return WrapInNameSpace(*type.enum_def);
741*890232f2SAndroid Build Coastguard Worker       if (type.base_type == BASE_TYPE_BOOL) return "bool";
742*890232f2SAndroid Build Coastguard Worker     }
743*890232f2SAndroid Build Coastguard Worker     return ctypename[type.base_type];
744*890232f2SAndroid Build Coastguard Worker   }
745*890232f2SAndroid Build Coastguard Worker 
746*890232f2SAndroid Build Coastguard Worker   // Return a C++ pointer type, specialized to the actual struct/table types,
747*890232f2SAndroid Build Coastguard Worker   // and vector element types.
GenTypePointer(const Type & type) const748*890232f2SAndroid Build Coastguard Worker   std::string GenTypePointer(const Type &type) const {
749*890232f2SAndroid Build Coastguard Worker     switch (type.base_type) {
750*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRING: {
751*890232f2SAndroid Build Coastguard Worker         return "flatbuffers::String";
752*890232f2SAndroid Build Coastguard Worker       }
753*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_VECTOR: {
754*890232f2SAndroid Build Coastguard Worker         const auto type_name = GenTypeWire(
755*890232f2SAndroid Build Coastguard Worker             type.VectorType(), "", VectorElementUserFacing(type.VectorType()));
756*890232f2SAndroid Build Coastguard Worker         return "flatbuffers::Vector<" + type_name + ">";
757*890232f2SAndroid Build Coastguard Worker       }
758*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRUCT: {
759*890232f2SAndroid Build Coastguard Worker         return WrapInNameSpace(*type.struct_def);
760*890232f2SAndroid Build Coastguard Worker       }
761*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UNION:
762*890232f2SAndroid Build Coastguard Worker         // fall through
763*890232f2SAndroid Build Coastguard Worker       default: {
764*890232f2SAndroid Build Coastguard Worker         return "void";
765*890232f2SAndroid Build Coastguard Worker       }
766*890232f2SAndroid Build Coastguard Worker     }
767*890232f2SAndroid Build Coastguard Worker   }
768*890232f2SAndroid Build Coastguard Worker 
769*890232f2SAndroid Build Coastguard Worker   // Return a C++ type for any type (scalar/pointer) specifically for
770*890232f2SAndroid Build Coastguard Worker   // building a flatbuffer.
GenTypeWire(const Type & type,const char * postfix,bool user_facing_type) const771*890232f2SAndroid Build Coastguard Worker   std::string GenTypeWire(const Type &type, const char *postfix,
772*890232f2SAndroid Build Coastguard Worker                           bool user_facing_type) const {
773*890232f2SAndroid Build Coastguard Worker     if (IsScalar(type.base_type)) {
774*890232f2SAndroid Build Coastguard Worker       return GenTypeBasic(type, user_facing_type) + postfix;
775*890232f2SAndroid Build Coastguard Worker     } else if (IsStruct(type)) {
776*890232f2SAndroid Build Coastguard Worker       return "const " + GenTypePointer(type) + " *";
777*890232f2SAndroid Build Coastguard Worker     } else {
778*890232f2SAndroid Build Coastguard Worker       return "flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix;
779*890232f2SAndroid Build Coastguard Worker     }
780*890232f2SAndroid Build Coastguard Worker   }
781*890232f2SAndroid Build Coastguard Worker 
782*890232f2SAndroid Build Coastguard Worker   // Return a C++ type for any type (scalar/pointer) that reflects its
783*890232f2SAndroid Build Coastguard Worker   // serialized size.
GenTypeSize(const Type & type) const784*890232f2SAndroid Build Coastguard Worker   std::string GenTypeSize(const Type &type) const {
785*890232f2SAndroid Build Coastguard Worker     if (IsScalar(type.base_type)) {
786*890232f2SAndroid Build Coastguard Worker       return GenTypeBasic(type, false);
787*890232f2SAndroid Build Coastguard Worker     } else if (IsStruct(type)) {
788*890232f2SAndroid Build Coastguard Worker       return GenTypePointer(type);
789*890232f2SAndroid Build Coastguard Worker     } else {
790*890232f2SAndroid Build Coastguard Worker       return "flatbuffers::uoffset_t";
791*890232f2SAndroid Build Coastguard Worker     }
792*890232f2SAndroid Build Coastguard Worker   }
793*890232f2SAndroid Build Coastguard Worker 
NullableExtension()794*890232f2SAndroid Build Coastguard Worker   std::string NullableExtension() {
795*890232f2SAndroid Build Coastguard Worker     return opts_.gen_nullable ? " _Nullable " : "";
796*890232f2SAndroid Build Coastguard Worker   }
797*890232f2SAndroid Build Coastguard Worker 
NativeName(const std::string & name,const StructDef * sd,const IDLOptions & opts)798*890232f2SAndroid Build Coastguard Worker   static std::string NativeName(const std::string &name, const StructDef *sd,
799*890232f2SAndroid Build Coastguard Worker                                 const IDLOptions &opts) {
800*890232f2SAndroid Build Coastguard Worker     return sd && !sd->fixed ? opts.object_prefix + name + opts.object_suffix
801*890232f2SAndroid Build Coastguard Worker                             : name;
802*890232f2SAndroid Build Coastguard Worker   }
803*890232f2SAndroid Build Coastguard Worker 
WrapNativeNameInNameSpace(const StructDef & struct_def,const IDLOptions & opts)804*890232f2SAndroid Build Coastguard Worker   std::string WrapNativeNameInNameSpace(const StructDef &struct_def,
805*890232f2SAndroid Build Coastguard Worker                                         const IDLOptions &opts) {
806*890232f2SAndroid Build Coastguard Worker     return WrapInNameSpace(struct_def.defined_namespace,
807*890232f2SAndroid Build Coastguard Worker                            NativeName(Name(struct_def), &struct_def, opts));
808*890232f2SAndroid Build Coastguard Worker   }
809*890232f2SAndroid Build Coastguard Worker 
PtrType(const FieldDef * field)810*890232f2SAndroid Build Coastguard Worker   const std::string &PtrType(const FieldDef *field) {
811*890232f2SAndroid Build Coastguard Worker     auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
812*890232f2SAndroid Build Coastguard Worker     return attr ? attr->constant : opts_.cpp_object_api_pointer_type;
813*890232f2SAndroid Build Coastguard Worker   }
814*890232f2SAndroid Build Coastguard Worker 
NativeString(const FieldDef * field)815*890232f2SAndroid Build Coastguard Worker   const std::string NativeString(const FieldDef *field) {
816*890232f2SAndroid Build Coastguard Worker     auto attr = field ? field->attributes.Lookup("cpp_str_type") : nullptr;
817*890232f2SAndroid Build Coastguard Worker     auto &ret = attr ? attr->constant : opts_.cpp_object_api_string_type;
818*890232f2SAndroid Build Coastguard Worker     if (ret.empty()) { return "std::string"; }
819*890232f2SAndroid Build Coastguard Worker     return ret;
820*890232f2SAndroid Build Coastguard Worker   }
821*890232f2SAndroid Build Coastguard Worker 
FlexibleStringConstructor(const FieldDef * field)822*890232f2SAndroid Build Coastguard Worker   bool FlexibleStringConstructor(const FieldDef *field) {
823*890232f2SAndroid Build Coastguard Worker     auto attr = field
824*890232f2SAndroid Build Coastguard Worker                     ? (field->attributes.Lookup("cpp_str_flex_ctor") != nullptr)
825*890232f2SAndroid Build Coastguard Worker                     : false;
826*890232f2SAndroid Build Coastguard Worker     auto ret = attr ? attr : opts_.cpp_object_api_string_flexible_constructor;
827*890232f2SAndroid Build Coastguard Worker     return ret && NativeString(field) !=
828*890232f2SAndroid Build Coastguard Worker                       "std::string";  // Only for custom string types.
829*890232f2SAndroid Build Coastguard Worker   }
830*890232f2SAndroid Build Coastguard Worker 
GenTypeNativePtr(const std::string & type,const FieldDef * field,bool is_constructor)831*890232f2SAndroid Build Coastguard Worker   std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
832*890232f2SAndroid Build Coastguard Worker                                bool is_constructor) {
833*890232f2SAndroid Build Coastguard Worker     auto &ptr_type = PtrType(field);
834*890232f2SAndroid Build Coastguard Worker     if (ptr_type != "naked") {
835*890232f2SAndroid Build Coastguard Worker       return (ptr_type != "default_ptr_type"
836*890232f2SAndroid Build Coastguard Worker                   ? ptr_type
837*890232f2SAndroid Build Coastguard Worker                   : opts_.cpp_object_api_pointer_type) +
838*890232f2SAndroid Build Coastguard Worker              "<" + type + ">";
839*890232f2SAndroid Build Coastguard Worker     } else if (is_constructor) {
840*890232f2SAndroid Build Coastguard Worker       return "";
841*890232f2SAndroid Build Coastguard Worker     } else {
842*890232f2SAndroid Build Coastguard Worker       return type + " *";
843*890232f2SAndroid Build Coastguard Worker     }
844*890232f2SAndroid Build Coastguard Worker   }
845*890232f2SAndroid Build Coastguard Worker 
GenPtrGet(const FieldDef & field)846*890232f2SAndroid Build Coastguard Worker   std::string GenPtrGet(const FieldDef &field) {
847*890232f2SAndroid Build Coastguard Worker     auto cpp_ptr_type_get = field.attributes.Lookup("cpp_ptr_type_get");
848*890232f2SAndroid Build Coastguard Worker     if (cpp_ptr_type_get) return cpp_ptr_type_get->constant;
849*890232f2SAndroid Build Coastguard Worker     auto &ptr_type = PtrType(&field);
850*890232f2SAndroid Build Coastguard Worker     return ptr_type == "naked" ? "" : ".get()";
851*890232f2SAndroid Build Coastguard Worker   }
852*890232f2SAndroid Build Coastguard Worker 
GenOptionalNull()853*890232f2SAndroid Build Coastguard Worker   std::string GenOptionalNull() { return "flatbuffers::nullopt"; }
854*890232f2SAndroid Build Coastguard Worker 
GenOptionalDecl(const Type & type)855*890232f2SAndroid Build Coastguard Worker   std::string GenOptionalDecl(const Type &type) {
856*890232f2SAndroid Build Coastguard Worker     return "flatbuffers::Optional<" + GenTypeBasic(type, true) + ">";
857*890232f2SAndroid Build Coastguard Worker   }
858*890232f2SAndroid Build Coastguard Worker 
GenTypeNative(const Type & type,bool invector,const FieldDef & field,bool forcopy=false)859*890232f2SAndroid Build Coastguard Worker   std::string GenTypeNative(const Type &type, bool invector,
860*890232f2SAndroid Build Coastguard Worker                             const FieldDef &field, bool forcopy = false) {
861*890232f2SAndroid Build Coastguard Worker     switch (type.base_type) {
862*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRING: {
863*890232f2SAndroid Build Coastguard Worker         return NativeString(&field);
864*890232f2SAndroid Build Coastguard Worker       }
865*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_VECTOR: {
866*890232f2SAndroid Build Coastguard Worker         const auto type_name = GenTypeNative(type.VectorType(), true, field);
867*890232f2SAndroid Build Coastguard Worker         if (type.struct_def &&
868*890232f2SAndroid Build Coastguard Worker             type.struct_def->attributes.Lookup("native_custom_alloc")) {
869*890232f2SAndroid Build Coastguard Worker           auto native_custom_alloc =
870*890232f2SAndroid Build Coastguard Worker               type.struct_def->attributes.Lookup("native_custom_alloc");
871*890232f2SAndroid Build Coastguard Worker           return "std::vector<" + type_name + "," +
872*890232f2SAndroid Build Coastguard Worker                  native_custom_alloc->constant + "<" + type_name + ">>";
873*890232f2SAndroid Build Coastguard Worker         } else
874*890232f2SAndroid Build Coastguard Worker           return "std::vector<" + type_name + ">";
875*890232f2SAndroid Build Coastguard Worker       }
876*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRUCT: {
877*890232f2SAndroid Build Coastguard Worker         auto type_name = WrapInNameSpace(*type.struct_def);
878*890232f2SAndroid Build Coastguard Worker         if (IsStruct(type)) {
879*890232f2SAndroid Build Coastguard Worker           auto native_type = type.struct_def->attributes.Lookup("native_type");
880*890232f2SAndroid Build Coastguard Worker           if (native_type) { type_name = native_type->constant; }
881*890232f2SAndroid Build Coastguard Worker           if (invector || field.native_inline || forcopy) {
882*890232f2SAndroid Build Coastguard Worker             return type_name;
883*890232f2SAndroid Build Coastguard Worker           } else {
884*890232f2SAndroid Build Coastguard Worker             return GenTypeNativePtr(type_name, &field, false);
885*890232f2SAndroid Build Coastguard Worker           }
886*890232f2SAndroid Build Coastguard Worker         } else {
887*890232f2SAndroid Build Coastguard Worker           const auto nn = WrapNativeNameInNameSpace(*type.struct_def, opts_);
888*890232f2SAndroid Build Coastguard Worker           return forcopy ? nn : GenTypeNativePtr(nn, &field, false);
889*890232f2SAndroid Build Coastguard Worker         }
890*890232f2SAndroid Build Coastguard Worker       }
891*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UNION: {
892*890232f2SAndroid Build Coastguard Worker         auto type_name = WrapInNameSpace(*type.enum_def);
893*890232f2SAndroid Build Coastguard Worker         return type_name + "Union";
894*890232f2SAndroid Build Coastguard Worker       }
895*890232f2SAndroid Build Coastguard Worker       default: {
896*890232f2SAndroid Build Coastguard Worker         return field.IsScalarOptional() ? GenOptionalDecl(type)
897*890232f2SAndroid Build Coastguard Worker                                         : GenTypeBasic(type, true);
898*890232f2SAndroid Build Coastguard Worker       }
899*890232f2SAndroid Build Coastguard Worker     }
900*890232f2SAndroid Build Coastguard Worker   }
901*890232f2SAndroid Build Coastguard Worker 
902*890232f2SAndroid Build Coastguard Worker   // Return a C++ type for any type (scalar/pointer) specifically for
903*890232f2SAndroid Build Coastguard Worker   // using a flatbuffer.
GenTypeGet(const Type & type,const char * afterbasic,const char * beforeptr,const char * afterptr,bool user_facing_type)904*890232f2SAndroid Build Coastguard Worker   std::string GenTypeGet(const Type &type, const char *afterbasic,
905*890232f2SAndroid Build Coastguard Worker                          const char *beforeptr, const char *afterptr,
906*890232f2SAndroid Build Coastguard Worker                          bool user_facing_type) {
907*890232f2SAndroid Build Coastguard Worker     if (IsScalar(type.base_type)) {
908*890232f2SAndroid Build Coastguard Worker       return GenTypeBasic(type, user_facing_type) + afterbasic;
909*890232f2SAndroid Build Coastguard Worker     } else if (IsArray(type)) {
910*890232f2SAndroid Build Coastguard Worker       auto element_type = type.VectorType();
911*890232f2SAndroid Build Coastguard Worker       // Check if enum arrays are used in C++ without specifying --scoped-enums
912*890232f2SAndroid Build Coastguard Worker       if (IsEnum(element_type) && !opts_.g_only_fixed_enums) {
913*890232f2SAndroid Build Coastguard Worker         LogCompilerError(
914*890232f2SAndroid Build Coastguard Worker             "--scoped-enums must be enabled to use enum arrays in C++");
915*890232f2SAndroid Build Coastguard Worker         FLATBUFFERS_ASSERT(true);
916*890232f2SAndroid Build Coastguard Worker       }
917*890232f2SAndroid Build Coastguard Worker       return beforeptr +
918*890232f2SAndroid Build Coastguard Worker              (IsScalar(element_type.base_type)
919*890232f2SAndroid Build Coastguard Worker                   ? GenTypeBasic(element_type, user_facing_type)
920*890232f2SAndroid Build Coastguard Worker                   : GenTypePointer(element_type)) +
921*890232f2SAndroid Build Coastguard Worker              afterptr;
922*890232f2SAndroid Build Coastguard Worker     } else {
923*890232f2SAndroid Build Coastguard Worker       return beforeptr + GenTypePointer(type) + afterptr;
924*890232f2SAndroid Build Coastguard Worker     }
925*890232f2SAndroid Build Coastguard Worker   }
926*890232f2SAndroid Build Coastguard Worker 
GenTypeSpan(const Type & type,bool immutable,size_t extent)927*890232f2SAndroid Build Coastguard Worker   std::string GenTypeSpan(const Type &type, bool immutable, size_t extent) {
928*890232f2SAndroid Build Coastguard Worker     // Generate "flatbuffers::span<const U, extent>".
929*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(IsSeries(type) && "unexpected type");
930*890232f2SAndroid Build Coastguard Worker     auto element_type = type.VectorType();
931*890232f2SAndroid Build Coastguard Worker     std::string text = "flatbuffers::span<";
932*890232f2SAndroid Build Coastguard Worker     text += immutable ? "const " : "";
933*890232f2SAndroid Build Coastguard Worker     if (IsScalar(element_type.base_type)) {
934*890232f2SAndroid Build Coastguard Worker       text += GenTypeBasic(element_type, IsEnum(element_type));
935*890232f2SAndroid Build Coastguard Worker     } else {
936*890232f2SAndroid Build Coastguard Worker       switch (element_type.base_type) {
937*890232f2SAndroid Build Coastguard Worker         case BASE_TYPE_STRING: {
938*890232f2SAndroid Build Coastguard Worker           text += "char";
939*890232f2SAndroid Build Coastguard Worker           break;
940*890232f2SAndroid Build Coastguard Worker         }
941*890232f2SAndroid Build Coastguard Worker         case BASE_TYPE_STRUCT: {
942*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT(type.struct_def);
943*890232f2SAndroid Build Coastguard Worker           text += WrapInNameSpace(*type.struct_def);
944*890232f2SAndroid Build Coastguard Worker           break;
945*890232f2SAndroid Build Coastguard Worker         }
946*890232f2SAndroid Build Coastguard Worker         default:
947*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT(false && "unexpected element's type");
948*890232f2SAndroid Build Coastguard Worker           break;
949*890232f2SAndroid Build Coastguard Worker       }
950*890232f2SAndroid Build Coastguard Worker     }
951*890232f2SAndroid Build Coastguard Worker     if (extent != flatbuffers::dynamic_extent) {
952*890232f2SAndroid Build Coastguard Worker       text += ", ";
953*890232f2SAndroid Build Coastguard Worker       text += NumToString(extent);
954*890232f2SAndroid Build Coastguard Worker     }
955*890232f2SAndroid Build Coastguard Worker     text += "> ";
956*890232f2SAndroid Build Coastguard Worker     return text;
957*890232f2SAndroid Build Coastguard Worker   }
958*890232f2SAndroid Build Coastguard Worker 
GenEnumValDecl(const EnumDef & enum_def,const std::string & enum_val) const959*890232f2SAndroid Build Coastguard Worker   std::string GenEnumValDecl(const EnumDef &enum_def,
960*890232f2SAndroid Build Coastguard Worker                              const std::string &enum_val) const {
961*890232f2SAndroid Build Coastguard Worker     return opts_.prefixed_enums ? Name(enum_def) + "_" + enum_val : enum_val;
962*890232f2SAndroid Build Coastguard Worker   }
963*890232f2SAndroid Build Coastguard Worker 
GetEnumValUse(const EnumDef & enum_def,const EnumVal & enum_val) const964*890232f2SAndroid Build Coastguard Worker   std::string GetEnumValUse(const EnumDef &enum_def,
965*890232f2SAndroid Build Coastguard Worker                             const EnumVal &enum_val) const {
966*890232f2SAndroid Build Coastguard Worker     if (opts_.scoped_enums) {
967*890232f2SAndroid Build Coastguard Worker       return Name(enum_def) + "::" + Name(enum_val);
968*890232f2SAndroid Build Coastguard Worker     } else if (opts_.prefixed_enums) {
969*890232f2SAndroid Build Coastguard Worker       return Name(enum_def) + "_" + Name(enum_val);
970*890232f2SAndroid Build Coastguard Worker     } else {
971*890232f2SAndroid Build Coastguard Worker       return Name(enum_val);
972*890232f2SAndroid Build Coastguard Worker     }
973*890232f2SAndroid Build Coastguard Worker   }
974*890232f2SAndroid Build Coastguard Worker 
StripUnionType(const std::string & name)975*890232f2SAndroid Build Coastguard Worker   std::string StripUnionType(const std::string &name) {
976*890232f2SAndroid Build Coastguard Worker     return name.substr(0, name.size() - strlen(UnionTypeFieldSuffix()));
977*890232f2SAndroid Build Coastguard Worker   }
978*890232f2SAndroid Build Coastguard Worker 
GetUnionElement(const EnumVal & ev,bool native_type,const IDLOptions & opts)979*890232f2SAndroid Build Coastguard Worker   std::string GetUnionElement(const EnumVal &ev, bool native_type,
980*890232f2SAndroid Build Coastguard Worker                               const IDLOptions &opts) {
981*890232f2SAndroid Build Coastguard Worker     if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
982*890232f2SAndroid Build Coastguard Worker       auto name = ev.union_type.struct_def->name;
983*890232f2SAndroid Build Coastguard Worker       if (native_type) {
984*890232f2SAndroid Build Coastguard Worker         name = NativeName(name, ev.union_type.struct_def, opts);
985*890232f2SAndroid Build Coastguard Worker       }
986*890232f2SAndroid Build Coastguard Worker       return WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name);
987*890232f2SAndroid Build Coastguard Worker     } else if (IsString(ev.union_type)) {
988*890232f2SAndroid Build Coastguard Worker       return native_type ? "std::string" : "flatbuffers::String";
989*890232f2SAndroid Build Coastguard Worker     } else {
990*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(false);
991*890232f2SAndroid Build Coastguard Worker       return Name(ev);
992*890232f2SAndroid Build Coastguard Worker     }
993*890232f2SAndroid Build Coastguard Worker   }
994*890232f2SAndroid Build Coastguard Worker 
UnionVerifySignature(const EnumDef & enum_def)995*890232f2SAndroid Build Coastguard Worker   std::string UnionVerifySignature(const EnumDef &enum_def) {
996*890232f2SAndroid Build Coastguard Worker     return "bool Verify" + Name(enum_def) +
997*890232f2SAndroid Build Coastguard Worker            "(flatbuffers::Verifier &verifier, const void *obj, " +
998*890232f2SAndroid Build Coastguard Worker            Name(enum_def) + " type)";
999*890232f2SAndroid Build Coastguard Worker   }
1000*890232f2SAndroid Build Coastguard Worker 
UnionVectorVerifySignature(const EnumDef & enum_def)1001*890232f2SAndroid Build Coastguard Worker   std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
1002*890232f2SAndroid Build Coastguard Worker     auto name = Name(enum_def);
1003*890232f2SAndroid Build Coastguard Worker     auto type = opts_.scoped_enums ? name : "uint8_t";
1004*890232f2SAndroid Build Coastguard Worker     return "bool Verify" + name + "Vector" +
1005*890232f2SAndroid Build Coastguard Worker            "(flatbuffers::Verifier &verifier, " +
1006*890232f2SAndroid Build Coastguard Worker            "const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " +
1007*890232f2SAndroid Build Coastguard Worker            "const flatbuffers::Vector<" + type + "> *types)";
1008*890232f2SAndroid Build Coastguard Worker   }
1009*890232f2SAndroid Build Coastguard Worker 
UnionUnPackSignature(const EnumDef & enum_def,bool inclass)1010*890232f2SAndroid Build Coastguard Worker   std::string UnionUnPackSignature(const EnumDef &enum_def, bool inclass) {
1011*890232f2SAndroid Build Coastguard Worker     return (inclass ? "static " : "") + std::string("void *") +
1012*890232f2SAndroid Build Coastguard Worker            (inclass ? "" : Name(enum_def) + "Union::") +
1013*890232f2SAndroid Build Coastguard Worker            "UnPack(const void *obj, " + Name(enum_def) +
1014*890232f2SAndroid Build Coastguard Worker            " type, const flatbuffers::resolver_function_t *resolver)";
1015*890232f2SAndroid Build Coastguard Worker   }
1016*890232f2SAndroid Build Coastguard Worker 
UnionPackSignature(const EnumDef & enum_def,bool inclass)1017*890232f2SAndroid Build Coastguard Worker   std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) {
1018*890232f2SAndroid Build Coastguard Worker     return "flatbuffers::Offset<void> " +
1019*890232f2SAndroid Build Coastguard Worker            (inclass ? "" : Name(enum_def) + "Union::") +
1020*890232f2SAndroid Build Coastguard Worker            "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
1021*890232f2SAndroid Build Coastguard Worker            "const flatbuffers::rehasher_function_t *_rehasher" +
1022*890232f2SAndroid Build Coastguard Worker            (inclass ? " = nullptr" : "") + ") const";
1023*890232f2SAndroid Build Coastguard Worker   }
1024*890232f2SAndroid Build Coastguard Worker 
TableCreateSignature(const StructDef & struct_def,bool predecl,const IDLOptions & opts)1025*890232f2SAndroid Build Coastguard Worker   std::string TableCreateSignature(const StructDef &struct_def, bool predecl,
1026*890232f2SAndroid Build Coastguard Worker                                    const IDLOptions &opts) {
1027*890232f2SAndroid Build Coastguard Worker     return "flatbuffers::Offset<" + Name(struct_def) + "> Create" +
1028*890232f2SAndroid Build Coastguard Worker            Name(struct_def) + "(flatbuffers::FlatBufferBuilder &_fbb, const " +
1029*890232f2SAndroid Build Coastguard Worker            NativeName(Name(struct_def), &struct_def, opts) +
1030*890232f2SAndroid Build Coastguard Worker            " *_o, const flatbuffers::rehasher_function_t *_rehasher" +
1031*890232f2SAndroid Build Coastguard Worker            (predecl ? " = nullptr" : "") + ")";
1032*890232f2SAndroid Build Coastguard Worker   }
1033*890232f2SAndroid Build Coastguard Worker 
TablePackSignature(const StructDef & struct_def,bool inclass,const IDLOptions & opts)1034*890232f2SAndroid Build Coastguard Worker   std::string TablePackSignature(const StructDef &struct_def, bool inclass,
1035*890232f2SAndroid Build Coastguard Worker                                  const IDLOptions &opts) {
1036*890232f2SAndroid Build Coastguard Worker     return std::string(inclass ? "static " : "") + "flatbuffers::Offset<" +
1037*890232f2SAndroid Build Coastguard Worker            Name(struct_def) + "> " + (inclass ? "" : Name(struct_def) + "::") +
1038*890232f2SAndroid Build Coastguard Worker            "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "const " +
1039*890232f2SAndroid Build Coastguard Worker            NativeName(Name(struct_def), &struct_def, opts) + "* _o, " +
1040*890232f2SAndroid Build Coastguard Worker            "const flatbuffers::rehasher_function_t *_rehasher" +
1041*890232f2SAndroid Build Coastguard Worker            (inclass ? " = nullptr" : "") + ")";
1042*890232f2SAndroid Build Coastguard Worker   }
1043*890232f2SAndroid Build Coastguard Worker 
TableUnPackSignature(const StructDef & struct_def,bool inclass,const IDLOptions & opts)1044*890232f2SAndroid Build Coastguard Worker   std::string TableUnPackSignature(const StructDef &struct_def, bool inclass,
1045*890232f2SAndroid Build Coastguard Worker                                    const IDLOptions &opts) {
1046*890232f2SAndroid Build Coastguard Worker     return NativeName(Name(struct_def), &struct_def, opts) + " *" +
1047*890232f2SAndroid Build Coastguard Worker            (inclass ? "" : Name(struct_def) + "::") +
1048*890232f2SAndroid Build Coastguard Worker            "UnPack(const flatbuffers::resolver_function_t *_resolver" +
1049*890232f2SAndroid Build Coastguard Worker            (inclass ? " = nullptr" : "") + ") const";
1050*890232f2SAndroid Build Coastguard Worker   }
1051*890232f2SAndroid Build Coastguard Worker 
TableUnPackToSignature(const StructDef & struct_def,bool inclass,const IDLOptions & opts)1052*890232f2SAndroid Build Coastguard Worker   std::string TableUnPackToSignature(const StructDef &struct_def, bool inclass,
1053*890232f2SAndroid Build Coastguard Worker                                      const IDLOptions &opts) {
1054*890232f2SAndroid Build Coastguard Worker     return "void " + (inclass ? "" : Name(struct_def) + "::") + "UnPackTo(" +
1055*890232f2SAndroid Build Coastguard Worker            NativeName(Name(struct_def), &struct_def, opts) + " *" +
1056*890232f2SAndroid Build Coastguard Worker            "_o, const flatbuffers::resolver_function_t *_resolver" +
1057*890232f2SAndroid Build Coastguard Worker            (inclass ? " = nullptr" : "") + ") const";
1058*890232f2SAndroid Build Coastguard Worker   }
1059*890232f2SAndroid Build Coastguard Worker 
GenMiniReflectPre(const StructDef * struct_def)1060*890232f2SAndroid Build Coastguard Worker   void GenMiniReflectPre(const StructDef *struct_def) {
1061*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NAME", struct_def->name);
1062*890232f2SAndroid Build Coastguard Worker     code_ += "inline const flatbuffers::TypeTable *{{NAME}}TypeTable();";
1063*890232f2SAndroid Build Coastguard Worker     code_ += "";
1064*890232f2SAndroid Build Coastguard Worker   }
1065*890232f2SAndroid Build Coastguard Worker 
GenMiniReflect(const StructDef * struct_def,const EnumDef * enum_def)1066*890232f2SAndroid Build Coastguard Worker   void GenMiniReflect(const StructDef *struct_def, const EnumDef *enum_def) {
1067*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NAME", struct_def ? struct_def->name : enum_def->name);
1068*890232f2SAndroid Build Coastguard Worker     code_.SetValue("SEQ_TYPE",
1069*890232f2SAndroid Build Coastguard Worker                    struct_def ? (struct_def->fixed ? "ST_STRUCT" : "ST_TABLE")
1070*890232f2SAndroid Build Coastguard Worker                               : (enum_def->is_union ? "ST_UNION" : "ST_ENUM"));
1071*890232f2SAndroid Build Coastguard Worker     auto num_fields =
1072*890232f2SAndroid Build Coastguard Worker         struct_def ? struct_def->fields.vec.size() : enum_def->size();
1073*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NUM_FIELDS", NumToString(num_fields));
1074*890232f2SAndroid Build Coastguard Worker     std::vector<std::string> names;
1075*890232f2SAndroid Build Coastguard Worker     std::vector<Type> types;
1076*890232f2SAndroid Build Coastguard Worker 
1077*890232f2SAndroid Build Coastguard Worker     if (struct_def) {
1078*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def->fields.vec.begin();
1079*890232f2SAndroid Build Coastguard Worker            it != struct_def->fields.vec.end(); ++it) {
1080*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
1081*890232f2SAndroid Build Coastguard Worker         names.push_back(Name(field));
1082*890232f2SAndroid Build Coastguard Worker         types.push_back(field.value.type);
1083*890232f2SAndroid Build Coastguard Worker       }
1084*890232f2SAndroid Build Coastguard Worker     } else {
1085*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
1086*890232f2SAndroid Build Coastguard Worker            ++it) {
1087*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1088*890232f2SAndroid Build Coastguard Worker         names.push_back(Name(ev));
1089*890232f2SAndroid Build Coastguard Worker         types.push_back(enum_def->is_union ? ev.union_type
1090*890232f2SAndroid Build Coastguard Worker                                            : Type(enum_def->underlying_type));
1091*890232f2SAndroid Build Coastguard Worker       }
1092*890232f2SAndroid Build Coastguard Worker     }
1093*890232f2SAndroid Build Coastguard Worker     std::string ts;
1094*890232f2SAndroid Build Coastguard Worker     std::vector<std::string> type_refs;
1095*890232f2SAndroid Build Coastguard Worker     std::vector<uint16_t> array_sizes;
1096*890232f2SAndroid Build Coastguard Worker     for (auto it = types.begin(); it != types.end(); ++it) {
1097*890232f2SAndroid Build Coastguard Worker       auto &type = *it;
1098*890232f2SAndroid Build Coastguard Worker       if (!ts.empty()) ts += ",\n    ";
1099*890232f2SAndroid Build Coastguard Worker       auto is_vector = IsVector(type);
1100*890232f2SAndroid Build Coastguard Worker       auto is_array = IsArray(type);
1101*890232f2SAndroid Build Coastguard Worker       auto bt = is_vector || is_array ? type.element : type.base_type;
1102*890232f2SAndroid Build Coastguard Worker       auto et = IsScalar(bt) || bt == BASE_TYPE_STRING
1103*890232f2SAndroid Build Coastguard Worker                     ? bt - BASE_TYPE_UTYPE + ET_UTYPE
1104*890232f2SAndroid Build Coastguard Worker                     : ET_SEQUENCE;
1105*890232f2SAndroid Build Coastguard Worker       int ref_idx = -1;
1106*890232f2SAndroid Build Coastguard Worker       std::string ref_name = type.struct_def ? WrapInNameSpace(*type.struct_def)
1107*890232f2SAndroid Build Coastguard Worker                              : type.enum_def ? WrapInNameSpace(*type.enum_def)
1108*890232f2SAndroid Build Coastguard Worker                                              : "";
1109*890232f2SAndroid Build Coastguard Worker       if (!ref_name.empty()) {
1110*890232f2SAndroid Build Coastguard Worker         auto rit = type_refs.begin();
1111*890232f2SAndroid Build Coastguard Worker         for (; rit != type_refs.end(); ++rit) {
1112*890232f2SAndroid Build Coastguard Worker           if (*rit == ref_name) {
1113*890232f2SAndroid Build Coastguard Worker             ref_idx = static_cast<int>(rit - type_refs.begin());
1114*890232f2SAndroid Build Coastguard Worker             break;
1115*890232f2SAndroid Build Coastguard Worker           }
1116*890232f2SAndroid Build Coastguard Worker         }
1117*890232f2SAndroid Build Coastguard Worker         if (rit == type_refs.end()) {
1118*890232f2SAndroid Build Coastguard Worker           ref_idx = static_cast<int>(type_refs.size());
1119*890232f2SAndroid Build Coastguard Worker           type_refs.push_back(ref_name);
1120*890232f2SAndroid Build Coastguard Worker         }
1121*890232f2SAndroid Build Coastguard Worker       }
1122*890232f2SAndroid Build Coastguard Worker       if (is_array) { array_sizes.push_back(type.fixed_length); }
1123*890232f2SAndroid Build Coastguard Worker       ts += "{ flatbuffers::" + std::string(ElementaryTypeNames()[et]) + ", " +
1124*890232f2SAndroid Build Coastguard Worker             NumToString(is_vector || is_array) + ", " + NumToString(ref_idx) +
1125*890232f2SAndroid Build Coastguard Worker             " }";
1126*890232f2SAndroid Build Coastguard Worker     }
1127*890232f2SAndroid Build Coastguard Worker     std::string rs;
1128*890232f2SAndroid Build Coastguard Worker     for (auto it = type_refs.begin(); it != type_refs.end(); ++it) {
1129*890232f2SAndroid Build Coastguard Worker       if (!rs.empty()) rs += ",\n    ";
1130*890232f2SAndroid Build Coastguard Worker       rs += *it + "TypeTable";
1131*890232f2SAndroid Build Coastguard Worker     }
1132*890232f2SAndroid Build Coastguard Worker     std::string as;
1133*890232f2SAndroid Build Coastguard Worker     for (auto it = array_sizes.begin(); it != array_sizes.end(); ++it) {
1134*890232f2SAndroid Build Coastguard Worker       as += NumToString(*it);
1135*890232f2SAndroid Build Coastguard Worker       as += ", ";
1136*890232f2SAndroid Build Coastguard Worker     }
1137*890232f2SAndroid Build Coastguard Worker     std::string ns;
1138*890232f2SAndroid Build Coastguard Worker     for (auto it = names.begin(); it != names.end(); ++it) {
1139*890232f2SAndroid Build Coastguard Worker       if (!ns.empty()) ns += ",\n    ";
1140*890232f2SAndroid Build Coastguard Worker       ns += "\"" + *it + "\"";
1141*890232f2SAndroid Build Coastguard Worker     }
1142*890232f2SAndroid Build Coastguard Worker     std::string vs;
1143*890232f2SAndroid Build Coastguard Worker     const auto consecutive_enum_from_zero =
1144*890232f2SAndroid Build Coastguard Worker         enum_def && enum_def->MinValue()->IsZero() &&
1145*890232f2SAndroid Build Coastguard Worker         ((enum_def->size() - 1) == enum_def->Distance());
1146*890232f2SAndroid Build Coastguard Worker     if (enum_def && !consecutive_enum_from_zero) {
1147*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
1148*890232f2SAndroid Build Coastguard Worker            ++it) {
1149*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1150*890232f2SAndroid Build Coastguard Worker         if (!vs.empty()) vs += ", ";
1151*890232f2SAndroid Build Coastguard Worker         vs += NumToStringCpp(enum_def->ToString(ev),
1152*890232f2SAndroid Build Coastguard Worker                              enum_def->underlying_type.base_type);
1153*890232f2SAndroid Build Coastguard Worker       }
1154*890232f2SAndroid Build Coastguard Worker     } else if (struct_def && struct_def->fixed) {
1155*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def->fields.vec.begin();
1156*890232f2SAndroid Build Coastguard Worker            it != struct_def->fields.vec.end(); ++it) {
1157*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
1158*890232f2SAndroid Build Coastguard Worker         vs += NumToString(field.value.offset);
1159*890232f2SAndroid Build Coastguard Worker         vs += ", ";
1160*890232f2SAndroid Build Coastguard Worker       }
1161*890232f2SAndroid Build Coastguard Worker       vs += NumToString(struct_def->bytesize);
1162*890232f2SAndroid Build Coastguard Worker     }
1163*890232f2SAndroid Build Coastguard Worker     code_.SetValue("TYPES", ts);
1164*890232f2SAndroid Build Coastguard Worker     code_.SetValue("REFS", rs);
1165*890232f2SAndroid Build Coastguard Worker     code_.SetValue("ARRAYSIZES", as);
1166*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NAMES", ns);
1167*890232f2SAndroid Build Coastguard Worker     code_.SetValue("VALUES", vs);
1168*890232f2SAndroid Build Coastguard Worker     code_ += "inline const flatbuffers::TypeTable *{{NAME}}TypeTable() {";
1169*890232f2SAndroid Build Coastguard Worker     if (num_fields) {
1170*890232f2SAndroid Build Coastguard Worker       code_ += "  static const flatbuffers::TypeCode type_codes[] = {";
1171*890232f2SAndroid Build Coastguard Worker       code_ += "    {{TYPES}}";
1172*890232f2SAndroid Build Coastguard Worker       code_ += "  };";
1173*890232f2SAndroid Build Coastguard Worker     }
1174*890232f2SAndroid Build Coastguard Worker     if (!type_refs.empty()) {
1175*890232f2SAndroid Build Coastguard Worker       code_ += "  static const flatbuffers::TypeFunction type_refs[] = {";
1176*890232f2SAndroid Build Coastguard Worker       code_ += "    {{REFS}}";
1177*890232f2SAndroid Build Coastguard Worker       code_ += "  };";
1178*890232f2SAndroid Build Coastguard Worker     }
1179*890232f2SAndroid Build Coastguard Worker     if (!as.empty()) {
1180*890232f2SAndroid Build Coastguard Worker       code_ += "  static const int16_t array_sizes[] = { {{ARRAYSIZES}} };";
1181*890232f2SAndroid Build Coastguard Worker     }
1182*890232f2SAndroid Build Coastguard Worker     if (!vs.empty()) {
1183*890232f2SAndroid Build Coastguard Worker       // Problem with uint64_t values greater than 9223372036854775807ULL.
1184*890232f2SAndroid Build Coastguard Worker       code_ += "  static const int64_t values[] = { {{VALUES}} };";
1185*890232f2SAndroid Build Coastguard Worker     }
1186*890232f2SAndroid Build Coastguard Worker     auto has_names =
1187*890232f2SAndroid Build Coastguard Worker         num_fields && opts_.mini_reflect == IDLOptions::kTypesAndNames;
1188*890232f2SAndroid Build Coastguard Worker     if (has_names) {
1189*890232f2SAndroid Build Coastguard Worker       code_ += "  static const char * const names[] = {";
1190*890232f2SAndroid Build Coastguard Worker       code_ += "    {{NAMES}}";
1191*890232f2SAndroid Build Coastguard Worker       code_ += "  };";
1192*890232f2SAndroid Build Coastguard Worker     }
1193*890232f2SAndroid Build Coastguard Worker     code_ += "  static const flatbuffers::TypeTable tt = {";
1194*890232f2SAndroid Build Coastguard Worker     code_ += std::string("    flatbuffers::{{SEQ_TYPE}}, {{NUM_FIELDS}}, ") +
1195*890232f2SAndroid Build Coastguard Worker              (num_fields ? "type_codes, " : "nullptr, ") +
1196*890232f2SAndroid Build Coastguard Worker              (!type_refs.empty() ? "type_refs, " : "nullptr, ") +
1197*890232f2SAndroid Build Coastguard Worker              (!as.empty() ? "array_sizes, " : "nullptr, ") +
1198*890232f2SAndroid Build Coastguard Worker              (!vs.empty() ? "values, " : "nullptr, ") +
1199*890232f2SAndroid Build Coastguard Worker              (has_names ? "names" : "nullptr");
1200*890232f2SAndroid Build Coastguard Worker     code_ += "  };";
1201*890232f2SAndroid Build Coastguard Worker     code_ += "  return &tt;";
1202*890232f2SAndroid Build Coastguard Worker     code_ += "}";
1203*890232f2SAndroid Build Coastguard Worker     code_ += "";
1204*890232f2SAndroid Build Coastguard Worker   }
1205*890232f2SAndroid Build Coastguard Worker 
1206*890232f2SAndroid Build Coastguard Worker   // Generate an enum declaration,
1207*890232f2SAndroid Build Coastguard Worker   // an enum string lookup table,
1208*890232f2SAndroid Build Coastguard Worker   // and an enum array of values
1209*890232f2SAndroid Build Coastguard Worker 
GenEnum(const EnumDef & enum_def)1210*890232f2SAndroid Build Coastguard Worker   void GenEnum(const EnumDef &enum_def) {
1211*890232f2SAndroid Build Coastguard Worker     code_.SetValue("ENUM_NAME", Name(enum_def));
1212*890232f2SAndroid Build Coastguard Worker     code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
1213*890232f2SAndroid Build Coastguard Worker 
1214*890232f2SAndroid Build Coastguard Worker     GenComment(enum_def.doc_comment);
1215*890232f2SAndroid Build Coastguard Worker     code_ +=
1216*890232f2SAndroid Build Coastguard Worker         (opts_.scoped_enums ? "enum class " : "enum ") + Name(enum_def) + "\\";
1217*890232f2SAndroid Build Coastguard Worker     if (opts_.g_only_fixed_enums) { code_ += " : {{BASE_TYPE}}\\"; }
1218*890232f2SAndroid Build Coastguard Worker     code_ += " {";
1219*890232f2SAndroid Build Coastguard Worker 
1220*890232f2SAndroid Build Coastguard Worker     code_.SetValue("SEP", ",");
1221*890232f2SAndroid Build Coastguard Worker     auto add_sep = false;
1222*890232f2SAndroid Build Coastguard Worker     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1223*890232f2SAndroid Build Coastguard Worker       const auto &ev = **it;
1224*890232f2SAndroid Build Coastguard Worker       if (add_sep) code_ += "{{SEP}}";
1225*890232f2SAndroid Build Coastguard Worker       GenComment(ev.doc_comment, "  ");
1226*890232f2SAndroid Build Coastguard Worker       code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(ev)));
1227*890232f2SAndroid Build Coastguard Worker       code_.SetValue("VALUE",
1228*890232f2SAndroid Build Coastguard Worker                      NumToStringCpp(enum_def.ToString(ev),
1229*890232f2SAndroid Build Coastguard Worker                                     enum_def.underlying_type.base_type));
1230*890232f2SAndroid Build Coastguard Worker       code_ += "  {{KEY}} = {{VALUE}}\\";
1231*890232f2SAndroid Build Coastguard Worker       add_sep = true;
1232*890232f2SAndroid Build Coastguard Worker     }
1233*890232f2SAndroid Build Coastguard Worker     const EnumVal *minv = enum_def.MinValue();
1234*890232f2SAndroid Build Coastguard Worker     const EnumVal *maxv = enum_def.MaxValue();
1235*890232f2SAndroid Build Coastguard Worker 
1236*890232f2SAndroid Build Coastguard Worker     if (opts_.scoped_enums || opts_.prefixed_enums) {
1237*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(minv && maxv);
1238*890232f2SAndroid Build Coastguard Worker 
1239*890232f2SAndroid Build Coastguard Worker       code_.SetValue("SEP", ",\n");
1240*890232f2SAndroid Build Coastguard Worker       if (enum_def.attributes.Lookup("bit_flags")) {
1241*890232f2SAndroid Build Coastguard Worker         code_.SetValue("KEY", GenEnumValDecl(enum_def, "NONE"));
1242*890232f2SAndroid Build Coastguard Worker         code_.SetValue("VALUE", "0");
1243*890232f2SAndroid Build Coastguard Worker         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
1244*890232f2SAndroid Build Coastguard Worker 
1245*890232f2SAndroid Build Coastguard Worker         code_.SetValue("KEY", GenEnumValDecl(enum_def, "ANY"));
1246*890232f2SAndroid Build Coastguard Worker         code_.SetValue("VALUE",
1247*890232f2SAndroid Build Coastguard Worker                        NumToStringCpp(enum_def.AllFlags(),
1248*890232f2SAndroid Build Coastguard Worker                                       enum_def.underlying_type.base_type));
1249*890232f2SAndroid Build Coastguard Worker         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
1250*890232f2SAndroid Build Coastguard Worker       } else {  // MIN & MAX are useless for bit_flags
1251*890232f2SAndroid Build Coastguard Worker         code_.SetValue("KEY", GenEnumValDecl(enum_def, "MIN"));
1252*890232f2SAndroid Build Coastguard Worker         code_.SetValue("VALUE", GenEnumValDecl(enum_def, Name(*minv)));
1253*890232f2SAndroid Build Coastguard Worker         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
1254*890232f2SAndroid Build Coastguard Worker 
1255*890232f2SAndroid Build Coastguard Worker         code_.SetValue("KEY", GenEnumValDecl(enum_def, "MAX"));
1256*890232f2SAndroid Build Coastguard Worker         code_.SetValue("VALUE", GenEnumValDecl(enum_def, Name(*maxv)));
1257*890232f2SAndroid Build Coastguard Worker         code_ += "{{SEP}}  {{KEY}} = {{VALUE}}\\";
1258*890232f2SAndroid Build Coastguard Worker       }
1259*890232f2SAndroid Build Coastguard Worker     }
1260*890232f2SAndroid Build Coastguard Worker     code_ += "";
1261*890232f2SAndroid Build Coastguard Worker     code_ += "};";
1262*890232f2SAndroid Build Coastguard Worker 
1263*890232f2SAndroid Build Coastguard Worker     if (opts_.scoped_enums && enum_def.attributes.Lookup("bit_flags")) {
1264*890232f2SAndroid Build Coastguard Worker       code_ +=
1265*890232f2SAndroid Build Coastguard Worker           "FLATBUFFERS_DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})";
1266*890232f2SAndroid Build Coastguard Worker     }
1267*890232f2SAndroid Build Coastguard Worker     code_ += "";
1268*890232f2SAndroid Build Coastguard Worker 
1269*890232f2SAndroid Build Coastguard Worker     // Generate an array of all enumeration values
1270*890232f2SAndroid Build Coastguard Worker     auto num_fields = NumToString(enum_def.size());
1271*890232f2SAndroid Build Coastguard Worker     code_ += "inline const {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" +
1272*890232f2SAndroid Build Coastguard Worker              num_fields + "] {";
1273*890232f2SAndroid Build Coastguard Worker     code_ += "  static const {{ENUM_NAME}} values[] = {";
1274*890232f2SAndroid Build Coastguard Worker     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1275*890232f2SAndroid Build Coastguard Worker       const auto &ev = **it;
1276*890232f2SAndroid Build Coastguard Worker       auto value = GetEnumValUse(enum_def, ev);
1277*890232f2SAndroid Build Coastguard Worker       auto suffix = *it != enum_def.Vals().back() ? "," : "";
1278*890232f2SAndroid Build Coastguard Worker       code_ += "    " + value + suffix;
1279*890232f2SAndroid Build Coastguard Worker     }
1280*890232f2SAndroid Build Coastguard Worker     code_ += "  };";
1281*890232f2SAndroid Build Coastguard Worker     code_ += "  return values;";
1282*890232f2SAndroid Build Coastguard Worker     code_ += "}";
1283*890232f2SAndroid Build Coastguard Worker     code_ += "";
1284*890232f2SAndroid Build Coastguard Worker 
1285*890232f2SAndroid Build Coastguard Worker     // Generate a generate string table for enum values.
1286*890232f2SAndroid Build Coastguard Worker     // Problem is, if values are very sparse that could generate really big
1287*890232f2SAndroid Build Coastguard Worker     // tables. Ideally in that case we generate a map lookup instead, but for
1288*890232f2SAndroid Build Coastguard Worker     // the moment we simply don't output a table at all.
1289*890232f2SAndroid Build Coastguard Worker     auto range = enum_def.Distance();
1290*890232f2SAndroid Build Coastguard Worker     // Average distance between values above which we consider a table
1291*890232f2SAndroid Build Coastguard Worker     // "too sparse". Change at will.
1292*890232f2SAndroid Build Coastguard Worker     static const uint64_t kMaxSparseness = 5;
1293*890232f2SAndroid Build Coastguard Worker     if (range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness) {
1294*890232f2SAndroid Build Coastguard Worker       code_ += "inline const char * const *EnumNames{{ENUM_NAME}}() {";
1295*890232f2SAndroid Build Coastguard Worker       code_ += "  static const char * const names[" +
1296*890232f2SAndroid Build Coastguard Worker                NumToString(range + 1 + 1) + "] = {";
1297*890232f2SAndroid Build Coastguard Worker 
1298*890232f2SAndroid Build Coastguard Worker       auto val = enum_def.Vals().front();
1299*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1300*890232f2SAndroid Build Coastguard Worker            ++it) {
1301*890232f2SAndroid Build Coastguard Worker         auto ev = *it;
1302*890232f2SAndroid Build Coastguard Worker         for (auto k = enum_def.Distance(val, ev); k > 1; --k) {
1303*890232f2SAndroid Build Coastguard Worker           code_ += "    \"\",";
1304*890232f2SAndroid Build Coastguard Worker         }
1305*890232f2SAndroid Build Coastguard Worker         val = ev;
1306*890232f2SAndroid Build Coastguard Worker         code_ += "    \"" + Name(*ev) + "\",";
1307*890232f2SAndroid Build Coastguard Worker       }
1308*890232f2SAndroid Build Coastguard Worker       code_ += "    nullptr";
1309*890232f2SAndroid Build Coastguard Worker       code_ += "  };";
1310*890232f2SAndroid Build Coastguard Worker 
1311*890232f2SAndroid Build Coastguard Worker       code_ += "  return names;";
1312*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1313*890232f2SAndroid Build Coastguard Worker       code_ += "";
1314*890232f2SAndroid Build Coastguard Worker 
1315*890232f2SAndroid Build Coastguard Worker       code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
1316*890232f2SAndroid Build Coastguard Worker 
1317*890232f2SAndroid Build Coastguard Worker       code_ += "  if (flatbuffers::IsOutRange(e, " +
1318*890232f2SAndroid Build Coastguard Worker                GetEnumValUse(enum_def, *enum_def.MinValue()) + ", " +
1319*890232f2SAndroid Build Coastguard Worker                GetEnumValUse(enum_def, *enum_def.MaxValue()) +
1320*890232f2SAndroid Build Coastguard Worker                ")) return \"\";";
1321*890232f2SAndroid Build Coastguard Worker 
1322*890232f2SAndroid Build Coastguard Worker       code_ += "  const size_t index = static_cast<size_t>(e)\\";
1323*890232f2SAndroid Build Coastguard Worker       if (enum_def.MinValue()->IsNonZero()) {
1324*890232f2SAndroid Build Coastguard Worker         auto vals = GetEnumValUse(enum_def, *enum_def.MinValue());
1325*890232f2SAndroid Build Coastguard Worker         code_ += " - static_cast<size_t>(" + vals + ")\\";
1326*890232f2SAndroid Build Coastguard Worker       }
1327*890232f2SAndroid Build Coastguard Worker       code_ += ";";
1328*890232f2SAndroid Build Coastguard Worker 
1329*890232f2SAndroid Build Coastguard Worker       code_ += "  return EnumNames{{ENUM_NAME}}()[index];";
1330*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1331*890232f2SAndroid Build Coastguard Worker       code_ += "";
1332*890232f2SAndroid Build Coastguard Worker     } else {
1333*890232f2SAndroid Build Coastguard Worker       code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
1334*890232f2SAndroid Build Coastguard Worker 
1335*890232f2SAndroid Build Coastguard Worker       code_ += "  switch (e) {";
1336*890232f2SAndroid Build Coastguard Worker 
1337*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1338*890232f2SAndroid Build Coastguard Worker            ++it) {
1339*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1340*890232f2SAndroid Build Coastguard Worker         code_ += "    case " + GetEnumValUse(enum_def, ev) + ": return \"" +
1341*890232f2SAndroid Build Coastguard Worker                  Name(ev) + "\";";
1342*890232f2SAndroid Build Coastguard Worker       }
1343*890232f2SAndroid Build Coastguard Worker 
1344*890232f2SAndroid Build Coastguard Worker       code_ += "    default: return \"\";";
1345*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
1346*890232f2SAndroid Build Coastguard Worker 
1347*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1348*890232f2SAndroid Build Coastguard Worker       code_ += "";
1349*890232f2SAndroid Build Coastguard Worker     }
1350*890232f2SAndroid Build Coastguard Worker 
1351*890232f2SAndroid Build Coastguard Worker     // Generate type traits for unions to map from a type to union enum value.
1352*890232f2SAndroid Build Coastguard Worker     if (enum_def.is_union && !enum_def.uses_multiple_type_instances) {
1353*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1354*890232f2SAndroid Build Coastguard Worker            ++it) {
1355*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1356*890232f2SAndroid Build Coastguard Worker 
1357*890232f2SAndroid Build Coastguard Worker         if (it == enum_def.Vals().begin()) {
1358*890232f2SAndroid Build Coastguard Worker           code_ += "template<typename T> struct {{ENUM_NAME}}Traits {";
1359*890232f2SAndroid Build Coastguard Worker         } else {
1360*890232f2SAndroid Build Coastguard Worker           auto name = GetUnionElement(ev, false, opts_);
1361*890232f2SAndroid Build Coastguard Worker           code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {";
1362*890232f2SAndroid Build Coastguard Worker         }
1363*890232f2SAndroid Build Coastguard Worker 
1364*890232f2SAndroid Build Coastguard Worker         auto value = GetEnumValUse(enum_def, ev);
1365*890232f2SAndroid Build Coastguard Worker         code_ += "  static const {{ENUM_NAME}} enum_value = " + value + ";";
1366*890232f2SAndroid Build Coastguard Worker         code_ += "};";
1367*890232f2SAndroid Build Coastguard Worker         code_ += "";
1368*890232f2SAndroid Build Coastguard Worker       }
1369*890232f2SAndroid Build Coastguard Worker     }
1370*890232f2SAndroid Build Coastguard Worker 
1371*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api && enum_def.is_union) {
1372*890232f2SAndroid Build Coastguard Worker       // Generate a union type and a trait type for it.
1373*890232f2SAndroid Build Coastguard Worker       code_.SetValue("NAME", Name(enum_def));
1374*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(enum_def.Lookup("NONE"));
1375*890232f2SAndroid Build Coastguard Worker       code_.SetValue("NONE", GetEnumValUse(enum_def, *enum_def.Lookup("NONE")));
1376*890232f2SAndroid Build Coastguard Worker 
1377*890232f2SAndroid Build Coastguard Worker       if (!enum_def.uses_multiple_type_instances) {
1378*890232f2SAndroid Build Coastguard Worker         for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1379*890232f2SAndroid Build Coastguard Worker              ++it) {
1380*890232f2SAndroid Build Coastguard Worker           const auto &ev = **it;
1381*890232f2SAndroid Build Coastguard Worker 
1382*890232f2SAndroid Build Coastguard Worker           if (it == enum_def.Vals().begin()) {
1383*890232f2SAndroid Build Coastguard Worker             code_ += "template<typename T> struct {{NAME}}UnionTraits {";
1384*890232f2SAndroid Build Coastguard Worker           } else {
1385*890232f2SAndroid Build Coastguard Worker             auto name = GetUnionElement(ev, true, opts_);
1386*890232f2SAndroid Build Coastguard Worker             code_ += "template<> struct {{NAME}}UnionTraits<" + name + "> {";
1387*890232f2SAndroid Build Coastguard Worker           }
1388*890232f2SAndroid Build Coastguard Worker 
1389*890232f2SAndroid Build Coastguard Worker           auto value = GetEnumValUse(enum_def, ev);
1390*890232f2SAndroid Build Coastguard Worker           code_ += "  static const {{ENUM_NAME}} enum_value = " + value + ";";
1391*890232f2SAndroid Build Coastguard Worker           code_ += "};";
1392*890232f2SAndroid Build Coastguard Worker           code_ += "";
1393*890232f2SAndroid Build Coastguard Worker         }
1394*890232f2SAndroid Build Coastguard Worker       }
1395*890232f2SAndroid Build Coastguard Worker 
1396*890232f2SAndroid Build Coastguard Worker       code_ += "struct {{NAME}}Union {";
1397*890232f2SAndroid Build Coastguard Worker       code_ += "  {{NAME}} type;";
1398*890232f2SAndroid Build Coastguard Worker       code_ += "  void *value;";
1399*890232f2SAndroid Build Coastguard Worker       code_ += "";
1400*890232f2SAndroid Build Coastguard Worker       code_ += "  {{NAME}}Union() : type({{NONE}}), value(nullptr) {}";
1401*890232f2SAndroid Build Coastguard Worker       code_ += "  {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :";
1402*890232f2SAndroid Build Coastguard Worker       code_ += "    type({{NONE}}), value(nullptr)";
1403*890232f2SAndroid Build Coastguard Worker       code_ += "    { std::swap(type, u.type); std::swap(value, u.value); }";
1404*890232f2SAndroid Build Coastguard Worker       code_ += "  {{NAME}}Union(const {{NAME}}Union &);";
1405*890232f2SAndroid Build Coastguard Worker       code_ += "  {{NAME}}Union &operator=(const {{NAME}}Union &u)";
1406*890232f2SAndroid Build Coastguard Worker       code_ +=
1407*890232f2SAndroid Build Coastguard Worker           "    { {{NAME}}Union t(u); std::swap(type, t.type); std::swap(value, "
1408*890232f2SAndroid Build Coastguard Worker           "t.value); return *this; }";
1409*890232f2SAndroid Build Coastguard Worker       code_ +=
1410*890232f2SAndroid Build Coastguard Worker           "  {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT";
1411*890232f2SAndroid Build Coastguard Worker       code_ +=
1412*890232f2SAndroid Build Coastguard Worker           "    { std::swap(type, u.type); std::swap(value, u.value); return "
1413*890232f2SAndroid Build Coastguard Worker           "*this; }";
1414*890232f2SAndroid Build Coastguard Worker       code_ += "  ~{{NAME}}Union() { Reset(); }";
1415*890232f2SAndroid Build Coastguard Worker       code_ += "";
1416*890232f2SAndroid Build Coastguard Worker       code_ += "  void Reset();";
1417*890232f2SAndroid Build Coastguard Worker       code_ += "";
1418*890232f2SAndroid Build Coastguard Worker       if (!enum_def.uses_multiple_type_instances) {
1419*890232f2SAndroid Build Coastguard Worker         code_ += "  template <typename T>";
1420*890232f2SAndroid Build Coastguard Worker         code_ += "  void Set(T&& val) {";
1421*890232f2SAndroid Build Coastguard Worker         code_ += "    typedef typename std::remove_reference<T>::type RT;";
1422*890232f2SAndroid Build Coastguard Worker         code_ += "    Reset();";
1423*890232f2SAndroid Build Coastguard Worker         code_ += "    type = {{NAME}}UnionTraits<RT>::enum_value;";
1424*890232f2SAndroid Build Coastguard Worker         code_ += "    if (type != {{NONE}}) {";
1425*890232f2SAndroid Build Coastguard Worker         code_ += "      value = new RT(std::forward<T>(val));";
1426*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1427*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
1428*890232f2SAndroid Build Coastguard Worker         code_ += "";
1429*890232f2SAndroid Build Coastguard Worker       }
1430*890232f2SAndroid Build Coastguard Worker       code_ += "  " + UnionUnPackSignature(enum_def, true) + ";";
1431*890232f2SAndroid Build Coastguard Worker       code_ += "  " + UnionPackSignature(enum_def, true) + ";";
1432*890232f2SAndroid Build Coastguard Worker       code_ += "";
1433*890232f2SAndroid Build Coastguard Worker 
1434*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1435*890232f2SAndroid Build Coastguard Worker            ++it) {
1436*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1437*890232f2SAndroid Build Coastguard Worker         if (ev.IsZero()) { continue; }
1438*890232f2SAndroid Build Coastguard Worker 
1439*890232f2SAndroid Build Coastguard Worker         const auto native_type = GetUnionElement(ev, true, opts_);
1440*890232f2SAndroid Build Coastguard Worker         code_.SetValue("NATIVE_TYPE", native_type);
1441*890232f2SAndroid Build Coastguard Worker         code_.SetValue("NATIVE_NAME", Name(ev));
1442*890232f2SAndroid Build Coastguard Worker         code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
1443*890232f2SAndroid Build Coastguard Worker 
1444*890232f2SAndroid Build Coastguard Worker         code_ += "  {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
1445*890232f2SAndroid Build Coastguard Worker         code_ += "    return type == {{NATIVE_ID}} ?";
1446*890232f2SAndroid Build Coastguard Worker         code_ += "      reinterpret_cast<{{NATIVE_TYPE}} *>(value) : nullptr;";
1447*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
1448*890232f2SAndroid Build Coastguard Worker 
1449*890232f2SAndroid Build Coastguard Worker         code_ += "  const {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() const {";
1450*890232f2SAndroid Build Coastguard Worker         code_ += "    return type == {{NATIVE_ID}} ?";
1451*890232f2SAndroid Build Coastguard Worker         code_ +=
1452*890232f2SAndroid Build Coastguard Worker             "      reinterpret_cast<const {{NATIVE_TYPE}} *>(value) : nullptr;";
1453*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
1454*890232f2SAndroid Build Coastguard Worker       }
1455*890232f2SAndroid Build Coastguard Worker       code_ += "};";
1456*890232f2SAndroid Build Coastguard Worker       code_ += "";
1457*890232f2SAndroid Build Coastguard Worker 
1458*890232f2SAndroid Build Coastguard Worker       if (opts_.gen_compare) {
1459*890232f2SAndroid Build Coastguard Worker         code_ += "";
1460*890232f2SAndroid Build Coastguard Worker         code_ +=
1461*890232f2SAndroid Build Coastguard Worker             "inline bool operator==(const {{NAME}}Union &lhs, const "
1462*890232f2SAndroid Build Coastguard Worker             "{{NAME}}Union &rhs) {";
1463*890232f2SAndroid Build Coastguard Worker         code_ += "  if (lhs.type != rhs.type) return false;";
1464*890232f2SAndroid Build Coastguard Worker         code_ += "  switch (lhs.type) {";
1465*890232f2SAndroid Build Coastguard Worker 
1466*890232f2SAndroid Build Coastguard Worker         for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1467*890232f2SAndroid Build Coastguard Worker              ++it) {
1468*890232f2SAndroid Build Coastguard Worker           const auto &ev = **it;
1469*890232f2SAndroid Build Coastguard Worker           code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
1470*890232f2SAndroid Build Coastguard Worker           if (ev.IsNonZero()) {
1471*890232f2SAndroid Build Coastguard Worker             const auto native_type = GetUnionElement(ev, true, opts_);
1472*890232f2SAndroid Build Coastguard Worker             code_.SetValue("NATIVE_TYPE", native_type);
1473*890232f2SAndroid Build Coastguard Worker             code_ += "    case {{NATIVE_ID}}: {";
1474*890232f2SAndroid Build Coastguard Worker             code_ +=
1475*890232f2SAndroid Build Coastguard Worker                 "      return *(reinterpret_cast<const {{NATIVE_TYPE}} "
1476*890232f2SAndroid Build Coastguard Worker                 "*>(lhs.value)) ==";
1477*890232f2SAndroid Build Coastguard Worker             code_ +=
1478*890232f2SAndroid Build Coastguard Worker                 "             *(reinterpret_cast<const {{NATIVE_TYPE}} "
1479*890232f2SAndroid Build Coastguard Worker                 "*>(rhs.value));";
1480*890232f2SAndroid Build Coastguard Worker             code_ += "    }";
1481*890232f2SAndroid Build Coastguard Worker           } else {
1482*890232f2SAndroid Build Coastguard Worker             code_ += "    case {{NATIVE_ID}}: {";
1483*890232f2SAndroid Build Coastguard Worker             code_ += "      return true;";  // "NONE" enum value.
1484*890232f2SAndroid Build Coastguard Worker             code_ += "    }";
1485*890232f2SAndroid Build Coastguard Worker           }
1486*890232f2SAndroid Build Coastguard Worker         }
1487*890232f2SAndroid Build Coastguard Worker         code_ += "    default: {";
1488*890232f2SAndroid Build Coastguard Worker         code_ += "      return false;";
1489*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1490*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
1491*890232f2SAndroid Build Coastguard Worker         code_ += "}";
1492*890232f2SAndroid Build Coastguard Worker 
1493*890232f2SAndroid Build Coastguard Worker         code_ += "";
1494*890232f2SAndroid Build Coastguard Worker         code_ +=
1495*890232f2SAndroid Build Coastguard Worker             "inline bool operator!=(const {{NAME}}Union &lhs, const "
1496*890232f2SAndroid Build Coastguard Worker             "{{NAME}}Union &rhs) {";
1497*890232f2SAndroid Build Coastguard Worker         code_ += "    return !(lhs == rhs);";
1498*890232f2SAndroid Build Coastguard Worker         code_ += "}";
1499*890232f2SAndroid Build Coastguard Worker         code_ += "";
1500*890232f2SAndroid Build Coastguard Worker       }
1501*890232f2SAndroid Build Coastguard Worker     }
1502*890232f2SAndroid Build Coastguard Worker 
1503*890232f2SAndroid Build Coastguard Worker     if (enum_def.is_union) {
1504*890232f2SAndroid Build Coastguard Worker       code_ += UnionVerifySignature(enum_def) + ";";
1505*890232f2SAndroid Build Coastguard Worker       code_ += UnionVectorVerifySignature(enum_def) + ";";
1506*890232f2SAndroid Build Coastguard Worker       code_ += "";
1507*890232f2SAndroid Build Coastguard Worker     }
1508*890232f2SAndroid Build Coastguard Worker   }
1509*890232f2SAndroid Build Coastguard Worker 
GenUnionPost(const EnumDef & enum_def)1510*890232f2SAndroid Build Coastguard Worker   void GenUnionPost(const EnumDef &enum_def) {
1511*890232f2SAndroid Build Coastguard Worker     // Generate a verifier function for this union that can be called by the
1512*890232f2SAndroid Build Coastguard Worker     // table verifier functions. It uses a switch case to select a specific
1513*890232f2SAndroid Build Coastguard Worker     // verifier function to call, this should be safe even if the union type
1514*890232f2SAndroid Build Coastguard Worker     // has been corrupted, since the verifiers will simply fail when called
1515*890232f2SAndroid Build Coastguard Worker     // on the wrong type.
1516*890232f2SAndroid Build Coastguard Worker     code_.SetValue("ENUM_NAME", Name(enum_def));
1517*890232f2SAndroid Build Coastguard Worker 
1518*890232f2SAndroid Build Coastguard Worker     code_ += "inline " + UnionVerifySignature(enum_def) + " {";
1519*890232f2SAndroid Build Coastguard Worker     code_ += "  switch (type) {";
1520*890232f2SAndroid Build Coastguard Worker     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1521*890232f2SAndroid Build Coastguard Worker       const auto &ev = **it;
1522*890232f2SAndroid Build Coastguard Worker       code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
1523*890232f2SAndroid Build Coastguard Worker 
1524*890232f2SAndroid Build Coastguard Worker       if (ev.IsNonZero()) {
1525*890232f2SAndroid Build Coastguard Worker         code_.SetValue("TYPE", GetUnionElement(ev, false, opts_));
1526*890232f2SAndroid Build Coastguard Worker         code_ += "    case {{LABEL}}: {";
1527*890232f2SAndroid Build Coastguard Worker         auto getptr =
1528*890232f2SAndroid Build Coastguard Worker             "      auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
1529*890232f2SAndroid Build Coastguard Worker         if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
1530*890232f2SAndroid Build Coastguard Worker           if (ev.union_type.struct_def->fixed) {
1531*890232f2SAndroid Build Coastguard Worker             code_.SetValue("ALIGN",
1532*890232f2SAndroid Build Coastguard Worker                            NumToString(ev.union_type.struct_def->minalign));
1533*890232f2SAndroid Build Coastguard Worker             code_ +=
1534*890232f2SAndroid Build Coastguard Worker                 "      return verifier.VerifyField<{{TYPE}}>("
1535*890232f2SAndroid Build Coastguard Worker                 "static_cast<const uint8_t *>(obj), 0, {{ALIGN}});";
1536*890232f2SAndroid Build Coastguard Worker           } else {
1537*890232f2SAndroid Build Coastguard Worker             code_ += getptr;
1538*890232f2SAndroid Build Coastguard Worker             code_ += "      return verifier.VerifyTable(ptr);";
1539*890232f2SAndroid Build Coastguard Worker           }
1540*890232f2SAndroid Build Coastguard Worker         } else if (IsString(ev.union_type)) {
1541*890232f2SAndroid Build Coastguard Worker           code_ += getptr;
1542*890232f2SAndroid Build Coastguard Worker           code_ += "      return verifier.VerifyString(ptr);";
1543*890232f2SAndroid Build Coastguard Worker         } else {
1544*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT(false);
1545*890232f2SAndroid Build Coastguard Worker         }
1546*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1547*890232f2SAndroid Build Coastguard Worker       } else {
1548*890232f2SAndroid Build Coastguard Worker         code_ += "    case {{LABEL}}: {";
1549*890232f2SAndroid Build Coastguard Worker         code_ += "      return true;";  // "NONE" enum value.
1550*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1551*890232f2SAndroid Build Coastguard Worker       }
1552*890232f2SAndroid Build Coastguard Worker     }
1553*890232f2SAndroid Build Coastguard Worker     code_ += "    default: return true;";  // unknown values are OK.
1554*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
1555*890232f2SAndroid Build Coastguard Worker     code_ += "}";
1556*890232f2SAndroid Build Coastguard Worker     code_ += "";
1557*890232f2SAndroid Build Coastguard Worker 
1558*890232f2SAndroid Build Coastguard Worker     code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
1559*890232f2SAndroid Build Coastguard Worker     code_ += "  if (!values || !types) return !values && !types;";
1560*890232f2SAndroid Build Coastguard Worker     code_ += "  if (values->size() != types->size()) return false;";
1561*890232f2SAndroid Build Coastguard Worker     code_ += "  for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {";
1562*890232f2SAndroid Build Coastguard Worker     code_ += "    if (!Verify" + Name(enum_def) + "(";
1563*890232f2SAndroid Build Coastguard Worker     code_ += "        verifier,  values->Get(i), types->GetEnum<" +
1564*890232f2SAndroid Build Coastguard Worker              Name(enum_def) + ">(i))) {";
1565*890232f2SAndroid Build Coastguard Worker     code_ += "      return false;";
1566*890232f2SAndroid Build Coastguard Worker     code_ += "    }";
1567*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
1568*890232f2SAndroid Build Coastguard Worker     code_ += "  return true;";
1569*890232f2SAndroid Build Coastguard Worker     code_ += "}";
1570*890232f2SAndroid Build Coastguard Worker     code_ += "";
1571*890232f2SAndroid Build Coastguard Worker 
1572*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) {
1573*890232f2SAndroid Build Coastguard Worker       // Generate union Unpack() and Pack() functions.
1574*890232f2SAndroid Build Coastguard Worker       code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {";
1575*890232f2SAndroid Build Coastguard Worker       code_ += "  (void)resolver;";
1576*890232f2SAndroid Build Coastguard Worker       code_ += "  switch (type) {";
1577*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1578*890232f2SAndroid Build Coastguard Worker            ++it) {
1579*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1580*890232f2SAndroid Build Coastguard Worker         if (ev.IsZero()) { continue; }
1581*890232f2SAndroid Build Coastguard Worker 
1582*890232f2SAndroid Build Coastguard Worker         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
1583*890232f2SAndroid Build Coastguard Worker         code_.SetValue("TYPE", GetUnionElement(ev, false, opts_));
1584*890232f2SAndroid Build Coastguard Worker         code_ += "    case {{LABEL}}: {";
1585*890232f2SAndroid Build Coastguard Worker         code_ += "      auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
1586*890232f2SAndroid Build Coastguard Worker         if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
1587*890232f2SAndroid Build Coastguard Worker           if (ev.union_type.struct_def->fixed) {
1588*890232f2SAndroid Build Coastguard Worker             code_ += "      return new " +
1589*890232f2SAndroid Build Coastguard Worker                      WrapInNameSpace(*ev.union_type.struct_def) + "(*ptr);";
1590*890232f2SAndroid Build Coastguard Worker           } else {
1591*890232f2SAndroid Build Coastguard Worker             code_ += "      return ptr->UnPack(resolver);";
1592*890232f2SAndroid Build Coastguard Worker           }
1593*890232f2SAndroid Build Coastguard Worker         } else if (IsString(ev.union_type)) {
1594*890232f2SAndroid Build Coastguard Worker           code_ += "      return new std::string(ptr->c_str(), ptr->size());";
1595*890232f2SAndroid Build Coastguard Worker         } else {
1596*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT(false);
1597*890232f2SAndroid Build Coastguard Worker         }
1598*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1599*890232f2SAndroid Build Coastguard Worker       }
1600*890232f2SAndroid Build Coastguard Worker       code_ += "    default: return nullptr;";
1601*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
1602*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1603*890232f2SAndroid Build Coastguard Worker       code_ += "";
1604*890232f2SAndroid Build Coastguard Worker 
1605*890232f2SAndroid Build Coastguard Worker       code_ += "inline " + UnionPackSignature(enum_def, false) + " {";
1606*890232f2SAndroid Build Coastguard Worker       code_ += "  (void)_rehasher;";
1607*890232f2SAndroid Build Coastguard Worker       code_ += "  switch (type) {";
1608*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1609*890232f2SAndroid Build Coastguard Worker            ++it) {
1610*890232f2SAndroid Build Coastguard Worker         auto &ev = **it;
1611*890232f2SAndroid Build Coastguard Worker         if (ev.IsZero()) { continue; }
1612*890232f2SAndroid Build Coastguard Worker 
1613*890232f2SAndroid Build Coastguard Worker         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
1614*890232f2SAndroid Build Coastguard Worker         code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
1615*890232f2SAndroid Build Coastguard Worker         code_ += "    case {{LABEL}}: {";
1616*890232f2SAndroid Build Coastguard Worker         code_ += "      auto ptr = reinterpret_cast<const {{TYPE}} *>(value);";
1617*890232f2SAndroid Build Coastguard Worker         if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
1618*890232f2SAndroid Build Coastguard Worker           if (ev.union_type.struct_def->fixed) {
1619*890232f2SAndroid Build Coastguard Worker             code_ += "      return _fbb.CreateStruct(*ptr).Union();";
1620*890232f2SAndroid Build Coastguard Worker           } else {
1621*890232f2SAndroid Build Coastguard Worker             code_.SetValue("NAME", ev.union_type.struct_def->name);
1622*890232f2SAndroid Build Coastguard Worker             code_ +=
1623*890232f2SAndroid Build Coastguard Worker                 "      return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
1624*890232f2SAndroid Build Coastguard Worker           }
1625*890232f2SAndroid Build Coastguard Worker         } else if (IsString(ev.union_type)) {
1626*890232f2SAndroid Build Coastguard Worker           code_ += "      return _fbb.CreateString(*ptr).Union();";
1627*890232f2SAndroid Build Coastguard Worker         } else {
1628*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT(false);
1629*890232f2SAndroid Build Coastguard Worker         }
1630*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1631*890232f2SAndroid Build Coastguard Worker       }
1632*890232f2SAndroid Build Coastguard Worker       code_ += "    default: return 0;";
1633*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
1634*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1635*890232f2SAndroid Build Coastguard Worker       code_ += "";
1636*890232f2SAndroid Build Coastguard Worker 
1637*890232f2SAndroid Build Coastguard Worker       // Union copy constructor
1638*890232f2SAndroid Build Coastguard Worker       code_ +=
1639*890232f2SAndroid Build Coastguard Worker           "inline {{ENUM_NAME}}Union::{{ENUM_NAME}}Union(const "
1640*890232f2SAndroid Build Coastguard Worker           "{{ENUM_NAME}}Union &u) : type(u.type), value(nullptr) {";
1641*890232f2SAndroid Build Coastguard Worker       code_ += "  switch (type) {";
1642*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1643*890232f2SAndroid Build Coastguard Worker            ++it) {
1644*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1645*890232f2SAndroid Build Coastguard Worker         if (ev.IsZero()) { continue; }
1646*890232f2SAndroid Build Coastguard Worker         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
1647*890232f2SAndroid Build Coastguard Worker         code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
1648*890232f2SAndroid Build Coastguard Worker         code_ += "    case {{LABEL}}: {";
1649*890232f2SAndroid Build Coastguard Worker         bool copyable = true;
1650*890232f2SAndroid Build Coastguard Worker         if (opts_.g_cpp_std < cpp::CPP_STD_11 &&
1651*890232f2SAndroid Build Coastguard Worker             ev.union_type.base_type == BASE_TYPE_STRUCT &&
1652*890232f2SAndroid Build Coastguard Worker             !ev.union_type.struct_def->fixed) {
1653*890232f2SAndroid Build Coastguard Worker           // Don't generate code to copy if table is not copyable.
1654*890232f2SAndroid Build Coastguard Worker           // TODO(wvo): make tables copyable instead.
1655*890232f2SAndroid Build Coastguard Worker           for (auto fit = ev.union_type.struct_def->fields.vec.begin();
1656*890232f2SAndroid Build Coastguard Worker                fit != ev.union_type.struct_def->fields.vec.end(); ++fit) {
1657*890232f2SAndroid Build Coastguard Worker             const auto &field = **fit;
1658*890232f2SAndroid Build Coastguard Worker             if (!field.deprecated && field.value.type.struct_def &&
1659*890232f2SAndroid Build Coastguard Worker                 !field.native_inline) {
1660*890232f2SAndroid Build Coastguard Worker               copyable = false;
1661*890232f2SAndroid Build Coastguard Worker               break;
1662*890232f2SAndroid Build Coastguard Worker             }
1663*890232f2SAndroid Build Coastguard Worker           }
1664*890232f2SAndroid Build Coastguard Worker         }
1665*890232f2SAndroid Build Coastguard Worker         if (copyable) {
1666*890232f2SAndroid Build Coastguard Worker           code_ +=
1667*890232f2SAndroid Build Coastguard Worker               "      value = new {{TYPE}}(*reinterpret_cast<{{TYPE}} *>"
1668*890232f2SAndroid Build Coastguard Worker               "(u.value));";
1669*890232f2SAndroid Build Coastguard Worker         } else {
1670*890232f2SAndroid Build Coastguard Worker           code_ +=
1671*890232f2SAndroid Build Coastguard Worker               "      FLATBUFFERS_ASSERT(false);  // {{TYPE}} not copyable.";
1672*890232f2SAndroid Build Coastguard Worker         }
1673*890232f2SAndroid Build Coastguard Worker         code_ += "      break;";
1674*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1675*890232f2SAndroid Build Coastguard Worker       }
1676*890232f2SAndroid Build Coastguard Worker       code_ += "    default:";
1677*890232f2SAndroid Build Coastguard Worker       code_ += "      break;";
1678*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
1679*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1680*890232f2SAndroid Build Coastguard Worker       code_ += "";
1681*890232f2SAndroid Build Coastguard Worker 
1682*890232f2SAndroid Build Coastguard Worker       // Union Reset() function.
1683*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(enum_def.Lookup("NONE"));
1684*890232f2SAndroid Build Coastguard Worker       code_.SetValue("NONE", GetEnumValUse(enum_def, *enum_def.Lookup("NONE")));
1685*890232f2SAndroid Build Coastguard Worker 
1686*890232f2SAndroid Build Coastguard Worker       code_ += "inline void {{ENUM_NAME}}Union::Reset() {";
1687*890232f2SAndroid Build Coastguard Worker       code_ += "  switch (type) {";
1688*890232f2SAndroid Build Coastguard Worker       for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1689*890232f2SAndroid Build Coastguard Worker            ++it) {
1690*890232f2SAndroid Build Coastguard Worker         const auto &ev = **it;
1691*890232f2SAndroid Build Coastguard Worker         if (ev.IsZero()) { continue; }
1692*890232f2SAndroid Build Coastguard Worker         code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
1693*890232f2SAndroid Build Coastguard Worker         code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
1694*890232f2SAndroid Build Coastguard Worker         code_ += "    case {{LABEL}}: {";
1695*890232f2SAndroid Build Coastguard Worker         code_ += "      auto ptr = reinterpret_cast<{{TYPE}} *>(value);";
1696*890232f2SAndroid Build Coastguard Worker         code_ += "      delete ptr;";
1697*890232f2SAndroid Build Coastguard Worker         code_ += "      break;";
1698*890232f2SAndroid Build Coastguard Worker         code_ += "    }";
1699*890232f2SAndroid Build Coastguard Worker       }
1700*890232f2SAndroid Build Coastguard Worker       code_ += "    default: break;";
1701*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
1702*890232f2SAndroid Build Coastguard Worker       code_ += "  value = nullptr;";
1703*890232f2SAndroid Build Coastguard Worker       code_ += "  type = {{NONE}};";
1704*890232f2SAndroid Build Coastguard Worker       code_ += "}";
1705*890232f2SAndroid Build Coastguard Worker       code_ += "";
1706*890232f2SAndroid Build Coastguard Worker     }
1707*890232f2SAndroid Build Coastguard Worker   }
1708*890232f2SAndroid Build Coastguard Worker 
1709*890232f2SAndroid Build Coastguard Worker   // Generates a value with optionally a cast applied if the field has a
1710*890232f2SAndroid Build Coastguard Worker   // different underlying type from its interface type (currently only the
1711*890232f2SAndroid Build Coastguard Worker   // case for enums. "from" specify the direction, true meaning from the
1712*890232f2SAndroid Build Coastguard Worker   // underlying type to the interface type.
GenUnderlyingCast(const FieldDef & field,bool from,const std::string & val)1713*890232f2SAndroid Build Coastguard Worker   std::string GenUnderlyingCast(const FieldDef &field, bool from,
1714*890232f2SAndroid Build Coastguard Worker                                 const std::string &val) {
1715*890232f2SAndroid Build Coastguard Worker     if (from && field.value.type.base_type == BASE_TYPE_BOOL) {
1716*890232f2SAndroid Build Coastguard Worker       return val + " != 0";
1717*890232f2SAndroid Build Coastguard Worker     } else if ((field.value.type.enum_def &&
1718*890232f2SAndroid Build Coastguard Worker                 IsScalar(field.value.type.base_type)) ||
1719*890232f2SAndroid Build Coastguard Worker                field.value.type.base_type == BASE_TYPE_BOOL) {
1720*890232f2SAndroid Build Coastguard Worker       return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" +
1721*890232f2SAndroid Build Coastguard Worker              val + ")";
1722*890232f2SAndroid Build Coastguard Worker     } else {
1723*890232f2SAndroid Build Coastguard Worker       return val;
1724*890232f2SAndroid Build Coastguard Worker     }
1725*890232f2SAndroid Build Coastguard Worker   }
1726*890232f2SAndroid Build Coastguard Worker 
GenFieldOffsetName(const FieldDef & field)1727*890232f2SAndroid Build Coastguard Worker   std::string GenFieldOffsetName(const FieldDef &field) {
1728*890232f2SAndroid Build Coastguard Worker     std::string uname = Name(field);
1729*890232f2SAndroid Build Coastguard Worker     std::transform(uname.begin(), uname.end(), uname.begin(), CharToUpper);
1730*890232f2SAndroid Build Coastguard Worker     return "VT_" + uname;
1731*890232f2SAndroid Build Coastguard Worker   }
1732*890232f2SAndroid Build Coastguard Worker 
GenFullyQualifiedNameGetter(const StructDef & struct_def,const std::string & name)1733*890232f2SAndroid Build Coastguard Worker   void GenFullyQualifiedNameGetter(const StructDef &struct_def,
1734*890232f2SAndroid Build Coastguard Worker                                    const std::string &name) {
1735*890232f2SAndroid Build Coastguard Worker     if (!opts_.generate_name_strings) { return; }
1736*890232f2SAndroid Build Coastguard Worker     auto fullname = struct_def.defined_namespace->GetFullyQualifiedName(name);
1737*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NAME", fullname);
1738*890232f2SAndroid Build Coastguard Worker     code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR_CPP11");
1739*890232f2SAndroid Build Coastguard Worker     code_ += "  static {{CONSTEXPR}} const char *GetFullyQualifiedName() {";
1740*890232f2SAndroid Build Coastguard Worker     code_ += "    return \"{{NAME}}\";";
1741*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
1742*890232f2SAndroid Build Coastguard Worker   }
1743*890232f2SAndroid Build Coastguard Worker 
GenDefaultConstant(const FieldDef & field)1744*890232f2SAndroid Build Coastguard Worker   std::string GenDefaultConstant(const FieldDef &field) {
1745*890232f2SAndroid Build Coastguard Worker     if (IsFloat(field.value.type.base_type))
1746*890232f2SAndroid Build Coastguard Worker       return float_const_gen_.GenFloatConstant(field);
1747*890232f2SAndroid Build Coastguard Worker     else
1748*890232f2SAndroid Build Coastguard Worker       return NumToStringCpp(field.value.constant, field.value.type.base_type);
1749*890232f2SAndroid Build Coastguard Worker   }
1750*890232f2SAndroid Build Coastguard Worker 
GetDefaultScalarValue(const FieldDef & field,bool is_ctor)1751*890232f2SAndroid Build Coastguard Worker   std::string GetDefaultScalarValue(const FieldDef &field, bool is_ctor) {
1752*890232f2SAndroid Build Coastguard Worker     const auto &type = field.value.type;
1753*890232f2SAndroid Build Coastguard Worker     if (field.IsScalarOptional()) {
1754*890232f2SAndroid Build Coastguard Worker       return GenOptionalNull();
1755*890232f2SAndroid Build Coastguard Worker     } else if (type.enum_def && IsScalar(type.base_type)) {
1756*890232f2SAndroid Build Coastguard Worker       auto ev = type.enum_def->FindByValue(field.value.constant);
1757*890232f2SAndroid Build Coastguard Worker       if (ev) {
1758*890232f2SAndroid Build Coastguard Worker         return WrapInNameSpace(type.enum_def->defined_namespace,
1759*890232f2SAndroid Build Coastguard Worker                                GetEnumValUse(*type.enum_def, *ev));
1760*890232f2SAndroid Build Coastguard Worker       } else {
1761*890232f2SAndroid Build Coastguard Worker         return GenUnderlyingCast(
1762*890232f2SAndroid Build Coastguard Worker             field, true, NumToStringCpp(field.value.constant, type.base_type));
1763*890232f2SAndroid Build Coastguard Worker       }
1764*890232f2SAndroid Build Coastguard Worker     } else if (type.base_type == BASE_TYPE_BOOL) {
1765*890232f2SAndroid Build Coastguard Worker       return field.value.constant == "0" ? "false" : "true";
1766*890232f2SAndroid Build Coastguard Worker     } else if (field.attributes.Lookup("cpp_type")) {
1767*890232f2SAndroid Build Coastguard Worker       if (is_ctor) {
1768*890232f2SAndroid Build Coastguard Worker         if (PtrType(&field) == "naked") {
1769*890232f2SAndroid Build Coastguard Worker           return "nullptr";
1770*890232f2SAndroid Build Coastguard Worker         } else {
1771*890232f2SAndroid Build Coastguard Worker           return "";
1772*890232f2SAndroid Build Coastguard Worker         }
1773*890232f2SAndroid Build Coastguard Worker       } else {
1774*890232f2SAndroid Build Coastguard Worker         return "0";
1775*890232f2SAndroid Build Coastguard Worker       }
1776*890232f2SAndroid Build Coastguard Worker     } else if (IsStruct(type) && (field.value.constant == "0")) {
1777*890232f2SAndroid Build Coastguard Worker       return "nullptr";
1778*890232f2SAndroid Build Coastguard Worker     } else {
1779*890232f2SAndroid Build Coastguard Worker       return GenDefaultConstant(field);
1780*890232f2SAndroid Build Coastguard Worker     }
1781*890232f2SAndroid Build Coastguard Worker   }
1782*890232f2SAndroid Build Coastguard Worker 
GenParam(const FieldDef & field,bool direct,const char * prefix)1783*890232f2SAndroid Build Coastguard Worker   void GenParam(const FieldDef &field, bool direct, const char *prefix) {
1784*890232f2SAndroid Build Coastguard Worker     code_.SetValue("PRE", prefix);
1785*890232f2SAndroid Build Coastguard Worker     code_.SetValue("PARAM_NAME", Name(field));
1786*890232f2SAndroid Build Coastguard Worker     if (direct && IsString(field.value.type)) {
1787*890232f2SAndroid Build Coastguard Worker       code_.SetValue("PARAM_TYPE", "const char *");
1788*890232f2SAndroid Build Coastguard Worker       code_.SetValue("PARAM_VALUE", "nullptr");
1789*890232f2SAndroid Build Coastguard Worker     } else if (direct && IsVector(field.value.type)) {
1790*890232f2SAndroid Build Coastguard Worker       const auto vtype = field.value.type.VectorType();
1791*890232f2SAndroid Build Coastguard Worker       std::string type;
1792*890232f2SAndroid Build Coastguard Worker       if (IsStruct(vtype)) {
1793*890232f2SAndroid Build Coastguard Worker         type = WrapInNameSpace(*vtype.struct_def);
1794*890232f2SAndroid Build Coastguard Worker       } else {
1795*890232f2SAndroid Build Coastguard Worker         type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
1796*890232f2SAndroid Build Coastguard Worker       }
1797*890232f2SAndroid Build Coastguard Worker       if (TypeHasKey(vtype)) {
1798*890232f2SAndroid Build Coastguard Worker         code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *");
1799*890232f2SAndroid Build Coastguard Worker       } else {
1800*890232f2SAndroid Build Coastguard Worker         code_.SetValue("PARAM_TYPE", "const std::vector<" + type + "> *");
1801*890232f2SAndroid Build Coastguard Worker       }
1802*890232f2SAndroid Build Coastguard Worker       code_.SetValue("PARAM_VALUE", "nullptr");
1803*890232f2SAndroid Build Coastguard Worker     } else {
1804*890232f2SAndroid Build Coastguard Worker       const auto &type = field.value.type;
1805*890232f2SAndroid Build Coastguard Worker       code_.SetValue("PARAM_VALUE", GetDefaultScalarValue(field, false));
1806*890232f2SAndroid Build Coastguard Worker       if (field.IsScalarOptional())
1807*890232f2SAndroid Build Coastguard Worker         code_.SetValue("PARAM_TYPE", GenOptionalDecl(type) + " ");
1808*890232f2SAndroid Build Coastguard Worker       else
1809*890232f2SAndroid Build Coastguard Worker         code_.SetValue("PARAM_TYPE", GenTypeWire(type, " ", true));
1810*890232f2SAndroid Build Coastguard Worker     }
1811*890232f2SAndroid Build Coastguard Worker     code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\";
1812*890232f2SAndroid Build Coastguard Worker   }
1813*890232f2SAndroid Build Coastguard Worker 
1814*890232f2SAndroid Build Coastguard Worker   // Generate a member, including a default value for scalars and raw pointers.
GenMember(const FieldDef & field)1815*890232f2SAndroid Build Coastguard Worker   void GenMember(const FieldDef &field) {
1816*890232f2SAndroid Build Coastguard Worker     if (!field.deprecated &&  // Deprecated fields won't be accessible.
1817*890232f2SAndroid Build Coastguard Worker         field.value.type.base_type != BASE_TYPE_UTYPE &&
1818*890232f2SAndroid Build Coastguard Worker         (field.value.type.base_type != BASE_TYPE_VECTOR ||
1819*890232f2SAndroid Build Coastguard Worker          field.value.type.element != BASE_TYPE_UTYPE)) {
1820*890232f2SAndroid Build Coastguard Worker       auto type = GenTypeNative(field.value.type, false, field);
1821*890232f2SAndroid Build Coastguard Worker       auto cpp_type = field.attributes.Lookup("cpp_type");
1822*890232f2SAndroid Build Coastguard Worker       auto full_type =
1823*890232f2SAndroid Build Coastguard Worker           (cpp_type
1824*890232f2SAndroid Build Coastguard Worker                ? (IsVector(field.value.type)
1825*890232f2SAndroid Build Coastguard Worker                       ? "std::vector<" +
1826*890232f2SAndroid Build Coastguard Worker                             GenTypeNativePtr(cpp_type->constant, &field,
1827*890232f2SAndroid Build Coastguard Worker                                              false) +
1828*890232f2SAndroid Build Coastguard Worker                             "> "
1829*890232f2SAndroid Build Coastguard Worker                       : GenTypeNativePtr(cpp_type->constant, &field, false))
1830*890232f2SAndroid Build Coastguard Worker                : type + " ");
1831*890232f2SAndroid Build Coastguard Worker       // Generate default member initializers for >= C++11.
1832*890232f2SAndroid Build Coastguard Worker       std::string field_di = "";
1833*890232f2SAndroid Build Coastguard Worker       if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
1834*890232f2SAndroid Build Coastguard Worker         field_di = "{}";
1835*890232f2SAndroid Build Coastguard Worker         auto native_default = field.attributes.Lookup("native_default");
1836*890232f2SAndroid Build Coastguard Worker         // Scalar types get parsed defaults, raw pointers get nullptrs.
1837*890232f2SAndroid Build Coastguard Worker         if (IsScalar(field.value.type.base_type)) {
1838*890232f2SAndroid Build Coastguard Worker           field_di =
1839*890232f2SAndroid Build Coastguard Worker               " = " + (native_default ? std::string(native_default->constant)
1840*890232f2SAndroid Build Coastguard Worker                                       : GetDefaultScalarValue(field, true));
1841*890232f2SAndroid Build Coastguard Worker         } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1842*890232f2SAndroid Build Coastguard Worker           if (IsStruct(field.value.type) && native_default) {
1843*890232f2SAndroid Build Coastguard Worker             field_di = " = " + native_default->constant;
1844*890232f2SAndroid Build Coastguard Worker           }
1845*890232f2SAndroid Build Coastguard Worker         }
1846*890232f2SAndroid Build Coastguard Worker       }
1847*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", full_type);
1848*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
1849*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_DI", field_di);
1850*890232f2SAndroid Build Coastguard Worker       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}{{FIELD_DI}};";
1851*890232f2SAndroid Build Coastguard Worker     }
1852*890232f2SAndroid Build Coastguard Worker   }
1853*890232f2SAndroid Build Coastguard Worker 
1854*890232f2SAndroid Build Coastguard Worker   // Returns true if `struct_def` needs a copy constructor and assignment
1855*890232f2SAndroid Build Coastguard Worker   // operator because it has one or more table members, struct members with a
1856*890232f2SAndroid Build Coastguard Worker   // custom cpp_type and non-naked pointer type, or vector members of those.
NeedsCopyCtorAssignOp(const StructDef & struct_def)1857*890232f2SAndroid Build Coastguard Worker   bool NeedsCopyCtorAssignOp(const StructDef &struct_def) {
1858*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
1859*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
1860*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
1861*890232f2SAndroid Build Coastguard Worker       const auto &type = field.value.type;
1862*890232f2SAndroid Build Coastguard Worker       if (field.deprecated) continue;
1863*890232f2SAndroid Build Coastguard Worker       if (type.base_type == BASE_TYPE_STRUCT) {
1864*890232f2SAndroid Build Coastguard Worker         const auto cpp_type = field.attributes.Lookup("cpp_type");
1865*890232f2SAndroid Build Coastguard Worker         const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
1866*890232f2SAndroid Build Coastguard Worker         const bool is_ptr = !(IsStruct(type) && field.native_inline) ||
1867*890232f2SAndroid Build Coastguard Worker                             (cpp_type && cpp_ptr_type->constant != "naked");
1868*890232f2SAndroid Build Coastguard Worker         if (is_ptr) { return true; }
1869*890232f2SAndroid Build Coastguard Worker       } else if (IsVector(type)) {
1870*890232f2SAndroid Build Coastguard Worker         const auto vec_type = type.VectorType();
1871*890232f2SAndroid Build Coastguard Worker         if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
1872*890232f2SAndroid Build Coastguard Worker         const auto cpp_type = field.attributes.Lookup("cpp_type");
1873*890232f2SAndroid Build Coastguard Worker         const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
1874*890232f2SAndroid Build Coastguard Worker         const bool is_ptr =
1875*890232f2SAndroid Build Coastguard Worker             (vec_type.base_type == BASE_TYPE_STRUCT && !IsStruct(vec_type)) ||
1876*890232f2SAndroid Build Coastguard Worker             (cpp_type && cpp_ptr_type->constant != "naked");
1877*890232f2SAndroid Build Coastguard Worker         if (is_ptr) { return true; }
1878*890232f2SAndroid Build Coastguard Worker       }
1879*890232f2SAndroid Build Coastguard Worker     }
1880*890232f2SAndroid Build Coastguard Worker     return false;
1881*890232f2SAndroid Build Coastguard Worker   }
1882*890232f2SAndroid Build Coastguard Worker 
1883*890232f2SAndroid Build Coastguard Worker   // Generate the default constructor for this struct. Properly initialize all
1884*890232f2SAndroid Build Coastguard Worker   // scalar members with default values.
GenDefaultConstructor(const StructDef & struct_def)1885*890232f2SAndroid Build Coastguard Worker   void GenDefaultConstructor(const StructDef &struct_def) {
1886*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NATIVE_NAME",
1887*890232f2SAndroid Build Coastguard Worker                    NativeName(Name(struct_def), &struct_def, opts_));
1888*890232f2SAndroid Build Coastguard Worker     // In >= C++11, default member initializers are generated. To allow for
1889*890232f2SAndroid Build Coastguard Worker     // aggregate initialization, do not emit a default constructor at all, with
1890*890232f2SAndroid Build Coastguard Worker     // the exception of types that need a copy/move ctors and assignment
1891*890232f2SAndroid Build Coastguard Worker     // operators.
1892*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
1893*890232f2SAndroid Build Coastguard Worker       if (NeedsCopyCtorAssignOp(struct_def)) {
1894*890232f2SAndroid Build Coastguard Worker         code_ += "  {{NATIVE_NAME}}() = default;";
1895*890232f2SAndroid Build Coastguard Worker       }
1896*890232f2SAndroid Build Coastguard Worker       return;
1897*890232f2SAndroid Build Coastguard Worker     }
1898*890232f2SAndroid Build Coastguard Worker     std::string initializer_list;
1899*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
1900*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
1901*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
1902*890232f2SAndroid Build Coastguard Worker       if (!field.deprecated &&  // Deprecated fields won't be accessible.
1903*890232f2SAndroid Build Coastguard Worker           field.value.type.base_type != BASE_TYPE_UTYPE) {
1904*890232f2SAndroid Build Coastguard Worker         auto cpp_type = field.attributes.Lookup("cpp_type");
1905*890232f2SAndroid Build Coastguard Worker         auto native_default = field.attributes.Lookup("native_default");
1906*890232f2SAndroid Build Coastguard Worker         // Scalar types get parsed defaults, raw pointers get nullptrs.
1907*890232f2SAndroid Build Coastguard Worker         if (IsScalar(field.value.type.base_type)) {
1908*890232f2SAndroid Build Coastguard Worker           if (!initializer_list.empty()) { initializer_list += ",\n        "; }
1909*890232f2SAndroid Build Coastguard Worker           initializer_list += Name(field);
1910*890232f2SAndroid Build Coastguard Worker           initializer_list +=
1911*890232f2SAndroid Build Coastguard Worker               "(" +
1912*890232f2SAndroid Build Coastguard Worker               (native_default ? std::string(native_default->constant)
1913*890232f2SAndroid Build Coastguard Worker                               : GetDefaultScalarValue(field, true)) +
1914*890232f2SAndroid Build Coastguard Worker               ")";
1915*890232f2SAndroid Build Coastguard Worker         } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1916*890232f2SAndroid Build Coastguard Worker           if (IsStruct(field.value.type)) {
1917*890232f2SAndroid Build Coastguard Worker             if (native_default) {
1918*890232f2SAndroid Build Coastguard Worker               if (!initializer_list.empty()) {
1919*890232f2SAndroid Build Coastguard Worker                 initializer_list += ",\n        ";
1920*890232f2SAndroid Build Coastguard Worker               }
1921*890232f2SAndroid Build Coastguard Worker               initializer_list +=
1922*890232f2SAndroid Build Coastguard Worker                   Name(field) + "(" + native_default->constant + ")";
1923*890232f2SAndroid Build Coastguard Worker             }
1924*890232f2SAndroid Build Coastguard Worker           }
1925*890232f2SAndroid Build Coastguard Worker         } else if (cpp_type && field.value.type.base_type != BASE_TYPE_VECTOR) {
1926*890232f2SAndroid Build Coastguard Worker           if (!initializer_list.empty()) { initializer_list += ",\n        "; }
1927*890232f2SAndroid Build Coastguard Worker           initializer_list += Name(field) + "(0)";
1928*890232f2SAndroid Build Coastguard Worker         }
1929*890232f2SAndroid Build Coastguard Worker       }
1930*890232f2SAndroid Build Coastguard Worker     }
1931*890232f2SAndroid Build Coastguard Worker     if (!initializer_list.empty()) {
1932*890232f2SAndroid Build Coastguard Worker       initializer_list = "\n      : " + initializer_list;
1933*890232f2SAndroid Build Coastguard Worker     }
1934*890232f2SAndroid Build Coastguard Worker 
1935*890232f2SAndroid Build Coastguard Worker     code_.SetValue("INIT_LIST", initializer_list);
1936*890232f2SAndroid Build Coastguard Worker 
1937*890232f2SAndroid Build Coastguard Worker     code_ += "  {{NATIVE_NAME}}(){{INIT_LIST}} {";
1938*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
1939*890232f2SAndroid Build Coastguard Worker   }
1940*890232f2SAndroid Build Coastguard Worker 
1941*890232f2SAndroid Build Coastguard Worker   // Generate the >= C++11 copy/move constructor and assignment operator
1942*890232f2SAndroid Build Coastguard Worker   // declarations if required. Tables that are default-copyable do not get
1943*890232f2SAndroid Build Coastguard Worker   // user-provided copy/move constructors and assignment operators so they
1944*890232f2SAndroid Build Coastguard Worker   // remain aggregates.
GenCopyMoveCtorAndAssigOpDecls(const StructDef & struct_def)1945*890232f2SAndroid Build Coastguard Worker   void GenCopyMoveCtorAndAssigOpDecls(const StructDef &struct_def) {
1946*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std < cpp::CPP_STD_11) return;
1947*890232f2SAndroid Build Coastguard Worker     if (!NeedsCopyCtorAssignOp(struct_def)) return;
1948*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NATIVE_NAME",
1949*890232f2SAndroid Build Coastguard Worker                    NativeName(Name(struct_def), &struct_def, opts_));
1950*890232f2SAndroid Build Coastguard Worker     code_ += "  {{NATIVE_NAME}}(const {{NATIVE_NAME}} &o);";
1951*890232f2SAndroid Build Coastguard Worker     code_ +=
1952*890232f2SAndroid Build Coastguard Worker         "  {{NATIVE_NAME}}({{NATIVE_NAME}}&&) FLATBUFFERS_NOEXCEPT = "
1953*890232f2SAndroid Build Coastguard Worker         "default;";
1954*890232f2SAndroid Build Coastguard Worker     code_ +=
1955*890232f2SAndroid Build Coastguard Worker         "  {{NATIVE_NAME}} &operator=({{NATIVE_NAME}} o) FLATBUFFERS_NOEXCEPT;";
1956*890232f2SAndroid Build Coastguard Worker   }
1957*890232f2SAndroid Build Coastguard Worker 
1958*890232f2SAndroid Build Coastguard Worker   // Generate the >= C++11 copy constructor and assignment operator definitions.
GenCopyCtorAssignOpDefs(const StructDef & struct_def)1959*890232f2SAndroid Build Coastguard Worker   void GenCopyCtorAssignOpDefs(const StructDef &struct_def) {
1960*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std < cpp::CPP_STD_11) return;
1961*890232f2SAndroid Build Coastguard Worker     if (!NeedsCopyCtorAssignOp(struct_def)) return;
1962*890232f2SAndroid Build Coastguard Worker     std::string initializer_list;
1963*890232f2SAndroid Build Coastguard Worker     std::string vector_copies;
1964*890232f2SAndroid Build Coastguard Worker     std::string swaps;
1965*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
1966*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
1967*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
1968*890232f2SAndroid Build Coastguard Worker       const auto &type = field.value.type;
1969*890232f2SAndroid Build Coastguard Worker       if (field.deprecated || type.base_type == BASE_TYPE_UTYPE) continue;
1970*890232f2SAndroid Build Coastguard Worker       if (type.base_type == BASE_TYPE_STRUCT) {
1971*890232f2SAndroid Build Coastguard Worker         if (!initializer_list.empty()) { initializer_list += ",\n        "; }
1972*890232f2SAndroid Build Coastguard Worker         const auto cpp_type = field.attributes.Lookup("cpp_type");
1973*890232f2SAndroid Build Coastguard Worker         const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
1974*890232f2SAndroid Build Coastguard Worker         auto type_name = (cpp_type) ? cpp_type->constant
1975*890232f2SAndroid Build Coastguard Worker                                     : GenTypeNative(type, /*invector*/ false,
1976*890232f2SAndroid Build Coastguard Worker                                                     field, /*forcopy*/ true);
1977*890232f2SAndroid Build Coastguard Worker         const bool is_ptr = !(IsStruct(type) && field.native_inline) ||
1978*890232f2SAndroid Build Coastguard Worker                             (cpp_type && cpp_ptr_type->constant != "naked");
1979*890232f2SAndroid Build Coastguard Worker         CodeWriter cw;
1980*890232f2SAndroid Build Coastguard Worker         cw.SetValue("FIELD", Name(field));
1981*890232f2SAndroid Build Coastguard Worker         cw.SetValue("TYPE", type_name);
1982*890232f2SAndroid Build Coastguard Worker         if (is_ptr) {
1983*890232f2SAndroid Build Coastguard Worker           cw +=
1984*890232f2SAndroid Build Coastguard Worker               "{{FIELD}}((o.{{FIELD}}) ? new {{TYPE}}(*o.{{FIELD}}) : "
1985*890232f2SAndroid Build Coastguard Worker               "nullptr)\\";
1986*890232f2SAndroid Build Coastguard Worker           initializer_list += cw.ToString();
1987*890232f2SAndroid Build Coastguard Worker         } else {
1988*890232f2SAndroid Build Coastguard Worker           cw += "{{FIELD}}(o.{{FIELD}})\\";
1989*890232f2SAndroid Build Coastguard Worker           initializer_list += cw.ToString();
1990*890232f2SAndroid Build Coastguard Worker         }
1991*890232f2SAndroid Build Coastguard Worker       } else if (IsVector(type)) {
1992*890232f2SAndroid Build Coastguard Worker         const auto vec_type = type.VectorType();
1993*890232f2SAndroid Build Coastguard Worker         if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
1994*890232f2SAndroid Build Coastguard Worker         const auto cpp_type = field.attributes.Lookup("cpp_type");
1995*890232f2SAndroid Build Coastguard Worker         const auto cpp_ptr_type = field.attributes.Lookup("cpp_ptr_type");
1996*890232f2SAndroid Build Coastguard Worker         const auto type_name = (cpp_type)
1997*890232f2SAndroid Build Coastguard Worker                                    ? cpp_type->constant
1998*890232f2SAndroid Build Coastguard Worker                                    : GenTypeNative(vec_type, /*invector*/ true,
1999*890232f2SAndroid Build Coastguard Worker                                                    field, /*forcopy*/ true);
2000*890232f2SAndroid Build Coastguard Worker         const bool is_ptr =
2001*890232f2SAndroid Build Coastguard Worker             (vec_type.base_type == BASE_TYPE_STRUCT && !IsStruct(vec_type)) ||
2002*890232f2SAndroid Build Coastguard Worker             (cpp_type && cpp_ptr_type->constant != "naked");
2003*890232f2SAndroid Build Coastguard Worker         CodeWriter cw("  ");
2004*890232f2SAndroid Build Coastguard Worker         cw.SetValue("FIELD", Name(field));
2005*890232f2SAndroid Build Coastguard Worker         cw.SetValue("TYPE", type_name);
2006*890232f2SAndroid Build Coastguard Worker         if (is_ptr) {
2007*890232f2SAndroid Build Coastguard Worker           // Use emplace_back to construct the potentially-smart pointer element
2008*890232f2SAndroid Build Coastguard Worker           // from a raw pointer to a new-allocated copy.
2009*890232f2SAndroid Build Coastguard Worker           cw.IncrementIdentLevel();
2010*890232f2SAndroid Build Coastguard Worker           cw += "{{FIELD}}.reserve(o.{{FIELD}}.size());";
2011*890232f2SAndroid Build Coastguard Worker           cw +=
2012*890232f2SAndroid Build Coastguard Worker               "for (const auto &{{FIELD}}_ : o.{{FIELD}}) { "
2013*890232f2SAndroid Build Coastguard Worker               "{{FIELD}}.emplace_back(({{FIELD}}_) ? new {{TYPE}}(*{{FIELD}}_) "
2014*890232f2SAndroid Build Coastguard Worker               ": nullptr); }";
2015*890232f2SAndroid Build Coastguard Worker           vector_copies += cw.ToString();
2016*890232f2SAndroid Build Coastguard Worker         } else {
2017*890232f2SAndroid Build Coastguard Worker           // For non-pointer elements, use std::vector's copy constructor in the
2018*890232f2SAndroid Build Coastguard Worker           // initializer list. This will yield better performance than an insert
2019*890232f2SAndroid Build Coastguard Worker           // range loop for trivially-copyable element types.
2020*890232f2SAndroid Build Coastguard Worker           if (!initializer_list.empty()) { initializer_list += ",\n        "; }
2021*890232f2SAndroid Build Coastguard Worker           cw += "{{FIELD}}(o.{{FIELD}})\\";
2022*890232f2SAndroid Build Coastguard Worker           initializer_list += cw.ToString();
2023*890232f2SAndroid Build Coastguard Worker         }
2024*890232f2SAndroid Build Coastguard Worker       } else {
2025*890232f2SAndroid Build Coastguard Worker         if (!initializer_list.empty()) { initializer_list += ",\n        "; }
2026*890232f2SAndroid Build Coastguard Worker         CodeWriter cw;
2027*890232f2SAndroid Build Coastguard Worker         cw.SetValue("FIELD", Name(field));
2028*890232f2SAndroid Build Coastguard Worker         cw += "{{FIELD}}(o.{{FIELD}})\\";
2029*890232f2SAndroid Build Coastguard Worker         initializer_list += cw.ToString();
2030*890232f2SAndroid Build Coastguard Worker       }
2031*890232f2SAndroid Build Coastguard Worker       {
2032*890232f2SAndroid Build Coastguard Worker         if (!swaps.empty()) { swaps += "\n  "; }
2033*890232f2SAndroid Build Coastguard Worker         CodeWriter cw;
2034*890232f2SAndroid Build Coastguard Worker         cw.SetValue("FIELD", Name(field));
2035*890232f2SAndroid Build Coastguard Worker         cw += "std::swap({{FIELD}}, o.{{FIELD}});\\";
2036*890232f2SAndroid Build Coastguard Worker         swaps += cw.ToString();
2037*890232f2SAndroid Build Coastguard Worker       }
2038*890232f2SAndroid Build Coastguard Worker     }
2039*890232f2SAndroid Build Coastguard Worker     if (!initializer_list.empty()) {
2040*890232f2SAndroid Build Coastguard Worker       initializer_list = "\n      : " + initializer_list;
2041*890232f2SAndroid Build Coastguard Worker     }
2042*890232f2SAndroid Build Coastguard Worker     if (!swaps.empty()) { swaps = "  " + swaps; }
2043*890232f2SAndroid Build Coastguard Worker 
2044*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NATIVE_NAME",
2045*890232f2SAndroid Build Coastguard Worker                    NativeName(Name(struct_def), &struct_def, opts_));
2046*890232f2SAndroid Build Coastguard Worker     code_.SetValue("INIT_LIST", initializer_list);
2047*890232f2SAndroid Build Coastguard Worker     code_.SetValue("VEC_COPY", vector_copies);
2048*890232f2SAndroid Build Coastguard Worker     code_.SetValue("SWAPS", swaps);
2049*890232f2SAndroid Build Coastguard Worker 
2050*890232f2SAndroid Build Coastguard Worker     code_ +=
2051*890232f2SAndroid Build Coastguard Worker         "inline {{NATIVE_NAME}}::{{NATIVE_NAME}}(const {{NATIVE_NAME}} &o)"
2052*890232f2SAndroid Build Coastguard Worker         "{{INIT_LIST}} {";
2053*890232f2SAndroid Build Coastguard Worker     code_ += "{{VEC_COPY}}}\n";
2054*890232f2SAndroid Build Coastguard Worker     code_ +=
2055*890232f2SAndroid Build Coastguard Worker         "inline {{NATIVE_NAME}} &{{NATIVE_NAME}}::operator="
2056*890232f2SAndroid Build Coastguard Worker         "({{NATIVE_NAME}} o) FLATBUFFERS_NOEXCEPT {";
2057*890232f2SAndroid Build Coastguard Worker     code_ += "{{SWAPS}}";
2058*890232f2SAndroid Build Coastguard Worker     code_ += "  return *this;\n}\n";
2059*890232f2SAndroid Build Coastguard Worker   }
2060*890232f2SAndroid Build Coastguard Worker 
GenCompareOperator(const StructDef & struct_def,std::string accessSuffix="")2061*890232f2SAndroid Build Coastguard Worker   void GenCompareOperator(const StructDef &struct_def,
2062*890232f2SAndroid Build Coastguard Worker                           std::string accessSuffix = "") {
2063*890232f2SAndroid Build Coastguard Worker     std::string compare_op;
2064*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2065*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2066*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2067*890232f2SAndroid Build Coastguard Worker       const auto accessor = Name(field) + accessSuffix;
2068*890232f2SAndroid Build Coastguard Worker       const auto lhs_accessor = "lhs." + accessor;
2069*890232f2SAndroid Build Coastguard Worker       const auto rhs_accessor = "rhs." + accessor;
2070*890232f2SAndroid Build Coastguard Worker 
2071*890232f2SAndroid Build Coastguard Worker       if (!field.deprecated &&  // Deprecated fields won't be accessible.
2072*890232f2SAndroid Build Coastguard Worker           field.value.type.base_type != BASE_TYPE_UTYPE &&
2073*890232f2SAndroid Build Coastguard Worker           (field.value.type.base_type != BASE_TYPE_VECTOR ||
2074*890232f2SAndroid Build Coastguard Worker            field.value.type.element != BASE_TYPE_UTYPE)) {
2075*890232f2SAndroid Build Coastguard Worker         if (!compare_op.empty()) { compare_op += " &&\n      "; }
2076*890232f2SAndroid Build Coastguard Worker         if (struct_def.fixed || field.native_inline ||
2077*890232f2SAndroid Build Coastguard Worker             field.value.type.base_type != BASE_TYPE_STRUCT) {
2078*890232f2SAndroid Build Coastguard Worker           // If the field is a vector of tables, the table need to be compared
2079*890232f2SAndroid Build Coastguard Worker           // by value, instead of by the default unique_ptr == operator which
2080*890232f2SAndroid Build Coastguard Worker           // compares by address.
2081*890232f2SAndroid Build Coastguard Worker           if (field.value.type.base_type == BASE_TYPE_VECTOR &&
2082*890232f2SAndroid Build Coastguard Worker               field.value.type.element == BASE_TYPE_STRUCT &&
2083*890232f2SAndroid Build Coastguard Worker               !field.value.type.struct_def->fixed) {
2084*890232f2SAndroid Build Coastguard Worker             const auto type =
2085*890232f2SAndroid Build Coastguard Worker                 GenTypeNative(field.value.type.VectorType(), true, field);
2086*890232f2SAndroid Build Coastguard Worker             const auto equal_length =
2087*890232f2SAndroid Build Coastguard Worker                 lhs_accessor + ".size() == " + rhs_accessor + ".size()";
2088*890232f2SAndroid Build Coastguard Worker             const auto elements_equal =
2089*890232f2SAndroid Build Coastguard Worker                 "std::equal(" + lhs_accessor + ".cbegin(), " + lhs_accessor +
2090*890232f2SAndroid Build Coastguard Worker                 ".cend(), " + rhs_accessor + ".cbegin(), [](" + type +
2091*890232f2SAndroid Build Coastguard Worker                 " const &a, " + type +
2092*890232f2SAndroid Build Coastguard Worker                 " const &b) { return (a == b) || (a && b && *a == *b); })";
2093*890232f2SAndroid Build Coastguard Worker 
2094*890232f2SAndroid Build Coastguard Worker             compare_op += "(" + equal_length + " && " + elements_equal + ")";
2095*890232f2SAndroid Build Coastguard Worker           } else {
2096*890232f2SAndroid Build Coastguard Worker             compare_op += "(" + lhs_accessor + " == " + rhs_accessor + ")";
2097*890232f2SAndroid Build Coastguard Worker           }
2098*890232f2SAndroid Build Coastguard Worker         } else {
2099*890232f2SAndroid Build Coastguard Worker           // Deep compare of std::unique_ptr. Null is not equal to empty.
2100*890232f2SAndroid Build Coastguard Worker           std::string both_null =
2101*890232f2SAndroid Build Coastguard Worker               "(" + lhs_accessor + " == " + rhs_accessor + ")";
2102*890232f2SAndroid Build Coastguard Worker           std::string not_null_and_equal = "(lhs." + accessor + " && rhs." +
2103*890232f2SAndroid Build Coastguard Worker                                            accessor + " && *lhs." + accessor +
2104*890232f2SAndroid Build Coastguard Worker                                            " == *rhs." + accessor + ")";
2105*890232f2SAndroid Build Coastguard Worker           compare_op += "(" + both_null + " || " + not_null_and_equal + ")";
2106*890232f2SAndroid Build Coastguard Worker         }
2107*890232f2SAndroid Build Coastguard Worker       }
2108*890232f2SAndroid Build Coastguard Worker     }
2109*890232f2SAndroid Build Coastguard Worker 
2110*890232f2SAndroid Build Coastguard Worker     std::string cmp_lhs;
2111*890232f2SAndroid Build Coastguard Worker     std::string cmp_rhs;
2112*890232f2SAndroid Build Coastguard Worker     if (compare_op.empty()) {
2113*890232f2SAndroid Build Coastguard Worker       cmp_lhs = "";
2114*890232f2SAndroid Build Coastguard Worker       cmp_rhs = "";
2115*890232f2SAndroid Build Coastguard Worker       compare_op = "  return true;";
2116*890232f2SAndroid Build Coastguard Worker     } else {
2117*890232f2SAndroid Build Coastguard Worker       cmp_lhs = "lhs";
2118*890232f2SAndroid Build Coastguard Worker       cmp_rhs = "rhs";
2119*890232f2SAndroid Build Coastguard Worker       compare_op = "  return\n      " + compare_op + ";";
2120*890232f2SAndroid Build Coastguard Worker     }
2121*890232f2SAndroid Build Coastguard Worker 
2122*890232f2SAndroid Build Coastguard Worker     code_.SetValue("CMP_OP", compare_op);
2123*890232f2SAndroid Build Coastguard Worker     code_.SetValue("CMP_LHS", cmp_lhs);
2124*890232f2SAndroid Build Coastguard Worker     code_.SetValue("CMP_RHS", cmp_rhs);
2125*890232f2SAndroid Build Coastguard Worker     code_ += "";
2126*890232f2SAndroid Build Coastguard Worker     code_ +=
2127*890232f2SAndroid Build Coastguard Worker         "inline bool operator==(const {{NATIVE_NAME}} &{{CMP_LHS}}, const "
2128*890232f2SAndroid Build Coastguard Worker         "{{NATIVE_NAME}} &{{CMP_RHS}}) {";
2129*890232f2SAndroid Build Coastguard Worker     code_ += "{{CMP_OP}}";
2130*890232f2SAndroid Build Coastguard Worker     code_ += "}";
2131*890232f2SAndroid Build Coastguard Worker 
2132*890232f2SAndroid Build Coastguard Worker     code_ += "";
2133*890232f2SAndroid Build Coastguard Worker     code_ +=
2134*890232f2SAndroid Build Coastguard Worker         "inline bool operator!=(const {{NATIVE_NAME}} &lhs, const "
2135*890232f2SAndroid Build Coastguard Worker         "{{NATIVE_NAME}} &rhs) {";
2136*890232f2SAndroid Build Coastguard Worker     code_ += "    return !(lhs == rhs);";
2137*890232f2SAndroid Build Coastguard Worker     code_ += "}";
2138*890232f2SAndroid Build Coastguard Worker     code_ += "";
2139*890232f2SAndroid Build Coastguard Worker   }
2140*890232f2SAndroid Build Coastguard Worker 
GenOperatorNewDelete(const StructDef & struct_def)2141*890232f2SAndroid Build Coastguard Worker   void GenOperatorNewDelete(const StructDef &struct_def) {
2142*890232f2SAndroid Build Coastguard Worker     if (auto native_custom_alloc =
2143*890232f2SAndroid Build Coastguard Worker             struct_def.attributes.Lookup("native_custom_alloc")) {
2144*890232f2SAndroid Build Coastguard Worker       code_ += "  inline void *operator new (std::size_t count) {";
2145*890232f2SAndroid Build Coastguard Worker       code_ += "    return " + native_custom_alloc->constant +
2146*890232f2SAndroid Build Coastguard Worker                "<{{NATIVE_NAME}}>().allocate(count / sizeof({{NATIVE_NAME}}));";
2147*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2148*890232f2SAndroid Build Coastguard Worker       code_ += "  inline void operator delete (void *ptr) {";
2149*890232f2SAndroid Build Coastguard Worker       code_ += "    return " + native_custom_alloc->constant +
2150*890232f2SAndroid Build Coastguard Worker                "<{{NATIVE_NAME}}>().deallocate(static_cast<{{NATIVE_NAME}}*>("
2151*890232f2SAndroid Build Coastguard Worker                "ptr),1);";
2152*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2153*890232f2SAndroid Build Coastguard Worker     }
2154*890232f2SAndroid Build Coastguard Worker   }
2155*890232f2SAndroid Build Coastguard Worker 
GenNativeTable(const StructDef & struct_def)2156*890232f2SAndroid Build Coastguard Worker   void GenNativeTable(const StructDef &struct_def) {
2157*890232f2SAndroid Build Coastguard Worker     const auto native_name = NativeName(Name(struct_def), &struct_def, opts_);
2158*890232f2SAndroid Build Coastguard Worker     code_.SetValue("STRUCT_NAME", Name(struct_def));
2159*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NATIVE_NAME", native_name);
2160*890232f2SAndroid Build Coastguard Worker 
2161*890232f2SAndroid Build Coastguard Worker     // Generate a C++ object that can hold an unpacked version of this table.
2162*890232f2SAndroid Build Coastguard Worker     code_ += "struct {{NATIVE_NAME}} : public flatbuffers::NativeTable {";
2163*890232f2SAndroid Build Coastguard Worker     code_ += "  typedef {{STRUCT_NAME}} TableType;";
2164*890232f2SAndroid Build Coastguard Worker     GenFullyQualifiedNameGetter(struct_def, native_name);
2165*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2166*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2167*890232f2SAndroid Build Coastguard Worker       GenMember(**it);
2168*890232f2SAndroid Build Coastguard Worker     }
2169*890232f2SAndroid Build Coastguard Worker     GenOperatorNewDelete(struct_def);
2170*890232f2SAndroid Build Coastguard Worker     GenDefaultConstructor(struct_def);
2171*890232f2SAndroid Build Coastguard Worker     GenCopyMoveCtorAndAssigOpDecls(struct_def);
2172*890232f2SAndroid Build Coastguard Worker     code_ += "};";
2173*890232f2SAndroid Build Coastguard Worker     code_ += "";
2174*890232f2SAndroid Build Coastguard Worker   }
2175*890232f2SAndroid Build Coastguard Worker 
GenNativeTablePost(const StructDef & struct_def)2176*890232f2SAndroid Build Coastguard Worker   void GenNativeTablePost(const StructDef &struct_def) {
2177*890232f2SAndroid Build Coastguard Worker     if (opts_.gen_compare) {
2178*890232f2SAndroid Build Coastguard Worker       const auto native_name = NativeName(Name(struct_def), &struct_def, opts_);
2179*890232f2SAndroid Build Coastguard Worker       code_.SetValue("STRUCT_NAME", Name(struct_def));
2180*890232f2SAndroid Build Coastguard Worker       code_.SetValue("NATIVE_NAME", native_name);
2181*890232f2SAndroid Build Coastguard Worker       GenCompareOperator(struct_def);
2182*890232f2SAndroid Build Coastguard Worker       code_ += "";
2183*890232f2SAndroid Build Coastguard Worker     }
2184*890232f2SAndroid Build Coastguard Worker   }
2185*890232f2SAndroid Build Coastguard Worker 
2186*890232f2SAndroid Build Coastguard Worker   // Generate the code to call the appropriate Verify function(s) for a field.
GenVerifyCall(const FieldDef & field,const char * prefix)2187*890232f2SAndroid Build Coastguard Worker   void GenVerifyCall(const FieldDef &field, const char *prefix) {
2188*890232f2SAndroid Build Coastguard Worker     code_.SetValue("PRE", prefix);
2189*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NAME", Name(field));
2190*890232f2SAndroid Build Coastguard Worker     code_.SetValue("REQUIRED", field.IsRequired() ? "Required" : "");
2191*890232f2SAndroid Build Coastguard Worker     code_.SetValue("SIZE", GenTypeSize(field.value.type));
2192*890232f2SAndroid Build Coastguard Worker     code_.SetValue("OFFSET", GenFieldOffsetName(field));
2193*890232f2SAndroid Build Coastguard Worker     if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
2194*890232f2SAndroid Build Coastguard Worker       code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type)));
2195*890232f2SAndroid Build Coastguard Worker       code_ +=
2196*890232f2SAndroid Build Coastguard Worker           "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
2197*890232f2SAndroid Build Coastguard Worker           "{{OFFSET}}, {{ALIGN}})\\";
2198*890232f2SAndroid Build Coastguard Worker     } else {
2199*890232f2SAndroid Build Coastguard Worker       code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
2200*890232f2SAndroid Build Coastguard Worker     }
2201*890232f2SAndroid Build Coastguard Worker 
2202*890232f2SAndroid Build Coastguard Worker     switch (field.value.type.base_type) {
2203*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UNION: {
2204*890232f2SAndroid Build Coastguard Worker         code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
2205*890232f2SAndroid Build Coastguard Worker         code_.SetValue("SUFFIX", UnionTypeFieldSuffix());
2206*890232f2SAndroid Build Coastguard Worker         code_ +=
2207*890232f2SAndroid Build Coastguard Worker             "{{PRE}}Verify{{ENUM_NAME}}(verifier, {{NAME}}(), "
2208*890232f2SAndroid Build Coastguard Worker             "{{NAME}}{{SUFFIX}}())\\";
2209*890232f2SAndroid Build Coastguard Worker         break;
2210*890232f2SAndroid Build Coastguard Worker       }
2211*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRUCT: {
2212*890232f2SAndroid Build Coastguard Worker         if (!field.value.type.struct_def->fixed) {
2213*890232f2SAndroid Build Coastguard Worker           code_ += "{{PRE}}verifier.VerifyTable({{NAME}}())\\";
2214*890232f2SAndroid Build Coastguard Worker         }
2215*890232f2SAndroid Build Coastguard Worker         break;
2216*890232f2SAndroid Build Coastguard Worker       }
2217*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRING: {
2218*890232f2SAndroid Build Coastguard Worker         code_ += "{{PRE}}verifier.VerifyString({{NAME}}())\\";
2219*890232f2SAndroid Build Coastguard Worker         break;
2220*890232f2SAndroid Build Coastguard Worker       }
2221*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_VECTOR: {
2222*890232f2SAndroid Build Coastguard Worker         code_ += "{{PRE}}verifier.VerifyVector({{NAME}}())\\";
2223*890232f2SAndroid Build Coastguard Worker 
2224*890232f2SAndroid Build Coastguard Worker         switch (field.value.type.element) {
2225*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_STRING: {
2226*890232f2SAndroid Build Coastguard Worker             code_ += "{{PRE}}verifier.VerifyVectorOfStrings({{NAME}}())\\";
2227*890232f2SAndroid Build Coastguard Worker             break;
2228*890232f2SAndroid Build Coastguard Worker           }
2229*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_STRUCT: {
2230*890232f2SAndroid Build Coastguard Worker             if (!field.value.type.struct_def->fixed) {
2231*890232f2SAndroid Build Coastguard Worker               code_ += "{{PRE}}verifier.VerifyVectorOfTables({{NAME}}())\\";
2232*890232f2SAndroid Build Coastguard Worker             }
2233*890232f2SAndroid Build Coastguard Worker             break;
2234*890232f2SAndroid Build Coastguard Worker           }
2235*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_UNION: {
2236*890232f2SAndroid Build Coastguard Worker             code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
2237*890232f2SAndroid Build Coastguard Worker             code_ +=
2238*890232f2SAndroid Build Coastguard Worker                 "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), "
2239*890232f2SAndroid Build Coastguard Worker                 "{{NAME}}_type())\\";
2240*890232f2SAndroid Build Coastguard Worker             break;
2241*890232f2SAndroid Build Coastguard Worker           }
2242*890232f2SAndroid Build Coastguard Worker           default: break;
2243*890232f2SAndroid Build Coastguard Worker         }
2244*890232f2SAndroid Build Coastguard Worker 
2245*890232f2SAndroid Build Coastguard Worker         auto nfn = GetNestedFlatBufferName(field);
2246*890232f2SAndroid Build Coastguard Worker         if (!nfn.empty()) {
2247*890232f2SAndroid Build Coastguard Worker           code_.SetValue("CPP_NAME", nfn);
2248*890232f2SAndroid Build Coastguard Worker           // FIXME: file_identifier.
2249*890232f2SAndroid Build Coastguard Worker           code_ +=
2250*890232f2SAndroid Build Coastguard Worker               "{{PRE}}verifier.VerifyNestedFlatBuffer<{{CPP_NAME}}>"
2251*890232f2SAndroid Build Coastguard Worker               "({{NAME}}(), nullptr)\\";
2252*890232f2SAndroid Build Coastguard Worker         } else if (field.flexbuffer) {
2253*890232f2SAndroid Build Coastguard Worker           code_ +=
2254*890232f2SAndroid Build Coastguard Worker               "{{PRE}}flexbuffers::VerifyNestedFlexBuffer"
2255*890232f2SAndroid Build Coastguard Worker               "({{NAME}}(), verifier)\\";
2256*890232f2SAndroid Build Coastguard Worker         }
2257*890232f2SAndroid Build Coastguard Worker         break;
2258*890232f2SAndroid Build Coastguard Worker       }
2259*890232f2SAndroid Build Coastguard Worker       default: {
2260*890232f2SAndroid Build Coastguard Worker         break;
2261*890232f2SAndroid Build Coastguard Worker       }
2262*890232f2SAndroid Build Coastguard Worker     }
2263*890232f2SAndroid Build Coastguard Worker   }
2264*890232f2SAndroid Build Coastguard Worker 
2265*890232f2SAndroid Build Coastguard Worker   // Generate CompareWithValue method for a key field.
GenKeyFieldMethods(const FieldDef & field)2266*890232f2SAndroid Build Coastguard Worker   void GenKeyFieldMethods(const FieldDef &field) {
2267*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(field.key);
2268*890232f2SAndroid Build Coastguard Worker     const bool is_string = (IsString(field.value.type));
2269*890232f2SAndroid Build Coastguard Worker 
2270*890232f2SAndroid Build Coastguard Worker     code_ += "  bool KeyCompareLessThan(const {{STRUCT_NAME}} *o) const {";
2271*890232f2SAndroid Build Coastguard Worker     if (is_string) {
2272*890232f2SAndroid Build Coastguard Worker       // use operator< of flatbuffers::String
2273*890232f2SAndroid Build Coastguard Worker       code_ += "    return *{{FIELD_NAME}}() < *o->{{FIELD_NAME}}();";
2274*890232f2SAndroid Build Coastguard Worker     } else {
2275*890232f2SAndroid Build Coastguard Worker       code_ += "    return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
2276*890232f2SAndroid Build Coastguard Worker     }
2277*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
2278*890232f2SAndroid Build Coastguard Worker 
2279*890232f2SAndroid Build Coastguard Worker     if (is_string) {
2280*890232f2SAndroid Build Coastguard Worker       code_ += "  int KeyCompareWithValue(const char *_{{FIELD_NAME}}) const {";
2281*890232f2SAndroid Build Coastguard Worker       code_ += "    return strcmp({{FIELD_NAME}}()->c_str(), _{{FIELD_NAME}});";
2282*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2283*890232f2SAndroid Build Coastguard Worker     } else {
2284*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(IsScalar(field.value.type.base_type));
2285*890232f2SAndroid Build Coastguard Worker       auto type = GenTypeBasic(field.value.type, false);
2286*890232f2SAndroid Build Coastguard Worker       if (opts_.scoped_enums && field.value.type.enum_def &&
2287*890232f2SAndroid Build Coastguard Worker           IsScalar(field.value.type.base_type)) {
2288*890232f2SAndroid Build Coastguard Worker         type = GenTypeGet(field.value.type, " ", "const ", " *", true);
2289*890232f2SAndroid Build Coastguard Worker       }
2290*890232f2SAndroid Build Coastguard Worker       // Returns {field<val: -1, field==val: 0, field>val: +1}.
2291*890232f2SAndroid Build Coastguard Worker       code_.SetValue("KEY_TYPE", type);
2292*890232f2SAndroid Build Coastguard Worker       code_ +=
2293*890232f2SAndroid Build Coastguard Worker           "  int KeyCompareWithValue({{KEY_TYPE}} _{{FIELD_NAME}}) const {";
2294*890232f2SAndroid Build Coastguard Worker       code_ +=
2295*890232f2SAndroid Build Coastguard Worker           "    return static_cast<int>({{FIELD_NAME}}() > _{{FIELD_NAME}}) - "
2296*890232f2SAndroid Build Coastguard Worker           "static_cast<int>({{FIELD_NAME}}() < _{{FIELD_NAME}});";
2297*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2298*890232f2SAndroid Build Coastguard Worker     }
2299*890232f2SAndroid Build Coastguard Worker   }
2300*890232f2SAndroid Build Coastguard Worker 
GenTableUnionAsGetters(const FieldDef & field)2301*890232f2SAndroid Build Coastguard Worker   void GenTableUnionAsGetters(const FieldDef &field) {
2302*890232f2SAndroid Build Coastguard Worker     const auto &type = field.value.type;
2303*890232f2SAndroid Build Coastguard Worker     auto u = type.enum_def;
2304*890232f2SAndroid Build Coastguard Worker 
2305*890232f2SAndroid Build Coastguard Worker     if (!type.enum_def->uses_multiple_type_instances)
2306*890232f2SAndroid Build Coastguard Worker       code_ +=
2307*890232f2SAndroid Build Coastguard Worker           "  template<typename T> "
2308*890232f2SAndroid Build Coastguard Worker           "const T *{{NULLABLE_EXT}}{{FIELD_NAME}}_as() const;";
2309*890232f2SAndroid Build Coastguard Worker 
2310*890232f2SAndroid Build Coastguard Worker     for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
2311*890232f2SAndroid Build Coastguard Worker       auto &ev = **u_it;
2312*890232f2SAndroid Build Coastguard Worker       if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
2313*890232f2SAndroid Build Coastguard Worker       auto full_struct_name = GetUnionElement(ev, false, opts_);
2314*890232f2SAndroid Build Coastguard Worker 
2315*890232f2SAndroid Build Coastguard Worker       // @TODO: Mby make this decisions more universal? How?
2316*890232f2SAndroid Build Coastguard Worker       code_.SetValue("U_GET_TYPE",
2317*890232f2SAndroid Build Coastguard Worker                      EscapeKeyword(Name(field) + UnionTypeFieldSuffix()));
2318*890232f2SAndroid Build Coastguard Worker       code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(u->defined_namespace,
2319*890232f2SAndroid Build Coastguard Worker                                                        GetEnumValUse(*u, ev)));
2320*890232f2SAndroid Build Coastguard Worker       code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
2321*890232f2SAndroid Build Coastguard Worker       code_.SetValue("U_FIELD_NAME", Name(field) + "_as_" + Name(ev));
2322*890232f2SAndroid Build Coastguard Worker       code_.SetValue("U_NULLABLE", NullableExtension());
2323*890232f2SAndroid Build Coastguard Worker 
2324*890232f2SAndroid Build Coastguard Worker       // `const Type *union_name_asType() const` accessor.
2325*890232f2SAndroid Build Coastguard Worker       code_ += "  {{U_FIELD_TYPE}}{{U_NULLABLE}}{{U_FIELD_NAME}}() const {";
2326*890232f2SAndroid Build Coastguard Worker       code_ +=
2327*890232f2SAndroid Build Coastguard Worker           "    return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
2328*890232f2SAndroid Build Coastguard Worker           "static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
2329*890232f2SAndroid Build Coastguard Worker           ": nullptr;";
2330*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2331*890232f2SAndroid Build Coastguard Worker     }
2332*890232f2SAndroid Build Coastguard Worker   }
2333*890232f2SAndroid Build Coastguard Worker 
GenTableFieldGetter(const FieldDef & field)2334*890232f2SAndroid Build Coastguard Worker   void GenTableFieldGetter(const FieldDef &field) {
2335*890232f2SAndroid Build Coastguard Worker     const auto &type = field.value.type;
2336*890232f2SAndroid Build Coastguard Worker     const auto offset_str = GenFieldOffsetName(field);
2337*890232f2SAndroid Build Coastguard Worker 
2338*890232f2SAndroid Build Coastguard Worker     GenComment(field.doc_comment, "  ");
2339*890232f2SAndroid Build Coastguard Worker     // Call a different accessor for pointers, that indirects.
2340*890232f2SAndroid Build Coastguard Worker     if (false == field.IsScalarOptional()) {
2341*890232f2SAndroid Build Coastguard Worker       const bool is_scalar = IsScalar(type.base_type);
2342*890232f2SAndroid Build Coastguard Worker       std::string accessor;
2343*890232f2SAndroid Build Coastguard Worker       if (is_scalar)
2344*890232f2SAndroid Build Coastguard Worker         accessor = "GetField<";
2345*890232f2SAndroid Build Coastguard Worker       else if (IsStruct(type))
2346*890232f2SAndroid Build Coastguard Worker         accessor = "GetStruct<";
2347*890232f2SAndroid Build Coastguard Worker       else
2348*890232f2SAndroid Build Coastguard Worker         accessor = "GetPointer<";
2349*890232f2SAndroid Build Coastguard Worker       auto offset_type = GenTypeGet(type, "", "const ", " *", false);
2350*890232f2SAndroid Build Coastguard Worker       auto call = accessor + offset_type + ">(" + offset_str;
2351*890232f2SAndroid Build Coastguard Worker       // Default value as second arg for non-pointer types.
2352*890232f2SAndroid Build Coastguard Worker       if (is_scalar) { call += ", " + GenDefaultConstant(field); }
2353*890232f2SAndroid Build Coastguard Worker       call += ")";
2354*890232f2SAndroid Build Coastguard Worker 
2355*890232f2SAndroid Build Coastguard Worker       std::string afterptr = " *" + NullableExtension();
2356*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE",
2357*890232f2SAndroid Build Coastguard Worker                      GenTypeGet(type, " ", "const ", afterptr.c_str(), true));
2358*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call));
2359*890232f2SAndroid Build Coastguard Worker       code_.SetValue("NULLABLE_EXT", NullableExtension());
2360*890232f2SAndroid Build Coastguard Worker       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
2361*890232f2SAndroid Build Coastguard Worker       code_ += "    return {{FIELD_VALUE}};";
2362*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2363*890232f2SAndroid Build Coastguard Worker     } else {
2364*890232f2SAndroid Build Coastguard Worker       auto wire_type = GenTypeBasic(type, false);
2365*890232f2SAndroid Build Coastguard Worker       auto face_type = GenTypeBasic(type, true);
2366*890232f2SAndroid Build Coastguard Worker       auto opt_value = "GetOptional<" + wire_type + ", " + face_type + ">(" +
2367*890232f2SAndroid Build Coastguard Worker                        offset_str + ")";
2368*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", GenOptionalDecl(type));
2369*890232f2SAndroid Build Coastguard Worker       code_ += "  {{FIELD_TYPE}} {{FIELD_NAME}}() const {";
2370*890232f2SAndroid Build Coastguard Worker       code_ += "    return " + opt_value + ";";
2371*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2372*890232f2SAndroid Build Coastguard Worker     }
2373*890232f2SAndroid Build Coastguard Worker 
2374*890232f2SAndroid Build Coastguard Worker     if (type.base_type == BASE_TYPE_UNION) { GenTableUnionAsGetters(field); }
2375*890232f2SAndroid Build Coastguard Worker   }
2376*890232f2SAndroid Build Coastguard Worker 
GenTableFieldType(const FieldDef & field)2377*890232f2SAndroid Build Coastguard Worker   void GenTableFieldType(const FieldDef &field) {
2378*890232f2SAndroid Build Coastguard Worker     const auto &type = field.value.type;
2379*890232f2SAndroid Build Coastguard Worker     const auto offset_str = GenFieldOffsetName(field);
2380*890232f2SAndroid Build Coastguard Worker     if (!field.IsScalarOptional()) {
2381*890232f2SAndroid Build Coastguard Worker       std::string afterptr = " *" + NullableExtension();
2382*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE",
2383*890232f2SAndroid Build Coastguard Worker                      GenTypeGet(type, "", "const ", afterptr.c_str(), true));
2384*890232f2SAndroid Build Coastguard Worker       code_ += "    {{FIELD_TYPE}}\\";
2385*890232f2SAndroid Build Coastguard Worker     } else {
2386*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", GenOptionalDecl(type));
2387*890232f2SAndroid Build Coastguard Worker       code_ += "    {{FIELD_TYPE}}\\";
2388*890232f2SAndroid Build Coastguard Worker     }
2389*890232f2SAndroid Build Coastguard Worker   }
2390*890232f2SAndroid Build Coastguard Worker 
GenStructFieldType(const FieldDef & field)2391*890232f2SAndroid Build Coastguard Worker   void GenStructFieldType(const FieldDef &field) {
2392*890232f2SAndroid Build Coastguard Worker     const auto is_array = IsArray(field.value.type);
2393*890232f2SAndroid Build Coastguard Worker     std::string field_type =
2394*890232f2SAndroid Build Coastguard Worker         GenTypeGet(field.value.type, "", is_array ? "" : "const ",
2395*890232f2SAndroid Build Coastguard Worker                    is_array ? "" : " &", true);
2396*890232f2SAndroid Build Coastguard Worker     code_.SetValue("FIELD_TYPE", field_type);
2397*890232f2SAndroid Build Coastguard Worker     code_ += "    {{FIELD_TYPE}}\\";
2398*890232f2SAndroid Build Coastguard Worker   }
2399*890232f2SAndroid Build Coastguard Worker 
GenFieldTypeHelper(const StructDef & struct_def)2400*890232f2SAndroid Build Coastguard Worker   void GenFieldTypeHelper(const StructDef &struct_def) {
2401*890232f2SAndroid Build Coastguard Worker     if (struct_def.fields.vec.empty()) { return; }
2402*890232f2SAndroid Build Coastguard Worker     code_ += "  template<size_t Index>";
2403*890232f2SAndroid Build Coastguard Worker     code_ += "  using FieldType = \\";
2404*890232f2SAndroid Build Coastguard Worker     code_ += "decltype(std::declval<type>().get_field<Index>());";
2405*890232f2SAndroid Build Coastguard Worker   }
2406*890232f2SAndroid Build Coastguard Worker 
GenIndexBasedFieldGetter(const StructDef & struct_def)2407*890232f2SAndroid Build Coastguard Worker   void GenIndexBasedFieldGetter(const StructDef &struct_def) {
2408*890232f2SAndroid Build Coastguard Worker     if (struct_def.fields.vec.empty()) { return; }
2409*890232f2SAndroid Build Coastguard Worker     code_ += "  template<size_t Index>";
2410*890232f2SAndroid Build Coastguard Worker     code_ += "  auto get_field() const {";
2411*890232f2SAndroid Build Coastguard Worker 
2412*890232f2SAndroid Build Coastguard Worker     size_t index = 0;
2413*890232f2SAndroid Build Coastguard Worker     bool need_else = false;
2414*890232f2SAndroid Build Coastguard Worker     // Generate one index-based getter for each field.
2415*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2416*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2417*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2418*890232f2SAndroid Build Coastguard Worker       if (field.deprecated) {
2419*890232f2SAndroid Build Coastguard Worker         // Deprecated fields won't be accessible.
2420*890232f2SAndroid Build Coastguard Worker         continue;
2421*890232f2SAndroid Build Coastguard Worker       }
2422*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
2423*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_INDEX",
2424*890232f2SAndroid Build Coastguard Worker                      std::to_string(static_cast<long long>(index++)));
2425*890232f2SAndroid Build Coastguard Worker       if (need_else) {
2426*890232f2SAndroid Build Coastguard Worker         code_ += "    else \\";
2427*890232f2SAndroid Build Coastguard Worker       } else {
2428*890232f2SAndroid Build Coastguard Worker         code_ += "         \\";
2429*890232f2SAndroid Build Coastguard Worker       }
2430*890232f2SAndroid Build Coastguard Worker       need_else = true;
2431*890232f2SAndroid Build Coastguard Worker       code_ += "if constexpr (Index == {{FIELD_INDEX}}) \\";
2432*890232f2SAndroid Build Coastguard Worker       code_ += "return {{FIELD_NAME}}();";
2433*890232f2SAndroid Build Coastguard Worker     }
2434*890232f2SAndroid Build Coastguard Worker     code_ += "    else static_assert(Index != Index, \"Invalid Field Index\");";
2435*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
2436*890232f2SAndroid Build Coastguard Worker   }
2437*890232f2SAndroid Build Coastguard Worker 
2438*890232f2SAndroid Build Coastguard Worker   // Sample for Vec3:
2439*890232f2SAndroid Build Coastguard Worker   //
2440*890232f2SAndroid Build Coastguard Worker   //   static constexpr std::array<const char *, 3> field_names = {
2441*890232f2SAndroid Build Coastguard Worker   //     "x",
2442*890232f2SAndroid Build Coastguard Worker   //     "y",
2443*890232f2SAndroid Build Coastguard Worker   //     "z"
2444*890232f2SAndroid Build Coastguard Worker   //   };
2445*890232f2SAndroid Build Coastguard Worker   //
GenFieldNames(const StructDef & struct_def)2446*890232f2SAndroid Build Coastguard Worker   void GenFieldNames(const StructDef &struct_def) {
2447*890232f2SAndroid Build Coastguard Worker     code_ += "  static constexpr std::array<\\";
2448*890232f2SAndroid Build Coastguard Worker     code_ += "const char *, fields_number> field_names = {\\";
2449*890232f2SAndroid Build Coastguard Worker     if (struct_def.fields.vec.empty()) {
2450*890232f2SAndroid Build Coastguard Worker       code_ += "};";
2451*890232f2SAndroid Build Coastguard Worker       return;
2452*890232f2SAndroid Build Coastguard Worker     }
2453*890232f2SAndroid Build Coastguard Worker     code_ += "";
2454*890232f2SAndroid Build Coastguard Worker     // Generate the field_names elements.
2455*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2456*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2457*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2458*890232f2SAndroid Build Coastguard Worker       if (field.deprecated) {
2459*890232f2SAndroid Build Coastguard Worker         // Deprecated fields won't be accessible.
2460*890232f2SAndroid Build Coastguard Worker         continue;
2461*890232f2SAndroid Build Coastguard Worker       }
2462*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
2463*890232f2SAndroid Build Coastguard Worker       code_ += "    \"{{FIELD_NAME}}\"\\";
2464*890232f2SAndroid Build Coastguard Worker       if (it + 1 != struct_def.fields.vec.end()) { code_ += ","; }
2465*890232f2SAndroid Build Coastguard Worker     }
2466*890232f2SAndroid Build Coastguard Worker     code_ += "\n  };";
2467*890232f2SAndroid Build Coastguard Worker   }
2468*890232f2SAndroid Build Coastguard Worker 
GenFieldsNumber(const StructDef & struct_def)2469*890232f2SAndroid Build Coastguard Worker   void GenFieldsNumber(const StructDef &struct_def) {
2470*890232f2SAndroid Build Coastguard Worker     const auto non_deprecated_field_count = std::count_if(
2471*890232f2SAndroid Build Coastguard Worker         struct_def.fields.vec.begin(), struct_def.fields.vec.end(),
2472*890232f2SAndroid Build Coastguard Worker         [](const FieldDef *field) { return !field->deprecated; });
2473*890232f2SAndroid Build Coastguard Worker     code_.SetValue(
2474*890232f2SAndroid Build Coastguard Worker         "FIELD_COUNT",
2475*890232f2SAndroid Build Coastguard Worker         std::to_string(static_cast<long long>(non_deprecated_field_count)));
2476*890232f2SAndroid Build Coastguard Worker     code_ += "  static constexpr size_t fields_number = {{FIELD_COUNT}};";
2477*890232f2SAndroid Build Coastguard Worker   }
2478*890232f2SAndroid Build Coastguard Worker 
GenTraitsStruct(const StructDef & struct_def)2479*890232f2SAndroid Build Coastguard Worker   void GenTraitsStruct(const StructDef &struct_def) {
2480*890232f2SAndroid Build Coastguard Worker     code_.SetValue(
2481*890232f2SAndroid Build Coastguard Worker         "FULLY_QUALIFIED_NAME",
2482*890232f2SAndroid Build Coastguard Worker         struct_def.defined_namespace->GetFullyQualifiedName(Name(struct_def)));
2483*890232f2SAndroid Build Coastguard Worker     code_ += "struct {{STRUCT_NAME}}::Traits {";
2484*890232f2SAndroid Build Coastguard Worker     code_ += "  using type = {{STRUCT_NAME}};";
2485*890232f2SAndroid Build Coastguard Worker     if (!struct_def.fixed) {
2486*890232f2SAndroid Build Coastguard Worker       // We have a table and not a struct.
2487*890232f2SAndroid Build Coastguard Worker       code_ += "  static auto constexpr Create = Create{{STRUCT_NAME}};";
2488*890232f2SAndroid Build Coastguard Worker     }
2489*890232f2SAndroid Build Coastguard Worker     if (opts_.cpp_static_reflection) {
2490*890232f2SAndroid Build Coastguard Worker       code_ += "  static constexpr auto name = \"{{STRUCT_NAME}}\";";
2491*890232f2SAndroid Build Coastguard Worker       code_ +=
2492*890232f2SAndroid Build Coastguard Worker           "  static constexpr auto fully_qualified_name = "
2493*890232f2SAndroid Build Coastguard Worker           "\"{{FULLY_QUALIFIED_NAME}}\";";
2494*890232f2SAndroid Build Coastguard Worker       GenFieldsNumber(struct_def);
2495*890232f2SAndroid Build Coastguard Worker       GenFieldNames(struct_def);
2496*890232f2SAndroid Build Coastguard Worker       GenFieldTypeHelper(struct_def);
2497*890232f2SAndroid Build Coastguard Worker     }
2498*890232f2SAndroid Build Coastguard Worker     code_ += "};";
2499*890232f2SAndroid Build Coastguard Worker     code_ += "";
2500*890232f2SAndroid Build Coastguard Worker   }
2501*890232f2SAndroid Build Coastguard Worker 
GenTableFieldSetter(const FieldDef & field)2502*890232f2SAndroid Build Coastguard Worker   void GenTableFieldSetter(const FieldDef &field) {
2503*890232f2SAndroid Build Coastguard Worker     const auto &type = field.value.type;
2504*890232f2SAndroid Build Coastguard Worker     const bool is_scalar = IsScalar(type.base_type);
2505*890232f2SAndroid Build Coastguard Worker     if (is_scalar && IsUnion(type))
2506*890232f2SAndroid Build Coastguard Worker       return;  // changing of a union's type is forbidden
2507*890232f2SAndroid Build Coastguard Worker 
2508*890232f2SAndroid Build Coastguard Worker     auto offset_str = GenFieldOffsetName(field);
2509*890232f2SAndroid Build Coastguard Worker     if (is_scalar) {
2510*890232f2SAndroid Build Coastguard Worker       const auto wire_type = GenTypeWire(type, "", false);
2511*890232f2SAndroid Build Coastguard Worker       code_.SetValue("SET_FN", "SetField<" + wire_type + ">");
2512*890232f2SAndroid Build Coastguard Worker       code_.SetValue("OFFSET_NAME", offset_str);
2513*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", GenTypeBasic(type, true));
2514*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_VALUE",
2515*890232f2SAndroid Build Coastguard Worker                      GenUnderlyingCast(field, false, "_" + Name(field)));
2516*890232f2SAndroid Build Coastguard Worker 
2517*890232f2SAndroid Build Coastguard Worker       code_ += "  bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} _{{FIELD_NAME}}\\";
2518*890232f2SAndroid Build Coastguard Worker       if (false == field.IsScalarOptional()) {
2519*890232f2SAndroid Build Coastguard Worker         code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field));
2520*890232f2SAndroid Build Coastguard Worker         code_.SetValue(
2521*890232f2SAndroid Build Coastguard Worker             "INTERFACE_DEFAULT_VALUE",
2522*890232f2SAndroid Build Coastguard Worker             GenUnderlyingCast(field, true, GenDefaultConstant(field)));
2523*890232f2SAndroid Build Coastguard Worker 
2524*890232f2SAndroid Build Coastguard Worker         // GenUnderlyingCast for a bool field generates 0 != 0
2525*890232f2SAndroid Build Coastguard Worker         // So the type has to be checked and the appropriate default chosen
2526*890232f2SAndroid Build Coastguard Worker         if (IsBool(field.value.type.base_type)) {
2527*890232f2SAndroid Build Coastguard Worker           code_ += " = {{DEFAULT_VALUE}}) {";
2528*890232f2SAndroid Build Coastguard Worker         } else {
2529*890232f2SAndroid Build Coastguard Worker           code_ += " = {{INTERFACE_DEFAULT_VALUE}}) {";
2530*890232f2SAndroid Build Coastguard Worker         }
2531*890232f2SAndroid Build Coastguard Worker         code_ +=
2532*890232f2SAndroid Build Coastguard Worker             "    return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, "
2533*890232f2SAndroid Build Coastguard Worker             "{{DEFAULT_VALUE}});";
2534*890232f2SAndroid Build Coastguard Worker       } else {
2535*890232f2SAndroid Build Coastguard Worker         code_ += ") {";
2536*890232f2SAndroid Build Coastguard Worker         code_ += "    return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}});";
2537*890232f2SAndroid Build Coastguard Worker       }
2538*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2539*890232f2SAndroid Build Coastguard Worker     } else {
2540*890232f2SAndroid Build Coastguard Worker       auto postptr = " *" + NullableExtension();
2541*890232f2SAndroid Build Coastguard Worker       auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true);
2542*890232f2SAndroid Build Coastguard Worker       std::string accessor = IsStruct(type) ? "GetStruct<" : "GetPointer<";
2543*890232f2SAndroid Build Coastguard Worker       auto underlying = accessor + wire_type + ">(" + offset_str + ")";
2544*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", wire_type);
2545*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying));
2546*890232f2SAndroid Build Coastguard Worker 
2547*890232f2SAndroid Build Coastguard Worker       code_ += "  {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
2548*890232f2SAndroid Build Coastguard Worker       code_ += "    return {{FIELD_VALUE}};";
2549*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2550*890232f2SAndroid Build Coastguard Worker     }
2551*890232f2SAndroid Build Coastguard Worker   }
2552*890232f2SAndroid Build Coastguard Worker 
GetNestedFlatBufferName(const FieldDef & field)2553*890232f2SAndroid Build Coastguard Worker   std::string GetNestedFlatBufferName(const FieldDef &field) {
2554*890232f2SAndroid Build Coastguard Worker     auto nested = field.attributes.Lookup("nested_flatbuffer");
2555*890232f2SAndroid Build Coastguard Worker     if (!nested) return "";
2556*890232f2SAndroid Build Coastguard Worker     std::string qualified_name = nested->constant;
2557*890232f2SAndroid Build Coastguard Worker     auto nested_root = parser_.LookupStruct(nested->constant);
2558*890232f2SAndroid Build Coastguard Worker     if (nested_root == nullptr) {
2559*890232f2SAndroid Build Coastguard Worker       qualified_name =
2560*890232f2SAndroid Build Coastguard Worker           parser_.current_namespace_->GetFullyQualifiedName(nested->constant);
2561*890232f2SAndroid Build Coastguard Worker       nested_root = parser_.LookupStruct(qualified_name);
2562*890232f2SAndroid Build Coastguard Worker     }
2563*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(nested_root);  // Guaranteed to exist by parser.
2564*890232f2SAndroid Build Coastguard Worker     (void)nested_root;
2565*890232f2SAndroid Build Coastguard Worker     return TranslateNameSpace(qualified_name);
2566*890232f2SAndroid Build Coastguard Worker   }
2567*890232f2SAndroid Build Coastguard Worker 
2568*890232f2SAndroid Build Coastguard Worker   // Generate an accessor struct, builder structs & function for a table.
GenTable(const StructDef & struct_def)2569*890232f2SAndroid Build Coastguard Worker   void GenTable(const StructDef &struct_def) {
2570*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) { GenNativeTable(struct_def); }
2571*890232f2SAndroid Build Coastguard Worker 
2572*890232f2SAndroid Build Coastguard Worker     // Generate an accessor struct, with methods of the form:
2573*890232f2SAndroid Build Coastguard Worker     // type name() const { return GetField<type>(offset, defaultval); }
2574*890232f2SAndroid Build Coastguard Worker     GenComment(struct_def.doc_comment);
2575*890232f2SAndroid Build Coastguard Worker 
2576*890232f2SAndroid Build Coastguard Worker     code_.SetValue("STRUCT_NAME", Name(struct_def));
2577*890232f2SAndroid Build Coastguard Worker     code_ +=
2578*890232f2SAndroid Build Coastguard Worker         "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS"
2579*890232f2SAndroid Build Coastguard Worker         " : private flatbuffers::Table {";
2580*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) {
2581*890232f2SAndroid Build Coastguard Worker       code_ += "  typedef {{NATIVE_NAME}} NativeTableType;";
2582*890232f2SAndroid Build Coastguard Worker     }
2583*890232f2SAndroid Build Coastguard Worker     code_ += "  typedef {{STRUCT_NAME}}Builder Builder;";
2584*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += "  struct Traits;"; }
2585*890232f2SAndroid Build Coastguard Worker     if (opts_.mini_reflect != IDLOptions::kNone) {
2586*890232f2SAndroid Build Coastguard Worker       code_ +=
2587*890232f2SAndroid Build Coastguard Worker           "  static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
2588*890232f2SAndroid Build Coastguard Worker       code_ += "    return {{STRUCT_NAME}}TypeTable();";
2589*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2590*890232f2SAndroid Build Coastguard Worker     }
2591*890232f2SAndroid Build Coastguard Worker 
2592*890232f2SAndroid Build Coastguard Worker     GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
2593*890232f2SAndroid Build Coastguard Worker 
2594*890232f2SAndroid Build Coastguard Worker     // Generate field id constants.
2595*890232f2SAndroid Build Coastguard Worker     if (struct_def.fields.vec.size() > 0) {
2596*890232f2SAndroid Build Coastguard Worker       // We need to add a trailing comma to all elements except the last one as
2597*890232f2SAndroid Build Coastguard Worker       // older versions of gcc complain about this.
2598*890232f2SAndroid Build Coastguard Worker       code_.SetValue("SEP", "");
2599*890232f2SAndroid Build Coastguard Worker       code_ +=
2600*890232f2SAndroid Build Coastguard Worker           "  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {";
2601*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
2602*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
2603*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
2604*890232f2SAndroid Build Coastguard Worker         if (field.deprecated) {
2605*890232f2SAndroid Build Coastguard Worker           // Deprecated fields won't be accessible.
2606*890232f2SAndroid Build Coastguard Worker           continue;
2607*890232f2SAndroid Build Coastguard Worker         }
2608*890232f2SAndroid Build Coastguard Worker 
2609*890232f2SAndroid Build Coastguard Worker         code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
2610*890232f2SAndroid Build Coastguard Worker         code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
2611*890232f2SAndroid Build Coastguard Worker         code_ += "{{SEP}}    {{OFFSET_NAME}} = {{OFFSET_VALUE}}\\";
2612*890232f2SAndroid Build Coastguard Worker         code_.SetValue("SEP", ",\n");
2613*890232f2SAndroid Build Coastguard Worker       }
2614*890232f2SAndroid Build Coastguard Worker       code_ += "";
2615*890232f2SAndroid Build Coastguard Worker       code_ += "  };";
2616*890232f2SAndroid Build Coastguard Worker     }
2617*890232f2SAndroid Build Coastguard Worker 
2618*890232f2SAndroid Build Coastguard Worker     // Generate the accessors.
2619*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2620*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2621*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2622*890232f2SAndroid Build Coastguard Worker       if (field.deprecated) {
2623*890232f2SAndroid Build Coastguard Worker         // Deprecated fields won't be accessible.
2624*890232f2SAndroid Build Coastguard Worker         continue;
2625*890232f2SAndroid Build Coastguard Worker       }
2626*890232f2SAndroid Build Coastguard Worker 
2627*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
2628*890232f2SAndroid Build Coastguard Worker       GenTableFieldGetter(field);
2629*890232f2SAndroid Build Coastguard Worker       if (opts_.mutable_buffer) { GenTableFieldSetter(field); }
2630*890232f2SAndroid Build Coastguard Worker 
2631*890232f2SAndroid Build Coastguard Worker       auto nfn = GetNestedFlatBufferName(field);
2632*890232f2SAndroid Build Coastguard Worker       if (!nfn.empty()) {
2633*890232f2SAndroid Build Coastguard Worker         code_.SetValue("CPP_NAME", nfn);
2634*890232f2SAndroid Build Coastguard Worker         code_ += "  const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
2635*890232f2SAndroid Build Coastguard Worker         code_ +=
2636*890232f2SAndroid Build Coastguard Worker             "    return "
2637*890232f2SAndroid Build Coastguard Worker             "flatbuffers::GetRoot<{{CPP_NAME}}>({{FIELD_NAME}}()->Data());";
2638*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
2639*890232f2SAndroid Build Coastguard Worker       }
2640*890232f2SAndroid Build Coastguard Worker 
2641*890232f2SAndroid Build Coastguard Worker       if (field.flexbuffer) {
2642*890232f2SAndroid Build Coastguard Worker         code_ +=
2643*890232f2SAndroid Build Coastguard Worker             "  flexbuffers::Reference {{FIELD_NAME}}_flexbuffer_root()"
2644*890232f2SAndroid Build Coastguard Worker             " const {";
2645*890232f2SAndroid Build Coastguard Worker         // Both Data() and size() are const-methods, therefore call order
2646*890232f2SAndroid Build Coastguard Worker         // doesn't matter.
2647*890232f2SAndroid Build Coastguard Worker         code_ +=
2648*890232f2SAndroid Build Coastguard Worker             "    return flexbuffers::GetRoot({{FIELD_NAME}}()->Data(), "
2649*890232f2SAndroid Build Coastguard Worker             "{{FIELD_NAME}}()->size());";
2650*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
2651*890232f2SAndroid Build Coastguard Worker       }
2652*890232f2SAndroid Build Coastguard Worker 
2653*890232f2SAndroid Build Coastguard Worker       // Generate a comparison function for this field if it is a key.
2654*890232f2SAndroid Build Coastguard Worker       if (field.key) { GenKeyFieldMethods(field); }
2655*890232f2SAndroid Build Coastguard Worker     }
2656*890232f2SAndroid Build Coastguard Worker 
2657*890232f2SAndroid Build Coastguard Worker     if (opts_.cpp_static_reflection) { GenIndexBasedFieldGetter(struct_def); }
2658*890232f2SAndroid Build Coastguard Worker 
2659*890232f2SAndroid Build Coastguard Worker     // Generate a verifier function that can check a buffer from an untrusted
2660*890232f2SAndroid Build Coastguard Worker     // source will never cause reads outside the buffer.
2661*890232f2SAndroid Build Coastguard Worker     code_ += "  bool Verify(flatbuffers::Verifier &verifier) const {";
2662*890232f2SAndroid Build Coastguard Worker     code_ += "    return VerifyTableStart(verifier)\\";
2663*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2664*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2665*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2666*890232f2SAndroid Build Coastguard Worker       if (field.deprecated) { continue; }
2667*890232f2SAndroid Build Coastguard Worker       GenVerifyCall(field, " &&\n           ");
2668*890232f2SAndroid Build Coastguard Worker     }
2669*890232f2SAndroid Build Coastguard Worker 
2670*890232f2SAndroid Build Coastguard Worker     code_ += " &&\n           verifier.EndTable();";
2671*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
2672*890232f2SAndroid Build Coastguard Worker 
2673*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) {
2674*890232f2SAndroid Build Coastguard Worker       // Generate the UnPack() pre declaration.
2675*890232f2SAndroid Build Coastguard Worker       code_ += "  " + TableUnPackSignature(struct_def, true, opts_) + ";";
2676*890232f2SAndroid Build Coastguard Worker       code_ += "  " + TableUnPackToSignature(struct_def, true, opts_) + ";";
2677*890232f2SAndroid Build Coastguard Worker       code_ += "  " + TablePackSignature(struct_def, true, opts_) + ";";
2678*890232f2SAndroid Build Coastguard Worker     }
2679*890232f2SAndroid Build Coastguard Worker 
2680*890232f2SAndroid Build Coastguard Worker     code_ += "};";  // End of table.
2681*890232f2SAndroid Build Coastguard Worker     code_ += "";
2682*890232f2SAndroid Build Coastguard Worker 
2683*890232f2SAndroid Build Coastguard Worker     // Explicit specializations for union accessors
2684*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2685*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2686*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2687*890232f2SAndroid Build Coastguard Worker       if (field.deprecated || field.value.type.base_type != BASE_TYPE_UNION) {
2688*890232f2SAndroid Build Coastguard Worker         continue;
2689*890232f2SAndroid Build Coastguard Worker       }
2690*890232f2SAndroid Build Coastguard Worker 
2691*890232f2SAndroid Build Coastguard Worker       auto u = field.value.type.enum_def;
2692*890232f2SAndroid Build Coastguard Worker       if (u->uses_multiple_type_instances) continue;
2693*890232f2SAndroid Build Coastguard Worker 
2694*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
2695*890232f2SAndroid Build Coastguard Worker 
2696*890232f2SAndroid Build Coastguard Worker       for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
2697*890232f2SAndroid Build Coastguard Worker         auto &ev = **u_it;
2698*890232f2SAndroid Build Coastguard Worker         if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
2699*890232f2SAndroid Build Coastguard Worker 
2700*890232f2SAndroid Build Coastguard Worker         auto full_struct_name = GetUnionElement(ev, false, opts_);
2701*890232f2SAndroid Build Coastguard Worker 
2702*890232f2SAndroid Build Coastguard Worker         code_.SetValue(
2703*890232f2SAndroid Build Coastguard Worker             "U_ELEMENT_TYPE",
2704*890232f2SAndroid Build Coastguard Worker             WrapInNameSpace(u->defined_namespace, GetEnumValUse(*u, ev)));
2705*890232f2SAndroid Build Coastguard Worker         code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
2706*890232f2SAndroid Build Coastguard Worker         code_.SetValue("U_ELEMENT_NAME", full_struct_name);
2707*890232f2SAndroid Build Coastguard Worker         code_.SetValue("U_FIELD_NAME", Name(field) + "_as_" + Name(ev));
2708*890232f2SAndroid Build Coastguard Worker 
2709*890232f2SAndroid Build Coastguard Worker         // `template<> const T *union_name_as<T>() const` accessor.
2710*890232f2SAndroid Build Coastguard Worker         code_ +=
2711*890232f2SAndroid Build Coastguard Worker             "template<> "
2712*890232f2SAndroid Build Coastguard Worker             "inline {{U_FIELD_TYPE}}{{STRUCT_NAME}}::{{FIELD_NAME}}_as"
2713*890232f2SAndroid Build Coastguard Worker             "<{{U_ELEMENT_NAME}}>() const {";
2714*890232f2SAndroid Build Coastguard Worker         code_ += "  return {{U_FIELD_NAME}}();";
2715*890232f2SAndroid Build Coastguard Worker         code_ += "}";
2716*890232f2SAndroid Build Coastguard Worker         code_ += "";
2717*890232f2SAndroid Build Coastguard Worker       }
2718*890232f2SAndroid Build Coastguard Worker     }
2719*890232f2SAndroid Build Coastguard Worker 
2720*890232f2SAndroid Build Coastguard Worker     GenBuilders(struct_def);
2721*890232f2SAndroid Build Coastguard Worker 
2722*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) {
2723*890232f2SAndroid Build Coastguard Worker       // Generate a pre-declaration for a CreateX method that works with an
2724*890232f2SAndroid Build Coastguard Worker       // unpacked C++ object.
2725*890232f2SAndroid Build Coastguard Worker       code_ += TableCreateSignature(struct_def, true, opts_) + ";";
2726*890232f2SAndroid Build Coastguard Worker       code_ += "";
2727*890232f2SAndroid Build Coastguard Worker     }
2728*890232f2SAndroid Build Coastguard Worker   }
2729*890232f2SAndroid Build Coastguard Worker 
2730*890232f2SAndroid Build Coastguard Worker   // Generate code to force vector alignment. Return empty string for vector
2731*890232f2SAndroid Build Coastguard Worker   // that doesn't need alignment code.
GenVectorForceAlign(const FieldDef & field,const std::string & field_size)2732*890232f2SAndroid Build Coastguard Worker   std::string GenVectorForceAlign(const FieldDef &field,
2733*890232f2SAndroid Build Coastguard Worker                                   const std::string &field_size) {
2734*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(IsVector(field.value.type));
2735*890232f2SAndroid Build Coastguard Worker     // Get the value of the force_align attribute.
2736*890232f2SAndroid Build Coastguard Worker     const auto *force_align = field.attributes.Lookup("force_align");
2737*890232f2SAndroid Build Coastguard Worker     const int align = force_align ? atoi(force_align->constant.c_str()) : 1;
2738*890232f2SAndroid Build Coastguard Worker     // Generate code to do force_align for the vector.
2739*890232f2SAndroid Build Coastguard Worker     if (align > 1) {
2740*890232f2SAndroid Build Coastguard Worker       const auto vtype = field.value.type.VectorType();
2741*890232f2SAndroid Build Coastguard Worker       const auto type = IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
2742*890232f2SAndroid Build Coastguard Worker                                         : GenTypeWire(vtype, "", false);
2743*890232f2SAndroid Build Coastguard Worker       return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type +
2744*890232f2SAndroid Build Coastguard Worker              "), " + std::to_string(static_cast<long long>(align)) + ");";
2745*890232f2SAndroid Build Coastguard Worker     }
2746*890232f2SAndroid Build Coastguard Worker     return "";
2747*890232f2SAndroid Build Coastguard Worker   }
2748*890232f2SAndroid Build Coastguard Worker 
GenBuilders(const StructDef & struct_def)2749*890232f2SAndroid Build Coastguard Worker   void GenBuilders(const StructDef &struct_def) {
2750*890232f2SAndroid Build Coastguard Worker     code_.SetValue("STRUCT_NAME", Name(struct_def));
2751*890232f2SAndroid Build Coastguard Worker 
2752*890232f2SAndroid Build Coastguard Worker     // Generate a builder struct:
2753*890232f2SAndroid Build Coastguard Worker     code_ += "struct {{STRUCT_NAME}}Builder {";
2754*890232f2SAndroid Build Coastguard Worker     code_ += "  typedef {{STRUCT_NAME}} Table;";
2755*890232f2SAndroid Build Coastguard Worker     code_ += "  flatbuffers::FlatBufferBuilder &fbb_;";
2756*890232f2SAndroid Build Coastguard Worker     code_ += "  flatbuffers::uoffset_t start_;";
2757*890232f2SAndroid Build Coastguard Worker 
2758*890232f2SAndroid Build Coastguard Worker     bool has_string_or_vector_fields = false;
2759*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2760*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2761*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2762*890232f2SAndroid Build Coastguard Worker       if (field.deprecated) continue;
2763*890232f2SAndroid Build Coastguard Worker       const bool is_scalar = IsScalar(field.value.type.base_type);
2764*890232f2SAndroid Build Coastguard Worker       const bool is_default_scalar = is_scalar && !field.IsScalarOptional();
2765*890232f2SAndroid Build Coastguard Worker       const bool is_string = IsString(field.value.type);
2766*890232f2SAndroid Build Coastguard Worker       const bool is_vector = IsVector(field.value.type);
2767*890232f2SAndroid Build Coastguard Worker       if (is_string || is_vector) { has_string_or_vector_fields = true; }
2768*890232f2SAndroid Build Coastguard Worker 
2769*890232f2SAndroid Build Coastguard Worker       std::string offset = GenFieldOffsetName(field);
2770*890232f2SAndroid Build Coastguard Worker       std::string name = GenUnderlyingCast(field, false, Name(field));
2771*890232f2SAndroid Build Coastguard Worker       std::string value = is_default_scalar ? GenDefaultConstant(field) : "";
2772*890232f2SAndroid Build Coastguard Worker 
2773*890232f2SAndroid Build Coastguard Worker       // Generate accessor functions of the form:
2774*890232f2SAndroid Build Coastguard Worker       // void add_name(type name) {
2775*890232f2SAndroid Build Coastguard Worker       //   fbb_.AddElement<type>(offset, name, default);
2776*890232f2SAndroid Build Coastguard Worker       // }
2777*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
2778*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true));
2779*890232f2SAndroid Build Coastguard Worker       code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset);
2780*890232f2SAndroid Build Coastguard Worker       code_.SetValue("ADD_NAME", name);
2781*890232f2SAndroid Build Coastguard Worker       code_.SetValue("ADD_VALUE", value);
2782*890232f2SAndroid Build Coastguard Worker       if (is_scalar) {
2783*890232f2SAndroid Build Coastguard Worker         const auto type = GenTypeWire(field.value.type, "", false);
2784*890232f2SAndroid Build Coastguard Worker         code_.SetValue("ADD_FN", "AddElement<" + type + ">");
2785*890232f2SAndroid Build Coastguard Worker       } else if (IsStruct(field.value.type)) {
2786*890232f2SAndroid Build Coastguard Worker         code_.SetValue("ADD_FN", "AddStruct");
2787*890232f2SAndroid Build Coastguard Worker       } else {
2788*890232f2SAndroid Build Coastguard Worker         code_.SetValue("ADD_FN", "AddOffset");
2789*890232f2SAndroid Build Coastguard Worker       }
2790*890232f2SAndroid Build Coastguard Worker 
2791*890232f2SAndroid Build Coastguard Worker       code_ += "  void add_{{FIELD_NAME}}({{FIELD_TYPE}}{{FIELD_NAME}}) {";
2792*890232f2SAndroid Build Coastguard Worker       code_ += "    fbb_.{{ADD_FN}}(\\";
2793*890232f2SAndroid Build Coastguard Worker       if (is_default_scalar) {
2794*890232f2SAndroid Build Coastguard Worker         code_ += "{{ADD_OFFSET}}, {{ADD_NAME}}, {{ADD_VALUE}});";
2795*890232f2SAndroid Build Coastguard Worker       } else {
2796*890232f2SAndroid Build Coastguard Worker         code_ += "{{ADD_OFFSET}}, {{ADD_NAME}});";
2797*890232f2SAndroid Build Coastguard Worker       }
2798*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
2799*890232f2SAndroid Build Coastguard Worker     }
2800*890232f2SAndroid Build Coastguard Worker 
2801*890232f2SAndroid Build Coastguard Worker     // Builder constructor
2802*890232f2SAndroid Build Coastguard Worker     code_ +=
2803*890232f2SAndroid Build Coastguard Worker         "  explicit {{STRUCT_NAME}}Builder(flatbuffers::FlatBufferBuilder "
2804*890232f2SAndroid Build Coastguard Worker         "&_fbb)";
2805*890232f2SAndroid Build Coastguard Worker     code_ += "        : fbb_(_fbb) {";
2806*890232f2SAndroid Build Coastguard Worker     code_ += "    start_ = fbb_.StartTable();";
2807*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
2808*890232f2SAndroid Build Coastguard Worker 
2809*890232f2SAndroid Build Coastguard Worker     // Finish() function.
2810*890232f2SAndroid Build Coastguard Worker     code_ += "  flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
2811*890232f2SAndroid Build Coastguard Worker     code_ += "    const auto end = fbb_.EndTable(start_);";
2812*890232f2SAndroid Build Coastguard Worker     code_ += "    auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);";
2813*890232f2SAndroid Build Coastguard Worker 
2814*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2815*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2816*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2817*890232f2SAndroid Build Coastguard Worker       if (!field.deprecated && field.IsRequired()) {
2818*890232f2SAndroid Build Coastguard Worker         code_.SetValue("FIELD_NAME", Name(field));
2819*890232f2SAndroid Build Coastguard Worker         code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
2820*890232f2SAndroid Build Coastguard Worker         code_ += "    fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});";
2821*890232f2SAndroid Build Coastguard Worker       }
2822*890232f2SAndroid Build Coastguard Worker     }
2823*890232f2SAndroid Build Coastguard Worker     code_ += "    return o;";
2824*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
2825*890232f2SAndroid Build Coastguard Worker     code_ += "};";
2826*890232f2SAndroid Build Coastguard Worker     code_ += "";
2827*890232f2SAndroid Build Coastguard Worker 
2828*890232f2SAndroid Build Coastguard Worker     // Generate a convenient CreateX function that uses the above builder
2829*890232f2SAndroid Build Coastguard Worker     // to create a table in one go.
2830*890232f2SAndroid Build Coastguard Worker     code_ +=
2831*890232f2SAndroid Build Coastguard Worker         "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
2832*890232f2SAndroid Build Coastguard Worker         "Create{{STRUCT_NAME}}(";
2833*890232f2SAndroid Build Coastguard Worker     code_ += "    flatbuffers::FlatBufferBuilder &_fbb\\";
2834*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
2835*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
2836*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
2837*890232f2SAndroid Build Coastguard Worker       if (!field.deprecated) { GenParam(field, false, ",\n    "); }
2838*890232f2SAndroid Build Coastguard Worker     }
2839*890232f2SAndroid Build Coastguard Worker     code_ += ") {";
2840*890232f2SAndroid Build Coastguard Worker 
2841*890232f2SAndroid Build Coastguard Worker     code_ += "  {{STRUCT_NAME}}Builder builder_(_fbb);";
2842*890232f2SAndroid Build Coastguard Worker     for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
2843*890232f2SAndroid Build Coastguard Worker          size; size /= 2) {
2844*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.rbegin();
2845*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.rend(); ++it) {
2846*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
2847*890232f2SAndroid Build Coastguard Worker         if (!field.deprecated && (!struct_def.sortbysize ||
2848*890232f2SAndroid Build Coastguard Worker                                   size == SizeOf(field.value.type.base_type))) {
2849*890232f2SAndroid Build Coastguard Worker           code_.SetValue("FIELD_NAME", Name(field));
2850*890232f2SAndroid Build Coastguard Worker           if (field.IsScalarOptional()) {
2851*890232f2SAndroid Build Coastguard Worker             code_ +=
2852*890232f2SAndroid Build Coastguard Worker                 "  if({{FIELD_NAME}}) { "
2853*890232f2SAndroid Build Coastguard Worker                 "builder_.add_{{FIELD_NAME}}(*{{FIELD_NAME}}); }";
2854*890232f2SAndroid Build Coastguard Worker           } else {
2855*890232f2SAndroid Build Coastguard Worker             code_ += "  builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});";
2856*890232f2SAndroid Build Coastguard Worker           }
2857*890232f2SAndroid Build Coastguard Worker         }
2858*890232f2SAndroid Build Coastguard Worker       }
2859*890232f2SAndroid Build Coastguard Worker     }
2860*890232f2SAndroid Build Coastguard Worker     code_ += "  return builder_.Finish();";
2861*890232f2SAndroid Build Coastguard Worker     code_ += "}";
2862*890232f2SAndroid Build Coastguard Worker     code_ += "";
2863*890232f2SAndroid Build Coastguard Worker 
2864*890232f2SAndroid Build Coastguard Worker     // Definition for type traits for this table type. This allows querying var-
2865*890232f2SAndroid Build Coastguard Worker     // ious compile-time traits of the table.
2866*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std >= cpp::CPP_STD_17) { GenTraitsStruct(struct_def); }
2867*890232f2SAndroid Build Coastguard Worker 
2868*890232f2SAndroid Build Coastguard Worker     // Generate a CreateXDirect function with vector types as parameters
2869*890232f2SAndroid Build Coastguard Worker     if (opts_.cpp_direct_copy && has_string_or_vector_fields) {
2870*890232f2SAndroid Build Coastguard Worker       code_ +=
2871*890232f2SAndroid Build Coastguard Worker           "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
2872*890232f2SAndroid Build Coastguard Worker           "Create{{STRUCT_NAME}}Direct(";
2873*890232f2SAndroid Build Coastguard Worker       code_ += "    flatbuffers::FlatBufferBuilder &_fbb\\";
2874*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
2875*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
2876*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
2877*890232f2SAndroid Build Coastguard Worker         if (!field.deprecated) { GenParam(field, true, ",\n    "); }
2878*890232f2SAndroid Build Coastguard Worker       }
2879*890232f2SAndroid Build Coastguard Worker       // Need to call "Create" with the struct namespace.
2880*890232f2SAndroid Build Coastguard Worker       const auto qualified_create_name =
2881*890232f2SAndroid Build Coastguard Worker           struct_def.defined_namespace->GetFullyQualifiedName("Create");
2882*890232f2SAndroid Build Coastguard Worker       code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
2883*890232f2SAndroid Build Coastguard Worker       code_ += ") {";
2884*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
2885*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
2886*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
2887*890232f2SAndroid Build Coastguard Worker         if (!field.deprecated) {
2888*890232f2SAndroid Build Coastguard Worker           code_.SetValue("FIELD_NAME", Name(field));
2889*890232f2SAndroid Build Coastguard Worker           if (IsString(field.value.type)) {
2890*890232f2SAndroid Build Coastguard Worker             if (!field.shared) {
2891*890232f2SAndroid Build Coastguard Worker               code_.SetValue("CREATE_STRING", "CreateString");
2892*890232f2SAndroid Build Coastguard Worker             } else {
2893*890232f2SAndroid Build Coastguard Worker               code_.SetValue("CREATE_STRING", "CreateSharedString");
2894*890232f2SAndroid Build Coastguard Worker             }
2895*890232f2SAndroid Build Coastguard Worker             code_ +=
2896*890232f2SAndroid Build Coastguard Worker                 "  auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
2897*890232f2SAndroid Build Coastguard Worker                 "_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
2898*890232f2SAndroid Build Coastguard Worker           } else if (IsVector(field.value.type)) {
2899*890232f2SAndroid Build Coastguard Worker             const std::string force_align_code =
2900*890232f2SAndroid Build Coastguard Worker                 GenVectorForceAlign(field, Name(field) + "->size()");
2901*890232f2SAndroid Build Coastguard Worker             if (!force_align_code.empty()) {
2902*890232f2SAndroid Build Coastguard Worker               code_ += "  if ({{FIELD_NAME}}) { " + force_align_code + " }";
2903*890232f2SAndroid Build Coastguard Worker             }
2904*890232f2SAndroid Build Coastguard Worker             code_ += "  auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
2905*890232f2SAndroid Build Coastguard Worker             const auto vtype = field.value.type.VectorType();
2906*890232f2SAndroid Build Coastguard Worker             const auto has_key = TypeHasKey(vtype);
2907*890232f2SAndroid Build Coastguard Worker             if (IsStruct(vtype)) {
2908*890232f2SAndroid Build Coastguard Worker               const auto type = WrapInNameSpace(*vtype.struct_def);
2909*890232f2SAndroid Build Coastguard Worker               code_ += (has_key ? "_fbb.CreateVectorOfSortedStructs<"
2910*890232f2SAndroid Build Coastguard Worker                                 : "_fbb.CreateVectorOfStructs<") +
2911*890232f2SAndroid Build Coastguard Worker                        type + ">\\";
2912*890232f2SAndroid Build Coastguard Worker             } else if (has_key) {
2913*890232f2SAndroid Build Coastguard Worker               const auto type = WrapInNameSpace(*vtype.struct_def);
2914*890232f2SAndroid Build Coastguard Worker               code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
2915*890232f2SAndroid Build Coastguard Worker             } else {
2916*890232f2SAndroid Build Coastguard Worker               const auto type =
2917*890232f2SAndroid Build Coastguard Worker                   GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
2918*890232f2SAndroid Build Coastguard Worker               code_ += "_fbb.CreateVector<" + type + ">\\";
2919*890232f2SAndroid Build Coastguard Worker             }
2920*890232f2SAndroid Build Coastguard Worker             code_ +=
2921*890232f2SAndroid Build Coastguard Worker                 has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
2922*890232f2SAndroid Build Coastguard Worker           }
2923*890232f2SAndroid Build Coastguard Worker         }
2924*890232f2SAndroid Build Coastguard Worker       }
2925*890232f2SAndroid Build Coastguard Worker       code_ += "  return {{CREATE_NAME}}{{STRUCT_NAME}}(";
2926*890232f2SAndroid Build Coastguard Worker       code_ += "      _fbb\\";
2927*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
2928*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
2929*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
2930*890232f2SAndroid Build Coastguard Worker         if (!field.deprecated) {
2931*890232f2SAndroid Build Coastguard Worker           code_.SetValue("FIELD_NAME", Name(field));
2932*890232f2SAndroid Build Coastguard Worker           code_ += ",\n      {{FIELD_NAME}}\\";
2933*890232f2SAndroid Build Coastguard Worker           if (IsString(field.value.type) || IsVector(field.value.type)) {
2934*890232f2SAndroid Build Coastguard Worker             code_ += "__\\";
2935*890232f2SAndroid Build Coastguard Worker           }
2936*890232f2SAndroid Build Coastguard Worker         }
2937*890232f2SAndroid Build Coastguard Worker       }
2938*890232f2SAndroid Build Coastguard Worker       code_ += ");";
2939*890232f2SAndroid Build Coastguard Worker       code_ += "}";
2940*890232f2SAndroid Build Coastguard Worker       code_ += "";
2941*890232f2SAndroid Build Coastguard Worker     }
2942*890232f2SAndroid Build Coastguard Worker   }
2943*890232f2SAndroid Build Coastguard Worker 
GenUnionUnpackVal(const FieldDef & afield,const char * vec_elem_access,const char * vec_type_access)2944*890232f2SAndroid Build Coastguard Worker   std::string GenUnionUnpackVal(const FieldDef &afield,
2945*890232f2SAndroid Build Coastguard Worker                                 const char *vec_elem_access,
2946*890232f2SAndroid Build Coastguard Worker                                 const char *vec_type_access) {
2947*890232f2SAndroid Build Coastguard Worker     auto type_name = WrapInNameSpace(*afield.value.type.enum_def);
2948*890232f2SAndroid Build Coastguard Worker     return type_name + "Union::UnPack(" + "_e" + vec_elem_access + ", " +
2949*890232f2SAndroid Build Coastguard Worker            EscapeKeyword(afield.name + UnionTypeFieldSuffix()) + "()" +
2950*890232f2SAndroid Build Coastguard Worker            vec_type_access + ", _resolver)";
2951*890232f2SAndroid Build Coastguard Worker   }
2952*890232f2SAndroid Build Coastguard Worker 
GenUnpackVal(const Type & type,const std::string & val,bool invector,const FieldDef & afield)2953*890232f2SAndroid Build Coastguard Worker   std::string GenUnpackVal(const Type &type, const std::string &val,
2954*890232f2SAndroid Build Coastguard Worker                            bool invector, const FieldDef &afield) {
2955*890232f2SAndroid Build Coastguard Worker     switch (type.base_type) {
2956*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRING: {
2957*890232f2SAndroid Build Coastguard Worker         if (FlexibleStringConstructor(&afield)) {
2958*890232f2SAndroid Build Coastguard Worker           return NativeString(&afield) + "(" + val + "->c_str(), " + val +
2959*890232f2SAndroid Build Coastguard Worker                  "->size())";
2960*890232f2SAndroid Build Coastguard Worker         } else {
2961*890232f2SAndroid Build Coastguard Worker           return val + "->str()";
2962*890232f2SAndroid Build Coastguard Worker         }
2963*890232f2SAndroid Build Coastguard Worker       }
2964*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRUCT: {
2965*890232f2SAndroid Build Coastguard Worker         if (IsStruct(type)) {
2966*890232f2SAndroid Build Coastguard Worker           const auto &struct_attrs = type.struct_def->attributes;
2967*890232f2SAndroid Build Coastguard Worker           const auto native_type = struct_attrs.Lookup("native_type");
2968*890232f2SAndroid Build Coastguard Worker           if (native_type) {
2969*890232f2SAndroid Build Coastguard Worker             std::string unpack_call = "flatbuffers::UnPack";
2970*890232f2SAndroid Build Coastguard Worker             const auto pack_name = struct_attrs.Lookup("native_type_pack_name");
2971*890232f2SAndroid Build Coastguard Worker             if (pack_name) { unpack_call += pack_name->constant; }
2972*890232f2SAndroid Build Coastguard Worker             unpack_call += "(*" + val + ")";
2973*890232f2SAndroid Build Coastguard Worker             return unpack_call;
2974*890232f2SAndroid Build Coastguard Worker           } else if (invector || afield.native_inline) {
2975*890232f2SAndroid Build Coastguard Worker             return "*" + val;
2976*890232f2SAndroid Build Coastguard Worker           } else {
2977*890232f2SAndroid Build Coastguard Worker             const auto name = WrapInNameSpace(*type.struct_def);
2978*890232f2SAndroid Build Coastguard Worker             const auto ptype = GenTypeNativePtr(name, &afield, true);
2979*890232f2SAndroid Build Coastguard Worker             return ptype + "(new " + name + "(*" + val + "))";
2980*890232f2SAndroid Build Coastguard Worker           }
2981*890232f2SAndroid Build Coastguard Worker         } else {
2982*890232f2SAndroid Build Coastguard Worker           const auto ptype = GenTypeNativePtr(
2983*890232f2SAndroid Build Coastguard Worker               WrapNativeNameInNameSpace(*type.struct_def, opts_), &afield,
2984*890232f2SAndroid Build Coastguard Worker               true);
2985*890232f2SAndroid Build Coastguard Worker           return ptype + "(" + val + "->UnPack(_resolver))";
2986*890232f2SAndroid Build Coastguard Worker         }
2987*890232f2SAndroid Build Coastguard Worker       }
2988*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UNION: {
2989*890232f2SAndroid Build Coastguard Worker         return GenUnionUnpackVal(
2990*890232f2SAndroid Build Coastguard Worker             afield, invector ? "->Get(_i)" : "",
2991*890232f2SAndroid Build Coastguard Worker             invector ? ("->GetEnum<" + type.enum_def->name + ">(_i)").c_str()
2992*890232f2SAndroid Build Coastguard Worker                      : "");
2993*890232f2SAndroid Build Coastguard Worker       }
2994*890232f2SAndroid Build Coastguard Worker       default: {
2995*890232f2SAndroid Build Coastguard Worker         return val;
2996*890232f2SAndroid Build Coastguard Worker         break;
2997*890232f2SAndroid Build Coastguard Worker       }
2998*890232f2SAndroid Build Coastguard Worker     }
2999*890232f2SAndroid Build Coastguard Worker   }
3000*890232f2SAndroid Build Coastguard Worker 
GenUnpackFieldStatement(const FieldDef & field,const FieldDef * union_field)3001*890232f2SAndroid Build Coastguard Worker   std::string GenUnpackFieldStatement(const FieldDef &field,
3002*890232f2SAndroid Build Coastguard Worker                                       const FieldDef *union_field) {
3003*890232f2SAndroid Build Coastguard Worker     std::string code;
3004*890232f2SAndroid Build Coastguard Worker     switch (field.value.type.base_type) {
3005*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_VECTOR: {
3006*890232f2SAndroid Build Coastguard Worker         auto name = Name(field);
3007*890232f2SAndroid Build Coastguard Worker         if (field.value.type.element == BASE_TYPE_UTYPE) {
3008*890232f2SAndroid Build Coastguard Worker           name = StripUnionType(Name(field));
3009*890232f2SAndroid Build Coastguard Worker         }
3010*890232f2SAndroid Build Coastguard Worker         code += "{ _o->" + name + ".resize(_e->size()); ";
3011*890232f2SAndroid Build Coastguard Worker         if (!field.value.type.enum_def && !IsBool(field.value.type.element) &&
3012*890232f2SAndroid Build Coastguard Worker             IsOneByte(field.value.type.element)) {
3013*890232f2SAndroid Build Coastguard Worker           // For vectors of bytes, std::copy is used to improve performance.
3014*890232f2SAndroid Build Coastguard Worker           // This doesn't work for:
3015*890232f2SAndroid Build Coastguard Worker           //  - enum types because they have to be explicitly static_cast.
3016*890232f2SAndroid Build Coastguard Worker           //  - vectors of bool, since they are a template specialization.
3017*890232f2SAndroid Build Coastguard Worker           //  - multiple-byte types due to endianness.
3018*890232f2SAndroid Build Coastguard Worker           code +=
3019*890232f2SAndroid Build Coastguard Worker               "std::copy(_e->begin(), _e->end(), _o->" + name + ".begin()); }";
3020*890232f2SAndroid Build Coastguard Worker         } else {
3021*890232f2SAndroid Build Coastguard Worker           std::string indexing;
3022*890232f2SAndroid Build Coastguard Worker           if (field.value.type.enum_def) {
3023*890232f2SAndroid Build Coastguard Worker             indexing += "static_cast<" +
3024*890232f2SAndroid Build Coastguard Worker                         WrapInNameSpace(*field.value.type.enum_def) + ">(";
3025*890232f2SAndroid Build Coastguard Worker           }
3026*890232f2SAndroid Build Coastguard Worker           indexing += "_e->Get(_i)";
3027*890232f2SAndroid Build Coastguard Worker           if (field.value.type.enum_def) { indexing += ")"; }
3028*890232f2SAndroid Build Coastguard Worker           if (field.value.type.element == BASE_TYPE_BOOL) {
3029*890232f2SAndroid Build Coastguard Worker             indexing += " != 0";
3030*890232f2SAndroid Build Coastguard Worker           }
3031*890232f2SAndroid Build Coastguard Worker           // Generate code that pushes data from _e to _o in the form:
3032*890232f2SAndroid Build Coastguard Worker           //   for (uoffset_t i = 0; i < _e->size(); ++i) {
3033*890232f2SAndroid Build Coastguard Worker           //     _o->field.push_back(_e->Get(_i));
3034*890232f2SAndroid Build Coastguard Worker           //   }
3035*890232f2SAndroid Build Coastguard Worker           auto access =
3036*890232f2SAndroid Build Coastguard Worker               field.value.type.element == BASE_TYPE_UTYPE
3037*890232f2SAndroid Build Coastguard Worker                   ? ".type"
3038*890232f2SAndroid Build Coastguard Worker                   : (field.value.type.element == BASE_TYPE_UNION ? ".value"
3039*890232f2SAndroid Build Coastguard Worker                                                                  : "");
3040*890232f2SAndroid Build Coastguard Worker 
3041*890232f2SAndroid Build Coastguard Worker           code += "for (flatbuffers::uoffset_t _i = 0;";
3042*890232f2SAndroid Build Coastguard Worker           code += " _i < _e->size(); _i++) { ";
3043*890232f2SAndroid Build Coastguard Worker           auto cpp_type = field.attributes.Lookup("cpp_type");
3044*890232f2SAndroid Build Coastguard Worker           if (cpp_type) {
3045*890232f2SAndroid Build Coastguard Worker             // Generate code that resolves the cpp pointer type, of the form:
3046*890232f2SAndroid Build Coastguard Worker             //  if (resolver)
3047*890232f2SAndroid Build Coastguard Worker             //    (*resolver)(&_o->field, (hash_value_t)(_e));
3048*890232f2SAndroid Build Coastguard Worker             //  else
3049*890232f2SAndroid Build Coastguard Worker             //    _o->field = nullptr;
3050*890232f2SAndroid Build Coastguard Worker             code += "//vector resolver, " + PtrType(&field) + "\n";
3051*890232f2SAndroid Build Coastguard Worker             code += "if (_resolver) ";
3052*890232f2SAndroid Build Coastguard Worker             code += "(*_resolver)";
3053*890232f2SAndroid Build Coastguard Worker             code += "(reinterpret_cast<void **>(&_o->" + name + "[_i]" +
3054*890232f2SAndroid Build Coastguard Worker                     access + "), ";
3055*890232f2SAndroid Build Coastguard Worker             code +=
3056*890232f2SAndroid Build Coastguard Worker                 "static_cast<flatbuffers::hash_value_t>(" + indexing + "));";
3057*890232f2SAndroid Build Coastguard Worker             if (PtrType(&field) == "naked") {
3058*890232f2SAndroid Build Coastguard Worker               code += " else ";
3059*890232f2SAndroid Build Coastguard Worker               code += "_o->" + name + "[_i]" + access + " = nullptr";
3060*890232f2SAndroid Build Coastguard Worker             } else {
3061*890232f2SAndroid Build Coastguard Worker               // code += " else ";
3062*890232f2SAndroid Build Coastguard Worker               // code += "_o->" + name + "[_i]" + access + " = " +
3063*890232f2SAndroid Build Coastguard Worker               // GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
3064*890232f2SAndroid Build Coastguard Worker               code += "/* else do nothing */";
3065*890232f2SAndroid Build Coastguard Worker             }
3066*890232f2SAndroid Build Coastguard Worker           } else {
3067*890232f2SAndroid Build Coastguard Worker             // clang-format off
3068*890232f2SAndroid Build Coastguard Worker             #if FLATBUFFERS_CPP_OBJECT_UNPACKTO
3069*890232f2SAndroid Build Coastguard Worker             const bool is_pointer =
3070*890232f2SAndroid Build Coastguard Worker                 field.value.type.VectorType().base_type == BASE_TYPE_STRUCT &&
3071*890232f2SAndroid Build Coastguard Worker                 !IsStruct(field.value.type.VectorType());
3072*890232f2SAndroid Build Coastguard Worker             if (is_pointer) {
3073*890232f2SAndroid Build Coastguard Worker               code += "if(_o->" + name + "[_i]" + ") { ";
3074*890232f2SAndroid Build Coastguard Worker               code += indexing + "->UnPackTo(_o->" + name +
3075*890232f2SAndroid Build Coastguard Worker                       "[_i].get(), _resolver);";
3076*890232f2SAndroid Build Coastguard Worker               code += " } else { ";
3077*890232f2SAndroid Build Coastguard Worker             }
3078*890232f2SAndroid Build Coastguard Worker             #endif
3079*890232f2SAndroid Build Coastguard Worker             code += "_o->" + name + "[_i]" + access + " = ";
3080*890232f2SAndroid Build Coastguard Worker             code += GenUnpackVal(field.value.type.VectorType(), indexing, true,
3081*890232f2SAndroid Build Coastguard Worker                                  field);
3082*890232f2SAndroid Build Coastguard Worker             #if FLATBUFFERS_CPP_OBJECT_UNPACKTO
3083*890232f2SAndroid Build Coastguard Worker             if (is_pointer) { code += "; }"; }
3084*890232f2SAndroid Build Coastguard Worker             #endif
3085*890232f2SAndroid Build Coastguard Worker             // clang-format on
3086*890232f2SAndroid Build Coastguard Worker           }
3087*890232f2SAndroid Build Coastguard Worker           code += "; } }";
3088*890232f2SAndroid Build Coastguard Worker         }
3089*890232f2SAndroid Build Coastguard Worker         break;
3090*890232f2SAndroid Build Coastguard Worker       }
3091*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UTYPE: {
3092*890232f2SAndroid Build Coastguard Worker         FLATBUFFERS_ASSERT(union_field->value.type.base_type ==
3093*890232f2SAndroid Build Coastguard Worker                            BASE_TYPE_UNION);
3094*890232f2SAndroid Build Coastguard Worker         // Generate code that sets the union type, of the form:
3095*890232f2SAndroid Build Coastguard Worker         //   _o->field.type = _e;
3096*890232f2SAndroid Build Coastguard Worker         code += "_o->" + union_field->name + ".type = _e;";
3097*890232f2SAndroid Build Coastguard Worker         break;
3098*890232f2SAndroid Build Coastguard Worker       }
3099*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UNION: {
3100*890232f2SAndroid Build Coastguard Worker         // Generate code that sets the union value, of the form:
3101*890232f2SAndroid Build Coastguard Worker         //   _o->field.value = Union::Unpack(_e, field_type(), resolver);
3102*890232f2SAndroid Build Coastguard Worker         code += "_o->" + Name(field) + ".value = ";
3103*890232f2SAndroid Build Coastguard Worker         code += GenUnionUnpackVal(field, "", "");
3104*890232f2SAndroid Build Coastguard Worker         code += ";";
3105*890232f2SAndroid Build Coastguard Worker         break;
3106*890232f2SAndroid Build Coastguard Worker       }
3107*890232f2SAndroid Build Coastguard Worker       default: {
3108*890232f2SAndroid Build Coastguard Worker         auto cpp_type = field.attributes.Lookup("cpp_type");
3109*890232f2SAndroid Build Coastguard Worker         if (cpp_type) {
3110*890232f2SAndroid Build Coastguard Worker           // Generate code that resolves the cpp pointer type, of the form:
3111*890232f2SAndroid Build Coastguard Worker           //  if (resolver)
3112*890232f2SAndroid Build Coastguard Worker           //    (*resolver)(&_o->field, (hash_value_t)(_e));
3113*890232f2SAndroid Build Coastguard Worker           //  else
3114*890232f2SAndroid Build Coastguard Worker           //    _o->field = nullptr;
3115*890232f2SAndroid Build Coastguard Worker           code += "//scalar resolver, " + PtrType(&field) + " \n";
3116*890232f2SAndroid Build Coastguard Worker           code += "if (_resolver) ";
3117*890232f2SAndroid Build Coastguard Worker           code += "(*_resolver)";
3118*890232f2SAndroid Build Coastguard Worker           code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), ";
3119*890232f2SAndroid Build Coastguard Worker           code += "static_cast<flatbuffers::hash_value_t>(_e));";
3120*890232f2SAndroid Build Coastguard Worker           if (PtrType(&field) == "naked") {
3121*890232f2SAndroid Build Coastguard Worker             code += " else ";
3122*890232f2SAndroid Build Coastguard Worker             code += "_o->" + Name(field) + " = nullptr;";
3123*890232f2SAndroid Build Coastguard Worker           } else {
3124*890232f2SAndroid Build Coastguard Worker             // code += " else ";
3125*890232f2SAndroid Build Coastguard Worker             // code += "_o->" + Name(field) + " = " +
3126*890232f2SAndroid Build Coastguard Worker             // GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
3127*890232f2SAndroid Build Coastguard Worker             code += "/* else do nothing */;";
3128*890232f2SAndroid Build Coastguard Worker           }
3129*890232f2SAndroid Build Coastguard Worker         } else {
3130*890232f2SAndroid Build Coastguard Worker           // Generate code for assigning the value, of the form:
3131*890232f2SAndroid Build Coastguard Worker           //  _o->field = value;
3132*890232f2SAndroid Build Coastguard Worker           // clang-format off
3133*890232f2SAndroid Build Coastguard Worker           #if FLATBUFFERS_CPP_OBJECT_UNPACKTO
3134*890232f2SAndroid Build Coastguard Worker           const bool is_pointer =
3135*890232f2SAndroid Build Coastguard Worker               field.value.type.base_type == BASE_TYPE_STRUCT &&
3136*890232f2SAndroid Build Coastguard Worker               !IsStruct(field.value.type);
3137*890232f2SAndroid Build Coastguard Worker           if (is_pointer) {
3138*890232f2SAndroid Build Coastguard Worker             code += "{ if(_o->" + Name(field) + ") { ";
3139*890232f2SAndroid Build Coastguard Worker             code += "_e->UnPackTo(_o->" + Name(field) + ".get(), _resolver);";
3140*890232f2SAndroid Build Coastguard Worker             code += " } else { ";
3141*890232f2SAndroid Build Coastguard Worker           }
3142*890232f2SAndroid Build Coastguard Worker           #endif
3143*890232f2SAndroid Build Coastguard Worker           code += "_o->" + Name(field) + " = ";
3144*890232f2SAndroid Build Coastguard Worker           code += GenUnpackVal(field.value.type, "_e", false, field) + ";";
3145*890232f2SAndroid Build Coastguard Worker           #if FLATBUFFERS_CPP_OBJECT_UNPACKTO
3146*890232f2SAndroid Build Coastguard Worker           if (is_pointer) { code += " } }"; }
3147*890232f2SAndroid Build Coastguard Worker           #endif
3148*890232f2SAndroid Build Coastguard Worker           // clang-format on
3149*890232f2SAndroid Build Coastguard Worker         }
3150*890232f2SAndroid Build Coastguard Worker         break;
3151*890232f2SAndroid Build Coastguard Worker       }
3152*890232f2SAndroid Build Coastguard Worker     }
3153*890232f2SAndroid Build Coastguard Worker     return code;
3154*890232f2SAndroid Build Coastguard Worker   }
3155*890232f2SAndroid Build Coastguard Worker 
GenCreateParam(const FieldDef & field)3156*890232f2SAndroid Build Coastguard Worker   std::string GenCreateParam(const FieldDef &field) {
3157*890232f2SAndroid Build Coastguard Worker     std::string value = "_o->";
3158*890232f2SAndroid Build Coastguard Worker     if (field.value.type.base_type == BASE_TYPE_UTYPE) {
3159*890232f2SAndroid Build Coastguard Worker       value += StripUnionType(Name(field));
3160*890232f2SAndroid Build Coastguard Worker       value += ".type";
3161*890232f2SAndroid Build Coastguard Worker     } else {
3162*890232f2SAndroid Build Coastguard Worker       value += Name(field);
3163*890232f2SAndroid Build Coastguard Worker     }
3164*890232f2SAndroid Build Coastguard Worker     if (field.value.type.base_type != BASE_TYPE_VECTOR &&
3165*890232f2SAndroid Build Coastguard Worker         field.attributes.Lookup("cpp_type")) {
3166*890232f2SAndroid Build Coastguard Worker       auto type = GenTypeBasic(field.value.type, false);
3167*890232f2SAndroid Build Coastguard Worker       value =
3168*890232f2SAndroid Build Coastguard Worker           "_rehasher ? "
3169*890232f2SAndroid Build Coastguard Worker           "static_cast<" +
3170*890232f2SAndroid Build Coastguard Worker           type + ">((*_rehasher)(" + value + GenPtrGet(field) + ")) : 0";
3171*890232f2SAndroid Build Coastguard Worker     }
3172*890232f2SAndroid Build Coastguard Worker 
3173*890232f2SAndroid Build Coastguard Worker     std::string code;
3174*890232f2SAndroid Build Coastguard Worker     switch (field.value.type.base_type) {
3175*890232f2SAndroid Build Coastguard Worker       // String fields are of the form:
3176*890232f2SAndroid Build Coastguard Worker       //   _fbb.CreateString(_o->field)
3177*890232f2SAndroid Build Coastguard Worker       // or
3178*890232f2SAndroid Build Coastguard Worker       //   _fbb.CreateSharedString(_o->field)
3179*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRING: {
3180*890232f2SAndroid Build Coastguard Worker         if (!field.shared) {
3181*890232f2SAndroid Build Coastguard Worker           code += "_fbb.CreateString(";
3182*890232f2SAndroid Build Coastguard Worker         } else {
3183*890232f2SAndroid Build Coastguard Worker           code += "_fbb.CreateSharedString(";
3184*890232f2SAndroid Build Coastguard Worker         }
3185*890232f2SAndroid Build Coastguard Worker         code += value;
3186*890232f2SAndroid Build Coastguard Worker         code.push_back(')');
3187*890232f2SAndroid Build Coastguard Worker 
3188*890232f2SAndroid Build Coastguard Worker         // For optional fields, check to see if there actually is any data
3189*890232f2SAndroid Build Coastguard Worker         // in _o->field before attempting to access it. If there isn't,
3190*890232f2SAndroid Build Coastguard Worker         // depending on set_empty_strings_to_null either set it to 0 or an empty
3191*890232f2SAndroid Build Coastguard Worker         // string.
3192*890232f2SAndroid Build Coastguard Worker         if (!field.IsRequired()) {
3193*890232f2SAndroid Build Coastguard Worker           auto empty_value = opts_.set_empty_strings_to_null
3194*890232f2SAndroid Build Coastguard Worker                                  ? "0"
3195*890232f2SAndroid Build Coastguard Worker                                  : "_fbb.CreateSharedString(\"\")";
3196*890232f2SAndroid Build Coastguard Worker           code = value + ".empty() ? " + empty_value + " : " + code;
3197*890232f2SAndroid Build Coastguard Worker         }
3198*890232f2SAndroid Build Coastguard Worker         break;
3199*890232f2SAndroid Build Coastguard Worker       }
3200*890232f2SAndroid Build Coastguard Worker         // Vector fields come in several flavours, of the forms:
3201*890232f2SAndroid Build Coastguard Worker         //   _fbb.CreateVector(_o->field);
3202*890232f2SAndroid Build Coastguard Worker         //   _fbb.CreateVector((const utype*)_o->field.data(),
3203*890232f2SAndroid Build Coastguard Worker         //   _o->field.size()); _fbb.CreateVectorOfStrings(_o->field)
3204*890232f2SAndroid Build Coastguard Worker         //   _fbb.CreateVectorOfStructs(_o->field)
3205*890232f2SAndroid Build Coastguard Worker         //   _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) {
3206*890232f2SAndroid Build Coastguard Worker         //     return CreateT(_fbb, _o->Get(i), rehasher);
3207*890232f2SAndroid Build Coastguard Worker         //   });
3208*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_VECTOR: {
3209*890232f2SAndroid Build Coastguard Worker         auto vector_type = field.value.type.VectorType();
3210*890232f2SAndroid Build Coastguard Worker         switch (vector_type.base_type) {
3211*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_STRING: {
3212*890232f2SAndroid Build Coastguard Worker             if (NativeString(&field) == "std::string") {
3213*890232f2SAndroid Build Coastguard Worker               code += "_fbb.CreateVectorOfStrings(" + value + ")";
3214*890232f2SAndroid Build Coastguard Worker             } else {
3215*890232f2SAndroid Build Coastguard Worker               // Use by-function serialization to emulate
3216*890232f2SAndroid Build Coastguard Worker               // CreateVectorOfStrings(); this works also with non-std strings.
3217*890232f2SAndroid Build Coastguard Worker               code +=
3218*890232f2SAndroid Build Coastguard Worker                   "_fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>"
3219*890232f2SAndroid Build Coastguard Worker                   " ";
3220*890232f2SAndroid Build Coastguard Worker               code += "(" + value + ".size(), ";
3221*890232f2SAndroid Build Coastguard Worker               code += "[](size_t i, _VectorArgs *__va) { ";
3222*890232f2SAndroid Build Coastguard Worker               code +=
3223*890232f2SAndroid Build Coastguard Worker                   "return __va->__fbb->CreateString(__va->_" + value + "[i]);";
3224*890232f2SAndroid Build Coastguard Worker               code += " }, &_va )";
3225*890232f2SAndroid Build Coastguard Worker             }
3226*890232f2SAndroid Build Coastguard Worker             break;
3227*890232f2SAndroid Build Coastguard Worker           }
3228*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_STRUCT: {
3229*890232f2SAndroid Build Coastguard Worker             if (IsStruct(vector_type)) {
3230*890232f2SAndroid Build Coastguard Worker               const auto &struct_attrs =
3231*890232f2SAndroid Build Coastguard Worker                   field.value.type.struct_def->attributes;
3232*890232f2SAndroid Build Coastguard Worker               const auto native_type = struct_attrs.Lookup("native_type");
3233*890232f2SAndroid Build Coastguard Worker               if (native_type) {
3234*890232f2SAndroid Build Coastguard Worker                 code += "_fbb.CreateVectorOfNativeStructs<";
3235*890232f2SAndroid Build Coastguard Worker                 code += WrapInNameSpace(*vector_type.struct_def) + ", " +
3236*890232f2SAndroid Build Coastguard Worker                         native_type->constant + ">";
3237*890232f2SAndroid Build Coastguard Worker                 code += "(" + value;
3238*890232f2SAndroid Build Coastguard Worker                 const auto pack_name =
3239*890232f2SAndroid Build Coastguard Worker                     struct_attrs.Lookup("native_type_pack_name");
3240*890232f2SAndroid Build Coastguard Worker                 if (pack_name) {
3241*890232f2SAndroid Build Coastguard Worker                   code += ", flatbuffers::Pack" + pack_name->constant;
3242*890232f2SAndroid Build Coastguard Worker                 }
3243*890232f2SAndroid Build Coastguard Worker                 code += ")";
3244*890232f2SAndroid Build Coastguard Worker               } else {
3245*890232f2SAndroid Build Coastguard Worker                 code += "_fbb.CreateVectorOfStructs";
3246*890232f2SAndroid Build Coastguard Worker                 code += "(" + value + ")";
3247*890232f2SAndroid Build Coastguard Worker               }
3248*890232f2SAndroid Build Coastguard Worker             } else {
3249*890232f2SAndroid Build Coastguard Worker               code += "_fbb.CreateVector<flatbuffers::Offset<";
3250*890232f2SAndroid Build Coastguard Worker               code += WrapInNameSpace(*vector_type.struct_def) + ">> ";
3251*890232f2SAndroid Build Coastguard Worker               code += "(" + value + ".size(), ";
3252*890232f2SAndroid Build Coastguard Worker               code += "[](size_t i, _VectorArgs *__va) { ";
3253*890232f2SAndroid Build Coastguard Worker               code += "return Create" + vector_type.struct_def->name;
3254*890232f2SAndroid Build Coastguard Worker               code += "(*__va->__fbb, __va->_" + value + "[i]" +
3255*890232f2SAndroid Build Coastguard Worker                       GenPtrGet(field) + ", ";
3256*890232f2SAndroid Build Coastguard Worker               code += "__va->__rehasher); }, &_va )";
3257*890232f2SAndroid Build Coastguard Worker             }
3258*890232f2SAndroid Build Coastguard Worker             break;
3259*890232f2SAndroid Build Coastguard Worker           }
3260*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_BOOL: {
3261*890232f2SAndroid Build Coastguard Worker             code += "_fbb.CreateVector(" + value + ")";
3262*890232f2SAndroid Build Coastguard Worker             break;
3263*890232f2SAndroid Build Coastguard Worker           }
3264*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_UNION: {
3265*890232f2SAndroid Build Coastguard Worker             code +=
3266*890232f2SAndroid Build Coastguard Worker                 "_fbb.CreateVector<flatbuffers::"
3267*890232f2SAndroid Build Coastguard Worker                 "Offset<void>>(" +
3268*890232f2SAndroid Build Coastguard Worker                 value +
3269*890232f2SAndroid Build Coastguard Worker                 ".size(), [](size_t i, _VectorArgs *__va) { "
3270*890232f2SAndroid Build Coastguard Worker                 "return __va->_" +
3271*890232f2SAndroid Build Coastguard Worker                 value + "[i].Pack(*__va->__fbb, __va->__rehasher); }, &_va)";
3272*890232f2SAndroid Build Coastguard Worker             break;
3273*890232f2SAndroid Build Coastguard Worker           }
3274*890232f2SAndroid Build Coastguard Worker           case BASE_TYPE_UTYPE: {
3275*890232f2SAndroid Build Coastguard Worker             value = StripUnionType(value);
3276*890232f2SAndroid Build Coastguard Worker             auto type = opts_.scoped_enums ? Name(*field.value.type.enum_def)
3277*890232f2SAndroid Build Coastguard Worker                                            : "uint8_t";
3278*890232f2SAndroid Build Coastguard Worker             auto enum_value = "__va->_" + value + "[i].type";
3279*890232f2SAndroid Build Coastguard Worker             if (!opts_.scoped_enums)
3280*890232f2SAndroid Build Coastguard Worker               enum_value = "static_cast<uint8_t>(" + enum_value + ")";
3281*890232f2SAndroid Build Coastguard Worker 
3282*890232f2SAndroid Build Coastguard Worker             code += "_fbb.CreateVector<" + type + ">(" + value +
3283*890232f2SAndroid Build Coastguard Worker                     ".size(), [](size_t i, _VectorArgs *__va) { return " +
3284*890232f2SAndroid Build Coastguard Worker                     enum_value + "; }, &_va)";
3285*890232f2SAndroid Build Coastguard Worker             break;
3286*890232f2SAndroid Build Coastguard Worker           }
3287*890232f2SAndroid Build Coastguard Worker           default: {
3288*890232f2SAndroid Build Coastguard Worker             if (field.value.type.enum_def &&
3289*890232f2SAndroid Build Coastguard Worker                 !VectorElementUserFacing(vector_type)) {
3290*890232f2SAndroid Build Coastguard Worker               // For enumerations, we need to get access to the array data for
3291*890232f2SAndroid Build Coastguard Worker               // the underlying storage type (eg. uint8_t).
3292*890232f2SAndroid Build Coastguard Worker               const auto basetype = GenTypeBasic(
3293*890232f2SAndroid Build Coastguard Worker                   field.value.type.enum_def->underlying_type, false);
3294*890232f2SAndroid Build Coastguard Worker               code += "_fbb.CreateVectorScalarCast<" + basetype +
3295*890232f2SAndroid Build Coastguard Worker                       ">(flatbuffers::data(" + value + "), " + value +
3296*890232f2SAndroid Build Coastguard Worker                       ".size())";
3297*890232f2SAndroid Build Coastguard Worker             } else if (field.attributes.Lookup("cpp_type")) {
3298*890232f2SAndroid Build Coastguard Worker               auto type = GenTypeBasic(vector_type, false);
3299*890232f2SAndroid Build Coastguard Worker               code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), ";
3300*890232f2SAndroid Build Coastguard Worker               code += "[](size_t i, _VectorArgs *__va) { ";
3301*890232f2SAndroid Build Coastguard Worker               code += "return __va->__rehasher ? ";
3302*890232f2SAndroid Build Coastguard Worker               code += "static_cast<" + type + ">((*__va->__rehasher)";
3303*890232f2SAndroid Build Coastguard Worker               code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
3304*890232f2SAndroid Build Coastguard Worker               code += "; }, &_va )";
3305*890232f2SAndroid Build Coastguard Worker             } else {
3306*890232f2SAndroid Build Coastguard Worker               code += "_fbb.CreateVector(" + value + ")";
3307*890232f2SAndroid Build Coastguard Worker             }
3308*890232f2SAndroid Build Coastguard Worker             break;
3309*890232f2SAndroid Build Coastguard Worker           }
3310*890232f2SAndroid Build Coastguard Worker         }
3311*890232f2SAndroid Build Coastguard Worker 
3312*890232f2SAndroid Build Coastguard Worker         // If set_empty_vectors_to_null option is enabled, for optional fields,
3313*890232f2SAndroid Build Coastguard Worker         // check to see if there actually is any data in _o->field before
3314*890232f2SAndroid Build Coastguard Worker         // attempting to access it.
3315*890232f2SAndroid Build Coastguard Worker         if (field.attributes.Lookup("nested_flatbuffer") ||
3316*890232f2SAndroid Build Coastguard Worker             (opts_.set_empty_vectors_to_null && !field.IsRequired())) {
3317*890232f2SAndroid Build Coastguard Worker           code = value + ".size() ? " + code + " : 0";
3318*890232f2SAndroid Build Coastguard Worker         }
3319*890232f2SAndroid Build Coastguard Worker         break;
3320*890232f2SAndroid Build Coastguard Worker       }
3321*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_UNION: {
3322*890232f2SAndroid Build Coastguard Worker         // _o->field.Pack(_fbb);
3323*890232f2SAndroid Build Coastguard Worker         code += value + ".Pack(_fbb)";
3324*890232f2SAndroid Build Coastguard Worker         break;
3325*890232f2SAndroid Build Coastguard Worker       }
3326*890232f2SAndroid Build Coastguard Worker       case BASE_TYPE_STRUCT: {
3327*890232f2SAndroid Build Coastguard Worker         if (IsStruct(field.value.type)) {
3328*890232f2SAndroid Build Coastguard Worker           const auto &struct_attribs = field.value.type.struct_def->attributes;
3329*890232f2SAndroid Build Coastguard Worker           const auto native_type = struct_attribs.Lookup("native_type");
3330*890232f2SAndroid Build Coastguard Worker           if (native_type) {
3331*890232f2SAndroid Build Coastguard Worker             code += "flatbuffers::Pack";
3332*890232f2SAndroid Build Coastguard Worker             const auto pack_name =
3333*890232f2SAndroid Build Coastguard Worker                 struct_attribs.Lookup("native_type_pack_name");
3334*890232f2SAndroid Build Coastguard Worker             if (pack_name) { code += pack_name->constant; }
3335*890232f2SAndroid Build Coastguard Worker             code += "(" + value + ")";
3336*890232f2SAndroid Build Coastguard Worker           } else if (field.native_inline) {
3337*890232f2SAndroid Build Coastguard Worker             code += "&" + value;
3338*890232f2SAndroid Build Coastguard Worker           } else {
3339*890232f2SAndroid Build Coastguard Worker             code += value + " ? " + value + GenPtrGet(field) + " : nullptr";
3340*890232f2SAndroid Build Coastguard Worker           }
3341*890232f2SAndroid Build Coastguard Worker         } else {
3342*890232f2SAndroid Build Coastguard Worker           // _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
3343*890232f2SAndroid Build Coastguard Worker           const auto type = field.value.type.struct_def->name;
3344*890232f2SAndroid Build Coastguard Worker           code += value + " ? Create" + type;
3345*890232f2SAndroid Build Coastguard Worker           code += "(_fbb, " + value + GenPtrGet(field) + ", _rehasher)";
3346*890232f2SAndroid Build Coastguard Worker           code += " : 0";
3347*890232f2SAndroid Build Coastguard Worker         }
3348*890232f2SAndroid Build Coastguard Worker         break;
3349*890232f2SAndroid Build Coastguard Worker       }
3350*890232f2SAndroid Build Coastguard Worker       default: {
3351*890232f2SAndroid Build Coastguard Worker         code += value;
3352*890232f2SAndroid Build Coastguard Worker         break;
3353*890232f2SAndroid Build Coastguard Worker       }
3354*890232f2SAndroid Build Coastguard Worker     }
3355*890232f2SAndroid Build Coastguard Worker     return code;
3356*890232f2SAndroid Build Coastguard Worker   }
3357*890232f2SAndroid Build Coastguard Worker 
3358*890232f2SAndroid Build Coastguard Worker   // Generate code for tables that needs to come after the regular definition.
GenTablePost(const StructDef & struct_def)3359*890232f2SAndroid Build Coastguard Worker   void GenTablePost(const StructDef &struct_def) {
3360*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) { GenNativeTablePost(struct_def); }
3361*890232f2SAndroid Build Coastguard Worker 
3362*890232f2SAndroid Build Coastguard Worker     code_.SetValue("STRUCT_NAME", Name(struct_def));
3363*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NATIVE_NAME",
3364*890232f2SAndroid Build Coastguard Worker                    NativeName(Name(struct_def), &struct_def, opts_));
3365*890232f2SAndroid Build Coastguard Worker 
3366*890232f2SAndroid Build Coastguard Worker     if (opts_.generate_object_based_api) {
3367*890232f2SAndroid Build Coastguard Worker       // Generate the >= C++11 copy ctor and assignment operator definitions.
3368*890232f2SAndroid Build Coastguard Worker       GenCopyCtorAssignOpDefs(struct_def);
3369*890232f2SAndroid Build Coastguard Worker 
3370*890232f2SAndroid Build Coastguard Worker       // Generate the X::UnPack() method.
3371*890232f2SAndroid Build Coastguard Worker       code_ +=
3372*890232f2SAndroid Build Coastguard Worker           "inline " + TableUnPackSignature(struct_def, false, opts_) + " {";
3373*890232f2SAndroid Build Coastguard Worker 
3374*890232f2SAndroid Build Coastguard Worker       if (opts_.g_cpp_std == cpp::CPP_STD_X0) {
3375*890232f2SAndroid Build Coastguard Worker         auto native_name = WrapNativeNameInNameSpace(struct_def, parser_.opts);
3376*890232f2SAndroid Build Coastguard Worker         code_.SetValue("POINTER_TYPE",
3377*890232f2SAndroid Build Coastguard Worker                        GenTypeNativePtr(native_name, nullptr, false));
3378*890232f2SAndroid Build Coastguard Worker         code_ +=
3379*890232f2SAndroid Build Coastguard Worker             "  {{POINTER_TYPE}} _o = {{POINTER_TYPE}}(new {{NATIVE_NAME}}());";
3380*890232f2SAndroid Build Coastguard Worker       } else if (opts_.g_cpp_std == cpp::CPP_STD_11) {
3381*890232f2SAndroid Build Coastguard Worker         code_ +=
3382*890232f2SAndroid Build Coastguard Worker             "  auto _o = std::unique_ptr<{{NATIVE_NAME}}>(new "
3383*890232f2SAndroid Build Coastguard Worker             "{{NATIVE_NAME}}());";
3384*890232f2SAndroid Build Coastguard Worker       } else {
3385*890232f2SAndroid Build Coastguard Worker         code_ += "  auto _o = std::make_unique<{{NATIVE_NAME}}>();";
3386*890232f2SAndroid Build Coastguard Worker       }
3387*890232f2SAndroid Build Coastguard Worker       code_ += "  UnPackTo(_o.get(), _resolver);";
3388*890232f2SAndroid Build Coastguard Worker       code_ += "  return _o.release();";
3389*890232f2SAndroid Build Coastguard Worker       code_ += "}";
3390*890232f2SAndroid Build Coastguard Worker       code_ += "";
3391*890232f2SAndroid Build Coastguard Worker       code_ +=
3392*890232f2SAndroid Build Coastguard Worker           "inline " + TableUnPackToSignature(struct_def, false, opts_) + " {";
3393*890232f2SAndroid Build Coastguard Worker       code_ += "  (void)_o;";
3394*890232f2SAndroid Build Coastguard Worker       code_ += "  (void)_resolver;";
3395*890232f2SAndroid Build Coastguard Worker 
3396*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
3397*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
3398*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
3399*890232f2SAndroid Build Coastguard Worker         if (field.deprecated) { continue; }
3400*890232f2SAndroid Build Coastguard Worker 
3401*890232f2SAndroid Build Coastguard Worker         // Assign a value from |this| to |_o|.   Values from |this| are stored
3402*890232f2SAndroid Build Coastguard Worker         // in a variable |_e| by calling this->field_type().  The value is then
3403*890232f2SAndroid Build Coastguard Worker         // assigned to |_o| using the GenUnpackFieldStatement.
3404*890232f2SAndroid Build Coastguard Worker         const bool is_union = field.value.type.base_type == BASE_TYPE_UTYPE;
3405*890232f2SAndroid Build Coastguard Worker         const auto statement =
3406*890232f2SAndroid Build Coastguard Worker             GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr);
3407*890232f2SAndroid Build Coastguard Worker 
3408*890232f2SAndroid Build Coastguard Worker         code_.SetValue("FIELD_NAME", Name(field));
3409*890232f2SAndroid Build Coastguard Worker         auto prefix = "  { auto _e = {{FIELD_NAME}}(); ";
3410*890232f2SAndroid Build Coastguard Worker         auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) ";
3411*890232f2SAndroid Build Coastguard Worker         auto postfix = " }";
3412*890232f2SAndroid Build Coastguard Worker         code_ += std::string(prefix) + check + statement + postfix;
3413*890232f2SAndroid Build Coastguard Worker       }
3414*890232f2SAndroid Build Coastguard Worker       code_ += "}";
3415*890232f2SAndroid Build Coastguard Worker       code_ += "";
3416*890232f2SAndroid Build Coastguard Worker 
3417*890232f2SAndroid Build Coastguard Worker       // Generate the X::Pack member function that simply calls the global
3418*890232f2SAndroid Build Coastguard Worker       // CreateX function.
3419*890232f2SAndroid Build Coastguard Worker       code_ += "inline " + TablePackSignature(struct_def, false, opts_) + " {";
3420*890232f2SAndroid Build Coastguard Worker       code_ += "  return Create{{STRUCT_NAME}}(_fbb, _o, _rehasher);";
3421*890232f2SAndroid Build Coastguard Worker       code_ += "}";
3422*890232f2SAndroid Build Coastguard Worker       code_ += "";
3423*890232f2SAndroid Build Coastguard Worker 
3424*890232f2SAndroid Build Coastguard Worker       // Generate a CreateX method that works with an unpacked C++ object.
3425*890232f2SAndroid Build Coastguard Worker       code_ +=
3426*890232f2SAndroid Build Coastguard Worker           "inline " + TableCreateSignature(struct_def, false, opts_) + " {";
3427*890232f2SAndroid Build Coastguard Worker       code_ += "  (void)_rehasher;";
3428*890232f2SAndroid Build Coastguard Worker       code_ += "  (void)_o;";
3429*890232f2SAndroid Build Coastguard Worker 
3430*890232f2SAndroid Build Coastguard Worker       code_ +=
3431*890232f2SAndroid Build Coastguard Worker           "  struct _VectorArgs "
3432*890232f2SAndroid Build Coastguard Worker           "{ flatbuffers::FlatBufferBuilder *__fbb; "
3433*890232f2SAndroid Build Coastguard Worker           "const " +
3434*890232f2SAndroid Build Coastguard Worker           NativeName(Name(struct_def), &struct_def, opts_) +
3435*890232f2SAndroid Build Coastguard Worker           "* __o; "
3436*890232f2SAndroid Build Coastguard Worker           "const flatbuffers::rehasher_function_t *__rehasher; } _va = { "
3437*890232f2SAndroid Build Coastguard Worker           "&_fbb, _o, _rehasher}; (void)_va;";
3438*890232f2SAndroid Build Coastguard Worker 
3439*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
3440*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
3441*890232f2SAndroid Build Coastguard Worker         auto &field = **it;
3442*890232f2SAndroid Build Coastguard Worker         if (field.deprecated) { continue; }
3443*890232f2SAndroid Build Coastguard Worker         if (IsVector(field.value.type)) {
3444*890232f2SAndroid Build Coastguard Worker           const std::string force_align_code =
3445*890232f2SAndroid Build Coastguard Worker               GenVectorForceAlign(field, "_o->" + Name(field) + ".size()");
3446*890232f2SAndroid Build Coastguard Worker           if (!force_align_code.empty()) { code_ += "  " + force_align_code; }
3447*890232f2SAndroid Build Coastguard Worker         }
3448*890232f2SAndroid Build Coastguard Worker         code_ += "  auto _" + Name(field) + " = " + GenCreateParam(field) + ";";
3449*890232f2SAndroid Build Coastguard Worker       }
3450*890232f2SAndroid Build Coastguard Worker       // Need to call "Create" with the struct namespace.
3451*890232f2SAndroid Build Coastguard Worker       const auto qualified_create_name =
3452*890232f2SAndroid Build Coastguard Worker           struct_def.defined_namespace->GetFullyQualifiedName("Create");
3453*890232f2SAndroid Build Coastguard Worker       code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
3454*890232f2SAndroid Build Coastguard Worker 
3455*890232f2SAndroid Build Coastguard Worker       code_ += "  return {{CREATE_NAME}}{{STRUCT_NAME}}(";
3456*890232f2SAndroid Build Coastguard Worker       code_ += "      _fbb\\";
3457*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
3458*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
3459*890232f2SAndroid Build Coastguard Worker         auto &field = **it;
3460*890232f2SAndroid Build Coastguard Worker         if (field.deprecated) { continue; }
3461*890232f2SAndroid Build Coastguard Worker 
3462*890232f2SAndroid Build Coastguard Worker         bool pass_by_address = false;
3463*890232f2SAndroid Build Coastguard Worker         if (field.value.type.base_type == BASE_TYPE_STRUCT) {
3464*890232f2SAndroid Build Coastguard Worker           if (IsStruct(field.value.type)) {
3465*890232f2SAndroid Build Coastguard Worker             auto native_type =
3466*890232f2SAndroid Build Coastguard Worker                 field.value.type.struct_def->attributes.Lookup("native_type");
3467*890232f2SAndroid Build Coastguard Worker             if (native_type) { pass_by_address = true; }
3468*890232f2SAndroid Build Coastguard Worker           }
3469*890232f2SAndroid Build Coastguard Worker         }
3470*890232f2SAndroid Build Coastguard Worker 
3471*890232f2SAndroid Build Coastguard Worker         // Call the CreateX function using values from |_o|.
3472*890232f2SAndroid Build Coastguard Worker         if (pass_by_address) {
3473*890232f2SAndroid Build Coastguard Worker           code_ += ",\n      &_" + Name(field) + "\\";
3474*890232f2SAndroid Build Coastguard Worker         } else {
3475*890232f2SAndroid Build Coastguard Worker           code_ += ",\n      _" + Name(field) + "\\";
3476*890232f2SAndroid Build Coastguard Worker         }
3477*890232f2SAndroid Build Coastguard Worker       }
3478*890232f2SAndroid Build Coastguard Worker       code_ += ");";
3479*890232f2SAndroid Build Coastguard Worker       code_ += "}";
3480*890232f2SAndroid Build Coastguard Worker       code_ += "";
3481*890232f2SAndroid Build Coastguard Worker     }
3482*890232f2SAndroid Build Coastguard Worker   }
3483*890232f2SAndroid Build Coastguard Worker 
GenPadding(const FieldDef & field,std::string * code_ptr,int * id,const std::function<void (int bits,std::string * code_ptr,int * id)> & f)3484*890232f2SAndroid Build Coastguard Worker   static void GenPadding(
3485*890232f2SAndroid Build Coastguard Worker       const FieldDef &field, std::string *code_ptr, int *id,
3486*890232f2SAndroid Build Coastguard Worker       const std::function<void(int bits, std::string *code_ptr, int *id)> &f) {
3487*890232f2SAndroid Build Coastguard Worker     if (field.padding) {
3488*890232f2SAndroid Build Coastguard Worker       for (int i = 0; i < 4; i++) {
3489*890232f2SAndroid Build Coastguard Worker         if (static_cast<int>(field.padding) & (1 << i)) {
3490*890232f2SAndroid Build Coastguard Worker           f((1 << i) * 8, code_ptr, id);
3491*890232f2SAndroid Build Coastguard Worker         }
3492*890232f2SAndroid Build Coastguard Worker       }
3493*890232f2SAndroid Build Coastguard Worker       FLATBUFFERS_ASSERT(!(field.padding & ~0xF));
3494*890232f2SAndroid Build Coastguard Worker     }
3495*890232f2SAndroid Build Coastguard Worker   }
3496*890232f2SAndroid Build Coastguard Worker 
PaddingDefinition(int bits,std::string * code_ptr,int * id)3497*890232f2SAndroid Build Coastguard Worker   static void PaddingDefinition(int bits, std::string *code_ptr, int *id) {
3498*890232f2SAndroid Build Coastguard Worker     *code_ptr += "  int" + NumToString(bits) + "_t padding" +
3499*890232f2SAndroid Build Coastguard Worker                  NumToString((*id)++) + "__;";
3500*890232f2SAndroid Build Coastguard Worker   }
3501*890232f2SAndroid Build Coastguard Worker 
PaddingInitializer(int bits,std::string * code_ptr,int * id)3502*890232f2SAndroid Build Coastguard Worker   static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
3503*890232f2SAndroid Build Coastguard Worker     (void)bits;
3504*890232f2SAndroid Build Coastguard Worker     if (!code_ptr->empty()) *code_ptr += ",\n        ";
3505*890232f2SAndroid Build Coastguard Worker     *code_ptr += "padding" + NumToString((*id)++) + "__(0)";
3506*890232f2SAndroid Build Coastguard Worker   }
3507*890232f2SAndroid Build Coastguard Worker 
PaddingNoop(int bits,std::string * code_ptr,int * id)3508*890232f2SAndroid Build Coastguard Worker   static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
3509*890232f2SAndroid Build Coastguard Worker     (void)bits;
3510*890232f2SAndroid Build Coastguard Worker     if (!code_ptr->empty()) *code_ptr += '\n';
3511*890232f2SAndroid Build Coastguard Worker     *code_ptr += "    (void)padding" + NumToString((*id)++) + "__;";
3512*890232f2SAndroid Build Coastguard Worker   }
3513*890232f2SAndroid Build Coastguard Worker 
GenStructDefaultConstructor(const StructDef & struct_def)3514*890232f2SAndroid Build Coastguard Worker   void GenStructDefaultConstructor(const StructDef &struct_def) {
3515*890232f2SAndroid Build Coastguard Worker     std::string init_list;
3516*890232f2SAndroid Build Coastguard Worker     std::string body;
3517*890232f2SAndroid Build Coastguard Worker     bool first_in_init_list = true;
3518*890232f2SAndroid Build Coastguard Worker     int padding_initializer_id = 0;
3519*890232f2SAndroid Build Coastguard Worker     int padding_body_id = 0;
3520*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
3521*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
3522*890232f2SAndroid Build Coastguard Worker       const auto field = *it;
3523*890232f2SAndroid Build Coastguard Worker       const auto field_name = Name(*field) + "_";
3524*890232f2SAndroid Build Coastguard Worker 
3525*890232f2SAndroid Build Coastguard Worker       if (first_in_init_list) {
3526*890232f2SAndroid Build Coastguard Worker         first_in_init_list = false;
3527*890232f2SAndroid Build Coastguard Worker       } else {
3528*890232f2SAndroid Build Coastguard Worker         init_list += ",";
3529*890232f2SAndroid Build Coastguard Worker         init_list += "\n        ";
3530*890232f2SAndroid Build Coastguard Worker       }
3531*890232f2SAndroid Build Coastguard Worker 
3532*890232f2SAndroid Build Coastguard Worker       init_list += field_name;
3533*890232f2SAndroid Build Coastguard Worker       if (IsStruct(field->value.type) || IsArray(field->value.type)) {
3534*890232f2SAndroid Build Coastguard Worker         // this is either default initialization of struct
3535*890232f2SAndroid Build Coastguard Worker         // or
3536*890232f2SAndroid Build Coastguard Worker         // implicit initialization of array
3537*890232f2SAndroid Build Coastguard Worker         // for each object in array it:
3538*890232f2SAndroid Build Coastguard Worker         // * sets it as zeros for POD types (integral, floating point, etc)
3539*890232f2SAndroid Build Coastguard Worker         // * calls default constructor for classes/structs
3540*890232f2SAndroid Build Coastguard Worker         init_list += "()";
3541*890232f2SAndroid Build Coastguard Worker       } else {
3542*890232f2SAndroid Build Coastguard Worker         init_list += "(0)";
3543*890232f2SAndroid Build Coastguard Worker       }
3544*890232f2SAndroid Build Coastguard Worker       if (field->padding) {
3545*890232f2SAndroid Build Coastguard Worker         GenPadding(*field, &init_list, &padding_initializer_id,
3546*890232f2SAndroid Build Coastguard Worker                    PaddingInitializer);
3547*890232f2SAndroid Build Coastguard Worker         GenPadding(*field, &body, &padding_body_id, PaddingNoop);
3548*890232f2SAndroid Build Coastguard Worker       }
3549*890232f2SAndroid Build Coastguard Worker     }
3550*890232f2SAndroid Build Coastguard Worker 
3551*890232f2SAndroid Build Coastguard Worker     if (init_list.empty()) {
3552*890232f2SAndroid Build Coastguard Worker       code_ += "  {{STRUCT_NAME}}()";
3553*890232f2SAndroid Build Coastguard Worker       code_ += "  {}";
3554*890232f2SAndroid Build Coastguard Worker     } else {
3555*890232f2SAndroid Build Coastguard Worker       code_.SetValue("INIT_LIST", init_list);
3556*890232f2SAndroid Build Coastguard Worker       code_ += "  {{STRUCT_NAME}}()";
3557*890232f2SAndroid Build Coastguard Worker       code_ += "      : {{INIT_LIST}} {";
3558*890232f2SAndroid Build Coastguard Worker       if (!body.empty()) { code_ += body; }
3559*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
3560*890232f2SAndroid Build Coastguard Worker     }
3561*890232f2SAndroid Build Coastguard Worker   }
3562*890232f2SAndroid Build Coastguard Worker 
GenStructConstructor(const StructDef & struct_def,GenArrayArgMode array_mode)3563*890232f2SAndroid Build Coastguard Worker   void GenStructConstructor(const StructDef &struct_def,
3564*890232f2SAndroid Build Coastguard Worker                             GenArrayArgMode array_mode) {
3565*890232f2SAndroid Build Coastguard Worker     std::string arg_list;
3566*890232f2SAndroid Build Coastguard Worker     std::string init_list;
3567*890232f2SAndroid Build Coastguard Worker     int padding_id = 0;
3568*890232f2SAndroid Build Coastguard Worker     auto first = struct_def.fields.vec.begin();
3569*890232f2SAndroid Build Coastguard Worker     // skip arrays if generate ctor without array assignment
3570*890232f2SAndroid Build Coastguard Worker     const auto init_arrays = (array_mode != kArrayArgModeNone);
3571*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
3572*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
3573*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
3574*890232f2SAndroid Build Coastguard Worker       const auto &type = field.value.type;
3575*890232f2SAndroid Build Coastguard Worker       const auto is_array = IsArray(type);
3576*890232f2SAndroid Build Coastguard Worker       const auto arg_name = "_" + Name(field);
3577*890232f2SAndroid Build Coastguard Worker       if (!is_array || init_arrays) {
3578*890232f2SAndroid Build Coastguard Worker         if (it != first && !arg_list.empty()) { arg_list += ", "; }
3579*890232f2SAndroid Build Coastguard Worker         arg_list += !is_array ? GenTypeGet(type, " ", "const ", " &", true)
3580*890232f2SAndroid Build Coastguard Worker                               : GenTypeSpan(type, true, type.fixed_length);
3581*890232f2SAndroid Build Coastguard Worker         arg_list += arg_name;
3582*890232f2SAndroid Build Coastguard Worker       }
3583*890232f2SAndroid Build Coastguard Worker       // skip an array with initialization from span
3584*890232f2SAndroid Build Coastguard Worker       if (false == (is_array && init_arrays)) {
3585*890232f2SAndroid Build Coastguard Worker         if (it != first && !init_list.empty()) { init_list += ",\n        "; }
3586*890232f2SAndroid Build Coastguard Worker         init_list += Name(field) + "_";
3587*890232f2SAndroid Build Coastguard Worker         if (IsScalar(type.base_type)) {
3588*890232f2SAndroid Build Coastguard Worker           auto scalar_type = GenUnderlyingCast(field, false, arg_name);
3589*890232f2SAndroid Build Coastguard Worker           init_list += "(flatbuffers::EndianScalar(" + scalar_type + "))";
3590*890232f2SAndroid Build Coastguard Worker         } else {
3591*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT((is_array && !init_arrays) || IsStruct(type));
3592*890232f2SAndroid Build Coastguard Worker           if (!is_array)
3593*890232f2SAndroid Build Coastguard Worker             init_list += "(" + arg_name + ")";
3594*890232f2SAndroid Build Coastguard Worker           else
3595*890232f2SAndroid Build Coastguard Worker             init_list += "()";
3596*890232f2SAndroid Build Coastguard Worker         }
3597*890232f2SAndroid Build Coastguard Worker       }
3598*890232f2SAndroid Build Coastguard Worker       if (field.padding)
3599*890232f2SAndroid Build Coastguard Worker         GenPadding(field, &init_list, &padding_id, PaddingInitializer);
3600*890232f2SAndroid Build Coastguard Worker     }
3601*890232f2SAndroid Build Coastguard Worker 
3602*890232f2SAndroid Build Coastguard Worker     if (!arg_list.empty()) {
3603*890232f2SAndroid Build Coastguard Worker       code_.SetValue("ARG_LIST", arg_list);
3604*890232f2SAndroid Build Coastguard Worker       code_.SetValue("INIT_LIST", init_list);
3605*890232f2SAndroid Build Coastguard Worker       if (!init_list.empty()) {
3606*890232f2SAndroid Build Coastguard Worker         code_ += "  {{STRUCT_NAME}}({{ARG_LIST}})";
3607*890232f2SAndroid Build Coastguard Worker         code_ += "      : {{INIT_LIST}} {";
3608*890232f2SAndroid Build Coastguard Worker       } else {
3609*890232f2SAndroid Build Coastguard Worker         code_ += "  {{STRUCT_NAME}}({{ARG_LIST}}) {";
3610*890232f2SAndroid Build Coastguard Worker       }
3611*890232f2SAndroid Build Coastguard Worker       padding_id = 0;
3612*890232f2SAndroid Build Coastguard Worker       for (auto it = struct_def.fields.vec.begin();
3613*890232f2SAndroid Build Coastguard Worker            it != struct_def.fields.vec.end(); ++it) {
3614*890232f2SAndroid Build Coastguard Worker         const auto &field = **it;
3615*890232f2SAndroid Build Coastguard Worker         const auto &type = field.value.type;
3616*890232f2SAndroid Build Coastguard Worker         if (IsArray(type) && init_arrays) {
3617*890232f2SAndroid Build Coastguard Worker           const auto &element_type = type.VectorType();
3618*890232f2SAndroid Build Coastguard Worker           const auto is_enum = IsEnum(element_type);
3619*890232f2SAndroid Build Coastguard Worker           FLATBUFFERS_ASSERT(
3620*890232f2SAndroid Build Coastguard Worker               (IsScalar(element_type.base_type) || IsStruct(element_type)) &&
3621*890232f2SAndroid Build Coastguard Worker               "invalid declaration");
3622*890232f2SAndroid Build Coastguard Worker           const auto face_type = GenTypeGet(type, " ", "", "", is_enum);
3623*890232f2SAndroid Build Coastguard Worker           std::string get_array =
3624*890232f2SAndroid Build Coastguard Worker               is_enum ? "CastToArrayOfEnum<" + face_type + ">" : "CastToArray";
3625*890232f2SAndroid Build Coastguard Worker           const auto field_name = Name(field) + "_";
3626*890232f2SAndroid Build Coastguard Worker           const auto arg_name = "_" + Name(field);
3627*890232f2SAndroid Build Coastguard Worker           code_ += "    flatbuffers::" + get_array + "(" + field_name +
3628*890232f2SAndroid Build Coastguard Worker                    ").CopyFromSpan(" + arg_name + ");";
3629*890232f2SAndroid Build Coastguard Worker         }
3630*890232f2SAndroid Build Coastguard Worker         if (field.padding) {
3631*890232f2SAndroid Build Coastguard Worker           std::string padding;
3632*890232f2SAndroid Build Coastguard Worker           GenPadding(field, &padding, &padding_id, PaddingNoop);
3633*890232f2SAndroid Build Coastguard Worker           code_ += padding;
3634*890232f2SAndroid Build Coastguard Worker         }
3635*890232f2SAndroid Build Coastguard Worker       }
3636*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
3637*890232f2SAndroid Build Coastguard Worker     }
3638*890232f2SAndroid Build Coastguard Worker   }
3639*890232f2SAndroid Build Coastguard Worker 
GenArrayAccessor(const Type & type,bool mutable_accessor)3640*890232f2SAndroid Build Coastguard Worker   void GenArrayAccessor(const Type &type, bool mutable_accessor) {
3641*890232f2SAndroid Build Coastguard Worker     FLATBUFFERS_ASSERT(IsArray(type));
3642*890232f2SAndroid Build Coastguard Worker     const auto is_enum = IsEnum(type.VectorType());
3643*890232f2SAndroid Build Coastguard Worker     // The Array<bool,N> is a tricky case, like std::vector<bool>.
3644*890232f2SAndroid Build Coastguard Worker     // It requires a specialization of Array class.
3645*890232f2SAndroid Build Coastguard Worker     // Generate Array<uint8_t> for Array<bool>.
3646*890232f2SAndroid Build Coastguard Worker     const auto face_type = GenTypeGet(type, " ", "", "", is_enum);
3647*890232f2SAndroid Build Coastguard Worker     std::string ret_type = "flatbuffers::Array<" + face_type + ", " +
3648*890232f2SAndroid Build Coastguard Worker                            NumToString(type.fixed_length) + ">";
3649*890232f2SAndroid Build Coastguard Worker     if (mutable_accessor)
3650*890232f2SAndroid Build Coastguard Worker       code_ += "  " + ret_type + " *mutable_{{FIELD_NAME}}() {";
3651*890232f2SAndroid Build Coastguard Worker     else
3652*890232f2SAndroid Build Coastguard Worker       code_ += "  const " + ret_type + " *{{FIELD_NAME}}() const {";
3653*890232f2SAndroid Build Coastguard Worker 
3654*890232f2SAndroid Build Coastguard Worker     std::string get_array =
3655*890232f2SAndroid Build Coastguard Worker         is_enum ? "CastToArrayOfEnum<" + face_type + ">" : "CastToArray";
3656*890232f2SAndroid Build Coastguard Worker     code_ += "    return &flatbuffers::" + get_array + "({{FIELD_VALUE}});";
3657*890232f2SAndroid Build Coastguard Worker     code_ += "  }";
3658*890232f2SAndroid Build Coastguard Worker   }
3659*890232f2SAndroid Build Coastguard Worker 
3660*890232f2SAndroid Build Coastguard Worker   // Generate an accessor struct with constructor for a flatbuffers struct.
GenStruct(const StructDef & struct_def)3661*890232f2SAndroid Build Coastguard Worker   void GenStruct(const StructDef &struct_def) {
3662*890232f2SAndroid Build Coastguard Worker     // Generate an accessor struct, with private variables of the form:
3663*890232f2SAndroid Build Coastguard Worker     // type name_;
3664*890232f2SAndroid Build Coastguard Worker     // Generates manual padding and alignment.
3665*890232f2SAndroid Build Coastguard Worker     // Variables are private because they contain little endian data on all
3666*890232f2SAndroid Build Coastguard Worker     // platforms.
3667*890232f2SAndroid Build Coastguard Worker     GenComment(struct_def.doc_comment);
3668*890232f2SAndroid Build Coastguard Worker     code_.SetValue("ALIGN", NumToString(struct_def.minalign));
3669*890232f2SAndroid Build Coastguard Worker     code_.SetValue("STRUCT_NAME", Name(struct_def));
3670*890232f2SAndroid Build Coastguard Worker 
3671*890232f2SAndroid Build Coastguard Worker     code_ +=
3672*890232f2SAndroid Build Coastguard Worker         "FLATBUFFERS_MANUALLY_ALIGNED_STRUCT({{ALIGN}}) "
3673*890232f2SAndroid Build Coastguard Worker         "{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {";
3674*890232f2SAndroid Build Coastguard Worker     code_ += " private:";
3675*890232f2SAndroid Build Coastguard Worker 
3676*890232f2SAndroid Build Coastguard Worker     int padding_id = 0;
3677*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
3678*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
3679*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
3680*890232f2SAndroid Build Coastguard Worker       const auto &field_type = field.value.type;
3681*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", GenTypeGet(field_type, " ", "", " ", false));
3682*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
3683*890232f2SAndroid Build Coastguard Worker       code_.SetValue("ARRAY",
3684*890232f2SAndroid Build Coastguard Worker                      IsArray(field_type)
3685*890232f2SAndroid Build Coastguard Worker                          ? "[" + NumToString(field_type.fixed_length) + "]"
3686*890232f2SAndroid Build Coastguard Worker                          : "");
3687*890232f2SAndroid Build Coastguard Worker       code_ += ("  {{FIELD_TYPE}}{{FIELD_NAME}}_{{ARRAY}};");
3688*890232f2SAndroid Build Coastguard Worker 
3689*890232f2SAndroid Build Coastguard Worker       if (field.padding) {
3690*890232f2SAndroid Build Coastguard Worker         std::string padding;
3691*890232f2SAndroid Build Coastguard Worker         GenPadding(field, &padding, &padding_id, PaddingDefinition);
3692*890232f2SAndroid Build Coastguard Worker         code_ += padding;
3693*890232f2SAndroid Build Coastguard Worker       }
3694*890232f2SAndroid Build Coastguard Worker     }
3695*890232f2SAndroid Build Coastguard Worker 
3696*890232f2SAndroid Build Coastguard Worker     // Generate GetFullyQualifiedName
3697*890232f2SAndroid Build Coastguard Worker     code_ += "";
3698*890232f2SAndroid Build Coastguard Worker     code_ += " public:";
3699*890232f2SAndroid Build Coastguard Worker 
3700*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += "  struct Traits;"; }
3701*890232f2SAndroid Build Coastguard Worker 
3702*890232f2SAndroid Build Coastguard Worker     // Make TypeTable accessible via the generated struct.
3703*890232f2SAndroid Build Coastguard Worker     if (opts_.mini_reflect != IDLOptions::kNone) {
3704*890232f2SAndroid Build Coastguard Worker       code_ +=
3705*890232f2SAndroid Build Coastguard Worker           "  static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
3706*890232f2SAndroid Build Coastguard Worker       code_ += "    return {{STRUCT_NAME}}TypeTable();";
3707*890232f2SAndroid Build Coastguard Worker       code_ += "  }";
3708*890232f2SAndroid Build Coastguard Worker     }
3709*890232f2SAndroid Build Coastguard Worker 
3710*890232f2SAndroid Build Coastguard Worker     GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
3711*890232f2SAndroid Build Coastguard Worker 
3712*890232f2SAndroid Build Coastguard Worker     // Generate a default constructor.
3713*890232f2SAndroid Build Coastguard Worker     GenStructDefaultConstructor(struct_def);
3714*890232f2SAndroid Build Coastguard Worker 
3715*890232f2SAndroid Build Coastguard Worker     // Generate a constructor that takes all fields as arguments,
3716*890232f2SAndroid Build Coastguard Worker     // excluding arrays.
3717*890232f2SAndroid Build Coastguard Worker     GenStructConstructor(struct_def, kArrayArgModeNone);
3718*890232f2SAndroid Build Coastguard Worker 
3719*890232f2SAndroid Build Coastguard Worker     auto arrays_num = std::count_if(struct_def.fields.vec.begin(),
3720*890232f2SAndroid Build Coastguard Worker                                     struct_def.fields.vec.end(),
3721*890232f2SAndroid Build Coastguard Worker                                     [](const flatbuffers::FieldDef *fd) {
3722*890232f2SAndroid Build Coastguard Worker                                       return IsArray(fd->value.type);
3723*890232f2SAndroid Build Coastguard Worker                                     });
3724*890232f2SAndroid Build Coastguard Worker     if (arrays_num > 0) {
3725*890232f2SAndroid Build Coastguard Worker       GenStructConstructor(struct_def, kArrayArgModeSpanStatic);
3726*890232f2SAndroid Build Coastguard Worker     }
3727*890232f2SAndroid Build Coastguard Worker 
3728*890232f2SAndroid Build Coastguard Worker     // Generate accessor methods of the form:
3729*890232f2SAndroid Build Coastguard Worker     // type name() const { return flatbuffers::EndianScalar(name_); }
3730*890232f2SAndroid Build Coastguard Worker     for (auto it = struct_def.fields.vec.begin();
3731*890232f2SAndroid Build Coastguard Worker          it != struct_def.fields.vec.end(); ++it) {
3732*890232f2SAndroid Build Coastguard Worker       const auto &field = **it;
3733*890232f2SAndroid Build Coastguard Worker       const auto &type = field.value.type;
3734*890232f2SAndroid Build Coastguard Worker       const auto is_scalar = IsScalar(type.base_type);
3735*890232f2SAndroid Build Coastguard Worker       const auto is_array = IsArray(type);
3736*890232f2SAndroid Build Coastguard Worker 
3737*890232f2SAndroid Build Coastguard Worker       const auto field_type = GenTypeGet(type, " ", is_array ? "" : "const ",
3738*890232f2SAndroid Build Coastguard Worker                                          is_array ? "" : " &", true);
3739*890232f2SAndroid Build Coastguard Worker       auto member = Name(field) + "_";
3740*890232f2SAndroid Build Coastguard Worker       auto value =
3741*890232f2SAndroid Build Coastguard Worker           is_scalar ? "flatbuffers::EndianScalar(" + member + ")" : member;
3742*890232f2SAndroid Build Coastguard Worker 
3743*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_NAME", Name(field));
3744*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_TYPE", field_type);
3745*890232f2SAndroid Build Coastguard Worker       code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
3746*890232f2SAndroid Build Coastguard Worker 
3747*890232f2SAndroid Build Coastguard Worker       GenComment(field.doc_comment, "  ");
3748*890232f2SAndroid Build Coastguard Worker 
3749*890232f2SAndroid Build Coastguard Worker       // Generate a const accessor function.
3750*890232f2SAndroid Build Coastguard Worker       if (is_array) {
3751*890232f2SAndroid Build Coastguard Worker         GenArrayAccessor(type, false);
3752*890232f2SAndroid Build Coastguard Worker       } else {
3753*890232f2SAndroid Build Coastguard Worker         code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
3754*890232f2SAndroid Build Coastguard Worker         code_ += "    return {{FIELD_VALUE}};";
3755*890232f2SAndroid Build Coastguard Worker         code_ += "  }";
3756*890232f2SAndroid Build Coastguard Worker       }
3757*890232f2SAndroid Build Coastguard Worker 
3758*890232f2SAndroid Build Coastguard Worker       // Generate a mutable accessor function.
3759*890232f2SAndroid Build Coastguard Worker       if (opts_.mutable_buffer) {
3760*890232f2SAndroid Build Coastguard Worker         auto mut_field_type =
3761*890232f2SAndroid Build Coastguard Worker             GenTypeGet(type, " ", "", is_array ? "" : " &", true);
3762*890232f2SAndroid Build Coastguard Worker         code_.SetValue("FIELD_TYPE", mut_field_type);
3763*890232f2SAndroid Build Coastguard Worker         if (is_scalar) {
3764*890232f2SAndroid Build Coastguard Worker           code_.SetValue("ARG", GenTypeBasic(type, true));
3765*890232f2SAndroid Build Coastguard Worker           code_.SetValue("FIELD_VALUE",
3766*890232f2SAndroid Build Coastguard Worker                          GenUnderlyingCast(field, false, "_" + Name(field)));
3767*890232f2SAndroid Build Coastguard Worker 
3768*890232f2SAndroid Build Coastguard Worker           code_ += "  void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {";
3769*890232f2SAndroid Build Coastguard Worker           code_ +=
3770*890232f2SAndroid Build Coastguard Worker               "    flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
3771*890232f2SAndroid Build Coastguard Worker               "{{FIELD_VALUE}});";
3772*890232f2SAndroid Build Coastguard Worker           code_ += "  }";
3773*890232f2SAndroid Build Coastguard Worker         } else if (is_array) {
3774*890232f2SAndroid Build Coastguard Worker           GenArrayAccessor(type, true);
3775*890232f2SAndroid Build Coastguard Worker         } else {
3776*890232f2SAndroid Build Coastguard Worker           code_ += "  {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
3777*890232f2SAndroid Build Coastguard Worker           code_ += "    return {{FIELD_VALUE}};";
3778*890232f2SAndroid Build Coastguard Worker           code_ += "  }";
3779*890232f2SAndroid Build Coastguard Worker         }
3780*890232f2SAndroid Build Coastguard Worker       }
3781*890232f2SAndroid Build Coastguard Worker 
3782*890232f2SAndroid Build Coastguard Worker       // Generate a comparison function for this field if it is a key.
3783*890232f2SAndroid Build Coastguard Worker       if (field.key) { GenKeyFieldMethods(field); }
3784*890232f2SAndroid Build Coastguard Worker     }
3785*890232f2SAndroid Build Coastguard Worker     code_.SetValue("NATIVE_NAME", Name(struct_def));
3786*890232f2SAndroid Build Coastguard Worker     GenOperatorNewDelete(struct_def);
3787*890232f2SAndroid Build Coastguard Worker 
3788*890232f2SAndroid Build Coastguard Worker     if (opts_.cpp_static_reflection) { GenIndexBasedFieldGetter(struct_def); }
3789*890232f2SAndroid Build Coastguard Worker 
3790*890232f2SAndroid Build Coastguard Worker     code_ += "};";
3791*890232f2SAndroid Build Coastguard Worker 
3792*890232f2SAndroid Build Coastguard Worker     code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
3793*890232f2SAndroid Build Coastguard Worker     code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
3794*890232f2SAndroid Build Coastguard Worker     if (opts_.gen_compare) GenCompareOperator(struct_def, "()");
3795*890232f2SAndroid Build Coastguard Worker     code_ += "";
3796*890232f2SAndroid Build Coastguard Worker 
3797*890232f2SAndroid Build Coastguard Worker     // Definition for type traits for this table type. This allows querying var-
3798*890232f2SAndroid Build Coastguard Worker     // ious compile-time traits of the table.
3799*890232f2SAndroid Build Coastguard Worker     if (opts_.g_cpp_std >= cpp::CPP_STD_17) { GenTraitsStruct(struct_def); }
3800*890232f2SAndroid Build Coastguard Worker   }
3801*890232f2SAndroid Build Coastguard Worker 
3802*890232f2SAndroid Build Coastguard Worker   // Set up the correct namespace. Only open a namespace if the existing one is
3803*890232f2SAndroid Build Coastguard Worker   // different (closing/opening only what is necessary).
3804*890232f2SAndroid Build Coastguard Worker   //
3805*890232f2SAndroid Build Coastguard Worker   // The file must start and end with an empty (or null) namespace so that
3806*890232f2SAndroid Build Coastguard Worker   // namespaces are properly opened and closed.
SetNameSpace(const Namespace * ns)3807*890232f2SAndroid Build Coastguard Worker   void SetNameSpace(const Namespace *ns) {
3808*890232f2SAndroid Build Coastguard Worker     if (cur_name_space_ == ns) { return; }
3809*890232f2SAndroid Build Coastguard Worker 
3810*890232f2SAndroid Build Coastguard Worker     // Compute the size of the longest common namespace prefix.
3811*890232f2SAndroid Build Coastguard Worker     // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
3812*890232f2SAndroid Build Coastguard Worker     // the common prefix is A::B:: and we have old_size = 4, new_size = 5
3813*890232f2SAndroid Build Coastguard Worker     // and common_prefix_size = 2
3814*890232f2SAndroid Build Coastguard Worker     size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
3815*890232f2SAndroid Build Coastguard Worker     size_t new_size = ns ? ns->components.size() : 0;
3816*890232f2SAndroid Build Coastguard Worker 
3817*890232f2SAndroid Build Coastguard Worker     size_t common_prefix_size = 0;
3818*890232f2SAndroid Build Coastguard Worker     while (common_prefix_size < old_size && common_prefix_size < new_size &&
3819*890232f2SAndroid Build Coastguard Worker            ns->components[common_prefix_size] ==
3820*890232f2SAndroid Build Coastguard Worker                cur_name_space_->components[common_prefix_size]) {
3821*890232f2SAndroid Build Coastguard Worker       common_prefix_size++;
3822*890232f2SAndroid Build Coastguard Worker     }
3823*890232f2SAndroid Build Coastguard Worker 
3824*890232f2SAndroid Build Coastguard Worker     // Close cur_name_space in reverse order to reach the common prefix.
3825*890232f2SAndroid Build Coastguard Worker     // In the previous example, D then C are closed.
3826*890232f2SAndroid Build Coastguard Worker     for (size_t j = old_size; j > common_prefix_size; --j) {
3827*890232f2SAndroid Build Coastguard Worker       code_ += "}  // namespace " + cur_name_space_->components[j - 1];
3828*890232f2SAndroid Build Coastguard Worker     }
3829*890232f2SAndroid Build Coastguard Worker     if (old_size != common_prefix_size) { code_ += ""; }
3830*890232f2SAndroid Build Coastguard Worker 
3831*890232f2SAndroid Build Coastguard Worker     // open namespace parts to reach the ns namespace
3832*890232f2SAndroid Build Coastguard Worker     // in the previous example, E, then F, then G are opened
3833*890232f2SAndroid Build Coastguard Worker     for (auto j = common_prefix_size; j != new_size; ++j) {
3834*890232f2SAndroid Build Coastguard Worker       code_ += "namespace " + ns->components[j] + " {";
3835*890232f2SAndroid Build Coastguard Worker     }
3836*890232f2SAndroid Build Coastguard Worker     if (new_size != common_prefix_size) { code_ += ""; }
3837*890232f2SAndroid Build Coastguard Worker 
3838*890232f2SAndroid Build Coastguard Worker     cur_name_space_ = ns;
3839*890232f2SAndroid Build Coastguard Worker   }
3840*890232f2SAndroid Build Coastguard Worker };
3841*890232f2SAndroid Build Coastguard Worker 
3842*890232f2SAndroid Build Coastguard Worker }  // namespace cpp
3843*890232f2SAndroid Build Coastguard Worker 
GenerateCPP(const Parser & parser,const std::string & path,const std::string & file_name)3844*890232f2SAndroid Build Coastguard Worker bool GenerateCPP(const Parser &parser, const std::string &path,
3845*890232f2SAndroid Build Coastguard Worker                  const std::string &file_name) {
3846*890232f2SAndroid Build Coastguard Worker   cpp::IDLOptionsCpp opts(parser.opts);
3847*890232f2SAndroid Build Coastguard Worker   // The '--cpp_std' argument could be extended (like ASAN):
3848*890232f2SAndroid Build Coastguard Worker   // Example: "flatc --cpp_std c++17:option1:option2".
3849*890232f2SAndroid Build Coastguard Worker   auto cpp_std = !opts.cpp_std.empty() ? opts.cpp_std : "C++11";
3850*890232f2SAndroid Build Coastguard Worker   std::transform(cpp_std.begin(), cpp_std.end(), cpp_std.begin(), CharToUpper);
3851*890232f2SAndroid Build Coastguard Worker   if (cpp_std == "C++0X") {
3852*890232f2SAndroid Build Coastguard Worker     opts.g_cpp_std = cpp::CPP_STD_X0;
3853*890232f2SAndroid Build Coastguard Worker     opts.g_only_fixed_enums = false;
3854*890232f2SAndroid Build Coastguard Worker   } else if (cpp_std == "C++11") {
3855*890232f2SAndroid Build Coastguard Worker     // Use the standard C++11 code generator.
3856*890232f2SAndroid Build Coastguard Worker     opts.g_cpp_std = cpp::CPP_STD_11;
3857*890232f2SAndroid Build Coastguard Worker     opts.g_only_fixed_enums = true;
3858*890232f2SAndroid Build Coastguard Worker   } else if (cpp_std == "C++17") {
3859*890232f2SAndroid Build Coastguard Worker     opts.g_cpp_std = cpp::CPP_STD_17;
3860*890232f2SAndroid Build Coastguard Worker     // With c++17 generate strong enums only.
3861*890232f2SAndroid Build Coastguard Worker     opts.scoped_enums = true;
3862*890232f2SAndroid Build Coastguard Worker     // By default, prefixed_enums==true, reset it.
3863*890232f2SAndroid Build Coastguard Worker     opts.prefixed_enums = false;
3864*890232f2SAndroid Build Coastguard Worker   } else {
3865*890232f2SAndroid Build Coastguard Worker     LogCompilerError("Unknown value of the '--cpp-std' switch: " +
3866*890232f2SAndroid Build Coastguard Worker                      opts.cpp_std);
3867*890232f2SAndroid Build Coastguard Worker     return false;
3868*890232f2SAndroid Build Coastguard Worker   }
3869*890232f2SAndroid Build Coastguard Worker   // The opts.scoped_enums has priority.
3870*890232f2SAndroid Build Coastguard Worker   opts.g_only_fixed_enums |= opts.scoped_enums;
3871*890232f2SAndroid Build Coastguard Worker 
3872*890232f2SAndroid Build Coastguard Worker   if (opts.cpp_static_reflection && opts.g_cpp_std < cpp::CPP_STD_17) {
3873*890232f2SAndroid Build Coastguard Worker     LogCompilerError(
3874*890232f2SAndroid Build Coastguard Worker         "--cpp-static-reflection requires using --cpp-std at \"C++17\" or "
3875*890232f2SAndroid Build Coastguard Worker         "higher.");
3876*890232f2SAndroid Build Coastguard Worker     return false;
3877*890232f2SAndroid Build Coastguard Worker   }
3878*890232f2SAndroid Build Coastguard Worker 
3879*890232f2SAndroid Build Coastguard Worker   cpp::CppGenerator generator(parser, path, file_name, opts);
3880*890232f2SAndroid Build Coastguard Worker   return generator.generate();
3881*890232f2SAndroid Build Coastguard Worker }
3882*890232f2SAndroid Build Coastguard Worker 
CPPMakeRule(const Parser & parser,const std::string & path,const std::string & file_name)3883*890232f2SAndroid Build Coastguard Worker std::string CPPMakeRule(const Parser &parser, const std::string &path,
3884*890232f2SAndroid Build Coastguard Worker                         const std::string &file_name) {
3885*890232f2SAndroid Build Coastguard Worker   const auto filebase =
3886*890232f2SAndroid Build Coastguard Worker       flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
3887*890232f2SAndroid Build Coastguard Worker   cpp::CppGenerator geneartor(parser, path, file_name, parser.opts);
3888*890232f2SAndroid Build Coastguard Worker   const auto included_files = parser.GetIncludedFilesRecursive(file_name);
3889*890232f2SAndroid Build Coastguard Worker   std::string make_rule =
3890*890232f2SAndroid Build Coastguard Worker       geneartor.GeneratedFileName(path, filebase, parser.opts) + ": ";
3891*890232f2SAndroid Build Coastguard Worker   for (auto it = included_files.begin(); it != included_files.end(); ++it) {
3892*890232f2SAndroid Build Coastguard Worker     make_rule += " " + *it;
3893*890232f2SAndroid Build Coastguard Worker   }
3894*890232f2SAndroid Build Coastguard Worker   return make_rule;
3895*890232f2SAndroid Build Coastguard Worker }
3896*890232f2SAndroid Build Coastguard Worker 
3897*890232f2SAndroid Build Coastguard Worker }  // namespace flatbuffers
3898