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