idl_gen_cpp.cpp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480
  1. /*
  2. * Copyright 2014 Google Inc. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. // independent from idl_parser, since this code is not needed for most clients
  17. #include "flatbuffers/flatbuffers.h"
  18. #include "flatbuffers/idl.h"
  19. #include "flatbuffers/util.h"
  20. #include "flatbuffers/code_generators.h"
  21. namespace flatbuffers {
  22. struct IsAlnum {
  23. bool operator()(char c) { return !isalnum(c); }
  24. };
  25. static std::string GeneratedFileName(const std::string &path,
  26. const std::string &file_name) {
  27. return path + file_name + "_generated.h";
  28. }
  29. namespace cpp {
  30. class CppGenerator : public BaseGenerator {
  31. public:
  32. CppGenerator(const Parser &parser, const std::string &path,
  33. const std::string &file_name)
  34. : BaseGenerator(parser, path, file_name, "", "::"),
  35. cur_name_space_(nullptr){};
  36. // Iterate through all definitions we haven't generate code for (enums,
  37. // structs,
  38. // and tables) and output them to a single file.
  39. bool generate() {
  40. if (IsEverythingGenerated()) return true;
  41. std::string code;
  42. code = code + "// " + FlatBuffersGeneratedWarning();
  43. // Generate include guard.
  44. std::string include_guard_ident = file_name_;
  45. // Remove any non-alpha-numeric characters that may appear in a filename.
  46. include_guard_ident.erase(
  47. std::remove_if(include_guard_ident.begin(), include_guard_ident.end(),
  48. IsAlnum()),
  49. include_guard_ident.end());
  50. std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident;
  51. include_guard += "_";
  52. // For further uniqueness, also add the namespace.
  53. auto name_space = parser_.namespaces_.back();
  54. for (auto it = name_space->components.begin();
  55. it != name_space->components.end(); ++it) {
  56. include_guard += *it + "_";
  57. }
  58. include_guard += "H_";
  59. std::transform(include_guard.begin(), include_guard.end(),
  60. include_guard.begin(), ::toupper);
  61. code += "#ifndef " + include_guard + "\n";
  62. code += "#define " + include_guard + "\n\n";
  63. code += "#include \"flatbuffers/flatbuffers.h\"\n\n";
  64. if (parser_.opts.include_dependence_headers) {
  65. int num_includes = 0;
  66. for (auto it = parser_.included_files_.begin();
  67. it != parser_.included_files_.end(); ++it) {
  68. auto basename =
  69. flatbuffers::StripPath(flatbuffers::StripExtension(it->first));
  70. if (basename != file_name_) {
  71. code += "#include \"" + basename + "_generated.h\"\n";
  72. num_includes++;
  73. }
  74. }
  75. if (num_includes) code += "\n";
  76. }
  77. assert(!cur_name_space_);
  78. // Generate forward declarations for all structs/tables, since they may
  79. // have circular references.
  80. for (auto it = parser_.structs_.vec.begin();
  81. it != parser_.structs_.vec.end(); ++it) {
  82. auto &struct_def = **it;
  83. if (!struct_def.generated) {
  84. SetNameSpace(struct_def.defined_namespace, &code);
  85. code += "struct " + struct_def.name + ";\n";
  86. if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
  87. code += "struct " + NativeName(struct_def.name) + ";\n";
  88. }
  89. code += "\n";
  90. }
  91. }
  92. // Generate code for all the enum declarations.
  93. for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
  94. ++it) {
  95. auto &enum_def = **it;
  96. if (!enum_def.generated) {
  97. SetNameSpace((**it).defined_namespace, &code);
  98. GenEnum(**it, &code);
  99. }
  100. }
  101. // Generate code for all structs, then all tables.
  102. for (auto it = parser_.structs_.vec.begin();
  103. it != parser_.structs_.vec.end(); ++it) {
  104. auto &struct_def = **it;
  105. if (struct_def.fixed && !struct_def.generated) {
  106. SetNameSpace(struct_def.defined_namespace, &code);
  107. GenStruct(struct_def, &code);
  108. }
  109. }
  110. for (auto it = parser_.structs_.vec.begin();
  111. it != parser_.structs_.vec.end(); ++it) {
  112. auto &struct_def = **it;
  113. if (!struct_def.fixed && !struct_def.generated) {
  114. SetNameSpace(struct_def.defined_namespace, &code);
  115. GenTable(struct_def, &code);
  116. }
  117. }
  118. for (auto it = parser_.structs_.vec.begin();
  119. it != parser_.structs_.vec.end(); ++it) {
  120. auto &struct_def = **it;
  121. if (!struct_def.fixed && !struct_def.generated) {
  122. SetNameSpace(struct_def.defined_namespace, &code);
  123. GenTablePost(struct_def, &code);
  124. }
  125. }
  126. // Generate code for union verifiers.
  127. for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
  128. ++it) {
  129. auto &enum_def = **it;
  130. if (enum_def.is_union && !enum_def.generated) {
  131. SetNameSpace(enum_def.defined_namespace, &code);
  132. GenUnionPost(enum_def, &code);
  133. }
  134. }
  135. // Generate convenient global helper functions:
  136. if (parser_.root_struct_def_) {
  137. SetNameSpace((*parser_.root_struct_def_).defined_namespace, &code);
  138. auto &name = parser_.root_struct_def_->name;
  139. std::string qualified_name =
  140. parser_.namespaces_.back()->GetFullyQualifiedName(name);
  141. std::string cpp_qualified_name = TranslateNameSpace(qualified_name);
  142. // The root datatype accessor:
  143. code += "inline const " + cpp_qualified_name + " *Get";
  144. code += name;
  145. code += "(const void *buf) {\n return flatbuffers::GetRoot<";
  146. code += cpp_qualified_name + ">(buf);\n}\n\n";
  147. if (parser_.opts.mutable_buffer) {
  148. code += "inline " + name + " *GetMutable";
  149. code += name;
  150. code += "(void *buf) {\n return flatbuffers::GetMutableRoot<";
  151. code += name + ">(buf);\n}\n\n";
  152. }
  153. if (parser_.file_identifier_.length()) {
  154. // Return the identifier
  155. code += "inline const char *" + name;
  156. code += "Identifier() {\n return \"" + parser_.file_identifier_;
  157. code += "\";\n}\n\n";
  158. // Check if a buffer has the identifier.
  159. code += "inline bool " + name;
  160. code += "BufferHasIdentifier(const void *buf) {\n return flatbuffers::";
  161. code += "BufferHasIdentifier(buf, ";
  162. code += name + "Identifier());\n}\n\n";
  163. }
  164. // The root verifier:
  165. code += "inline bool Verify";
  166. code += name;
  167. code +=
  168. "Buffer(flatbuffers::Verifier &verifier) {\n"
  169. " return verifier.VerifyBuffer<";
  170. code += cpp_qualified_name + ">(";
  171. if (parser_.file_identifier_.length())
  172. code += name + "Identifier()";
  173. else
  174. code += "nullptr";
  175. code += ");\n}\n\n";
  176. if (parser_.file_extension_.length()) {
  177. // Return the extension
  178. code += "inline const char *" + name;
  179. code += "Extension() { return \"" + parser_.file_extension_;
  180. code += "\"; }\n\n";
  181. }
  182. // Finish a buffer with a given root object:
  183. code += "inline void Finish" + name;
  184. code +=
  185. "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<";
  186. code += cpp_qualified_name + "> root) {\n fbb.Finish(root";
  187. if (parser_.file_identifier_.length())
  188. code += ", " + name + "Identifier()";
  189. code += ");\n}\n\n";
  190. if (parser_.opts.generate_object_based_api) {
  191. // A convenient root unpack function.
  192. auto native_name =
  193. NativeName(WrapInNameSpace(*parser_.root_struct_def_));
  194. code += "inline " + GenTypeNativePtr(native_name, nullptr, false);
  195. code += " UnPack" + name;
  196. code += "(const void *buf, const flatbuffers::resolver_function_t *";
  197. code += "resolver = nullptr) {\n return ";
  198. code += GenTypeNativePtr(native_name, nullptr, true);
  199. code += "(Get" + name + "(buf)->UnPack(resolver));\n}\n\n";
  200. }
  201. }
  202. assert(cur_name_space_);
  203. SetNameSpace(nullptr, &code);
  204. // Close the include guard.
  205. code += "#endif // " + include_guard + "\n";
  206. return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false);
  207. }
  208. private:
  209. // This tracks the current namespace so we can insert namespace declarations.
  210. const Namespace *cur_name_space_;
  211. const Namespace *CurrentNameSpace() { return cur_name_space_; }
  212. // Translates a qualified name in flatbuffer text format to the same name in
  213. // the equivalent C++ namespace.
  214. static std::string TranslateNameSpace(const std::string &qualified_name) {
  215. std::string cpp_qualified_name = qualified_name;
  216. size_t start_pos = 0;
  217. while ((start_pos = cpp_qualified_name.find(".", start_pos)) !=
  218. std::string::npos) {
  219. cpp_qualified_name.replace(start_pos, 1, "::");
  220. }
  221. return cpp_qualified_name;
  222. }
  223. // Return a C++ type from the table in idl.h
  224. std::string GenTypeBasic(const Type &type, bool user_facing_type) {
  225. static const char *ctypename[] = {
  226. #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
  227. #CTYPE,
  228. FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
  229. #undef FLATBUFFERS_TD
  230. };
  231. if (user_facing_type) {
  232. if (type.enum_def) return WrapInNameSpace(*type.enum_def);
  233. if (type.base_type == BASE_TYPE_BOOL) return "bool";
  234. }
  235. return ctypename[type.base_type];
  236. }
  237. // Return a C++ pointer type, specialized to the actual struct/table types,
  238. // and vector element types.
  239. std::string GenTypePointer(const Type &type) {
  240. switch (type.base_type) {
  241. case BASE_TYPE_STRING:
  242. return "flatbuffers::String";
  243. case BASE_TYPE_VECTOR:
  244. return "flatbuffers::Vector<" +
  245. GenTypeWire(type.VectorType(), "", false) + ">";
  246. case BASE_TYPE_STRUCT:
  247. return WrapInNameSpace(*type.struct_def);
  248. case BASE_TYPE_UNION:
  249. // fall through
  250. default:
  251. return "void";
  252. }
  253. }
  254. // Return a C++ type for any type (scalar/pointer) specifically for
  255. // building a flatbuffer.
  256. std::string GenTypeWire(const Type &type, const char *postfix,
  257. bool user_facing_type) {
  258. return IsScalar(type.base_type)
  259. ? GenTypeBasic(type, user_facing_type) + postfix
  260. : IsStruct(type) ? "const " + GenTypePointer(type) + " *"
  261. : "flatbuffers::Offset<" +
  262. GenTypePointer(type) + ">" + postfix;
  263. }
  264. // Return a C++ type for any type (scalar/pointer) that reflects its
  265. // serialized size.
  266. std::string GenTypeSize(const Type &type) {
  267. return IsScalar(type.base_type) ? GenTypeBasic(type, false)
  268. : IsStruct(type) ? GenTypePointer(type)
  269. : "flatbuffers::uoffset_t";
  270. }
  271. // TODO(wvo): make this configurable.
  272. std::string NativeName(const std::string &name) { return name + "T"; }
  273. const std::string &PtrType(const FieldDef *field) {
  274. auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
  275. return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type;
  276. }
  277. std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
  278. bool is_constructor) {
  279. auto &ptr_type = PtrType(field);
  280. if (ptr_type == "naked") return is_constructor ? "" : type + " *";
  281. return ptr_type + "<" + type + ">";
  282. }
  283. std::string GenPtrGet(const FieldDef &field) {
  284. auto &ptr_type = PtrType(&field);
  285. return ptr_type == "naked" ? "" : ".get()";
  286. }
  287. std::string GenTypeNative(const Type &type, bool invector,
  288. const FieldDef &field) {
  289. switch (type.base_type) {
  290. case BASE_TYPE_STRING:
  291. return "std::string";
  292. case BASE_TYPE_VECTOR:
  293. return "std::vector<" + GenTypeNative(type.VectorType(), true, field) +
  294. ">";
  295. case BASE_TYPE_STRUCT:
  296. if (IsStruct(type)) {
  297. if (invector || field.native_inline) {
  298. return WrapInNameSpace(*type.struct_def);
  299. } else {
  300. return GenTypeNativePtr(WrapInNameSpace(*type.struct_def), &field,
  301. false);
  302. }
  303. } else {
  304. return GenTypeNativePtr(NativeName(WrapInNameSpace(*type.struct_def)),
  305. &field, false);
  306. }
  307. case BASE_TYPE_UNION:
  308. return type.enum_def->name + "Union";
  309. default:
  310. return GenTypeBasic(type, true);
  311. }
  312. }
  313. // Return a C++ type for any type (scalar/pointer) specifically for
  314. // using a flatbuffer.
  315. std::string GenTypeGet(const Type &type, const char *afterbasic,
  316. const char *beforeptr, const char *afterptr,
  317. bool user_facing_type) {
  318. return IsScalar(type.base_type)
  319. ? GenTypeBasic(type, user_facing_type) + afterbasic
  320. : beforeptr + GenTypePointer(type) + afterptr;
  321. }
  322. static std::string GenEnumDecl(const EnumDef &enum_def,
  323. const IDLOptions &opts) {
  324. return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name;
  325. }
  326. static std::string GenEnumValDecl(const EnumDef &enum_def,
  327. const std::string &enum_val,
  328. const IDLOptions &opts) {
  329. return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val;
  330. }
  331. static std::string GetEnumValUse(const EnumDef &enum_def,
  332. const EnumVal &enum_val,
  333. const IDLOptions &opts) {
  334. if (opts.scoped_enums) {
  335. return enum_def.name + "::" + enum_val.name;
  336. } else if (opts.prefixed_enums) {
  337. return enum_def.name + "_" + enum_val.name;
  338. } else {
  339. return enum_val.name;
  340. }
  341. }
  342. std::string UnionVerifySignature(EnumDef &enum_def) {
  343. return "inline bool Verify" + enum_def.name +
  344. "(flatbuffers::Verifier &verifier, const void *union_obj, " +
  345. enum_def.name + " type)";
  346. }
  347. std::string UnionUnPackSignature(EnumDef &enum_def, bool inclass) {
  348. return (inclass ? "static " : "") +
  349. std::string("flatbuffers::NativeTable *") +
  350. (inclass ? "" : enum_def.name + "Union::") +
  351. "UnPack(const void *union_obj, " + enum_def.name +
  352. " type, const flatbuffers::resolver_function_t *resolver)";
  353. }
  354. std::string UnionPackSignature(EnumDef &enum_def, bool inclass) {
  355. return "flatbuffers::Offset<void> " +
  356. (inclass ? "" : enum_def.name + "Union::") +
  357. "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
  358. "const flatbuffers::rehasher_function_t *rehasher" +
  359. (inclass ? " = nullptr" : "") + ") const";
  360. }
  361. std::string TableCreateSignature(StructDef &struct_def, bool predecl) {
  362. return "inline flatbuffers::Offset<" + struct_def.name + "> Create" +
  363. struct_def.name +
  364. "(flatbuffers::FlatBufferBuilder &_fbb, const " +
  365. NativeName(struct_def.name) +
  366. " *_o, const flatbuffers::rehasher_function_t *rehasher" +
  367. (predecl ? " = nullptr" : "") + ")";
  368. }
  369. std::string TablePackSignature(StructDef &struct_def, bool inclass) {
  370. return std::string(inclass ? "static " : "") +
  371. "flatbuffers::Offset<" + struct_def.name + "> " +
  372. (inclass ? "" : struct_def.name + "::") +
  373. "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
  374. "const " + NativeName(struct_def.name) + "* _o, " +
  375. "const flatbuffers::rehasher_function_t *_rehasher" +
  376. (inclass ? " = nullptr" : "") + ")";
  377. }
  378. std::string TableUnPackSignature(StructDef &struct_def, bool inclass) {
  379. return NativeName(struct_def.name) + " *" +
  380. (inclass ? "" : struct_def.name + "::") +
  381. "UnPack(const flatbuffers::resolver_function_t *resolver" +
  382. (inclass ? " = nullptr" : "") + ") const";
  383. }
  384. // Generate an enum declaration and an enum string lookup table.
  385. void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
  386. std::string &code = *code_ptr;
  387. GenComment(enum_def.doc_comment, code_ptr, nullptr);
  388. code += GenEnumDecl(enum_def, parser_.opts);
  389. if (parser_.opts.scoped_enums)
  390. code += " : " + GenTypeBasic(enum_def.underlying_type, false);
  391. code += " {\n";
  392. int64_t anyv = 0;
  393. EnumVal *minv = nullptr, *maxv = nullptr;
  394. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  395. ++it) {
  396. auto &ev = **it;
  397. GenComment(ev.doc_comment, code_ptr, nullptr, " ");
  398. code += " " + GenEnumValDecl(enum_def, ev.name, parser_.opts) + " = ";
  399. code += NumToString(ev.value);
  400. if (it != enum_def.vals.vec.end() - 1) code += ",\n";
  401. minv = !minv || minv->value > ev.value ? &ev : minv;
  402. maxv = !maxv || maxv->value < ev.value ? &ev : maxv;
  403. anyv |= ev.value;
  404. }
  405. if (parser_.opts.scoped_enums || parser_.opts.prefixed_enums) {
  406. assert(minv && maxv);
  407. if (enum_def.attributes.Lookup("bit_flags")) {
  408. if (minv->value != 0) // If the user didn't defined NONE value
  409. code += ",\n " + GenEnumValDecl(enum_def, "NONE", parser_.opts) + " = 0";
  410. if (maxv->value != anyv) // If the user didn't defined ANY value
  411. code += ",\n " + GenEnumValDecl(enum_def, "ANY", parser_.opts) + " = " +
  412. NumToString(anyv);
  413. } else { // MIN & MAX are useless for bit_flags
  414. code += ",\n " + GenEnumValDecl(enum_def, "MIN", parser_.opts) + " = ";
  415. code += GenEnumValDecl(enum_def, minv->name, parser_.opts);
  416. code += ",\n " + GenEnumValDecl(enum_def, "MAX", parser_.opts) + " = ";
  417. code += GenEnumValDecl(enum_def, maxv->name, parser_.opts);
  418. }
  419. }
  420. code += "\n};\n";
  421. if (parser_.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags"))
  422. code += "DEFINE_BITMASK_OPERATORS(" + enum_def.name + ", " +
  423. GenTypeBasic(enum_def.underlying_type, false) + ")\n";
  424. code += "\n";
  425. // Generate a generate string table for enum values.
  426. // Problem is, if values are very sparse that could generate really big
  427. // tables. Ideally in that case we generate a map lookup instead, but for
  428. // the moment we simply don't output a table at all.
  429. auto range =
  430. enum_def.vals.vec.back()->value - enum_def.vals.vec.front()->value + 1;
  431. // Average distance between values above which we consider a table
  432. // "too sparse". Change at will.
  433. static const int kMaxSparseness = 5;
  434. if (range / static_cast<int64_t>(enum_def.vals.vec.size()) <
  435. kMaxSparseness) {
  436. code += "inline const char **EnumNames" + enum_def.name + "() {\n";
  437. code += " static const char *names[] = { ";
  438. auto val = enum_def.vals.vec.front()->value;
  439. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  440. ++it) {
  441. while (val++ != (*it)->value) code += "\"\", ";
  442. code += "\"" + (*it)->name + "\", ";
  443. }
  444. code += "nullptr };\n return names;\n}\n\n";
  445. code += "inline const char *EnumName" + enum_def.name;
  446. code += "(" + enum_def.name + " e) { return EnumNames" + enum_def.name;
  447. code += "()[static_cast<int>(e)";
  448. if (enum_def.vals.vec.front()->value) {
  449. code += " - static_cast<int>(";
  450. code += GetEnumValUse(enum_def, *enum_def.vals.vec.front(), parser_.opts) +
  451. ")";
  452. }
  453. code += "]; }\n\n";
  454. }
  455. // Generate type traits for unions to map from a type to union enum value.
  456. if (enum_def.is_union) {
  457. for (auto it = enum_def.vals.vec.begin();
  458. it != enum_def.vals.vec.end();
  459. ++it) {
  460. auto &ev = **it;
  461. if (it == enum_def.vals.vec.begin()) {
  462. code += "template<typename T> struct " + enum_def.name + "Traits {\n";
  463. }
  464. else {
  465. code += "template<> struct " + enum_def.name + "Traits<" +
  466. WrapInNameSpace(*ev.struct_def) + "> {\n";
  467. }
  468. code += " static const " + enum_def.name + " enum_value = " +
  469. GetEnumValUse(enum_def, ev, parser_.opts) + ";\n";
  470. code += "};\n\n";
  471. }
  472. }
  473. if (parser_.opts.generate_object_based_api && enum_def.is_union) {
  474. // Generate a union type
  475. code += "struct " + enum_def.name + "Union {\n";
  476. code += " " + enum_def.name + " type;\n\n";
  477. code += " flatbuffers::NativeTable *table;\n";
  478. code += " " + enum_def.name + "Union() : type(";
  479. code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
  480. code += "), table(nullptr) {}\n";
  481. code += " " + enum_def.name + "Union(const ";
  482. code += enum_def.name + "Union &);\n";
  483. code += " " + enum_def.name + "Union &operator=(const ";
  484. code += enum_def.name + "Union &);\n";
  485. code += " ~" + enum_def.name + "Union() { Reset(); }\n";
  486. code += " void Reset();\n\n";
  487. code += " template <typename T>\n";
  488. code += " void Set(T&& value) {\n";
  489. code += " Reset();\n";
  490. code += " type = " + enum_def.name;
  491. code += "Traits<typename T::TableType>::enum_value;\n";
  492. code += " if (type != ";
  493. code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
  494. code += ") {\n";
  495. code += " table = new T(std::forward<T>(value));\n";
  496. code += " }\n";
  497. code += " }\n\n";
  498. code += " " + UnionUnPackSignature(enum_def, true) + ";\n";
  499. code += " " + UnionPackSignature(enum_def, true) + ";\n\n";
  500. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  501. ++it) {
  502. auto &ev = **it;
  503. if (ev.value) {
  504. auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
  505. code += " " + native_name + " *As";
  506. code += ev.name + "() { return type == ";
  507. code += GetEnumValUse(enum_def, ev, parser_.opts);
  508. code += " ? reinterpret_cast<" + native_name;
  509. code += " *>(table) : nullptr; }\n";
  510. }
  511. }
  512. code += "};\n\n";
  513. }
  514. if (enum_def.is_union) {
  515. code += UnionVerifySignature(enum_def) + ";\n\n";
  516. }
  517. }
  518. void GenUnionPost(EnumDef &enum_def, std::string *code_ptr) {
  519. // Generate a verifier function for this union that can be called by the
  520. // table verifier functions. It uses a switch case to select a specific
  521. // verifier function to call, this should be safe even if the union type
  522. // has been corrupted, since the verifiers will simply fail when called
  523. // on the wrong type.
  524. std::string &code = *code_ptr;
  525. code += UnionVerifySignature(enum_def) + " {\n switch (type) {\n";
  526. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  527. ++it) {
  528. auto &ev = **it;
  529. code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
  530. if (!ev.value) {
  531. code += ": return true;\n"; // "NONE" enum value.
  532. } else {
  533. code += ": return verifier.VerifyTable(reinterpret_cast<const ";
  534. code += WrapInNameSpace(*ev.struct_def);
  535. code += " *>(union_obj));\n";
  536. }
  537. }
  538. code += " default: return false;\n }\n}\n\n";
  539. if (parser_.opts.generate_object_based_api) {
  540. // Generate a union pack & unpack function.
  541. code += "inline " + UnionUnPackSignature(enum_def, false);
  542. code += " {\n switch (type) {\n";
  543. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  544. ++it) {
  545. auto &ev = **it;
  546. code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
  547. if (!ev.value) {
  548. code += ": return nullptr;\n"; // "NONE" enum value.
  549. } else {
  550. code += ": return reinterpret_cast<const ";
  551. code += WrapInNameSpace(*ev.struct_def);
  552. code += " *>(union_obj)->UnPack(resolver);\n";
  553. }
  554. }
  555. code += " default: return nullptr;\n }\n}\n\n";
  556. code += "inline " + UnionPackSignature(enum_def, false);
  557. code += " {\n switch (type) {\n";
  558. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  559. ++it) {
  560. auto &ev = **it;
  561. code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
  562. if (!ev.value) {
  563. code += ": return 0;\n"; // "NONE" enum value.
  564. } else {
  565. code += ": return Create" + ev.struct_def->name;
  566. code += "(_fbb, reinterpret_cast<const ";
  567. code += NativeName(WrapInNameSpace(*ev.struct_def));
  568. code += " *>(table), rehasher).Union();\n";
  569. }
  570. }
  571. code += " default: return 0;\n }\n}\n\n";
  572. // Generate a union destructor.
  573. code += "inline void " + enum_def.name + "Union::Reset() {\n";
  574. code += " switch (type) {\n";
  575. for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
  576. ++it) {
  577. auto &ev = **it;
  578. if (ev.value) {
  579. code += " case " + GetEnumValUse(enum_def, ev, parser_.opts);
  580. code += ": delete reinterpret_cast<";
  581. code += NativeName(WrapInNameSpace(*ev.struct_def));
  582. code += " *>(table); break;\n";
  583. }
  584. }
  585. code += " default: break;\n";
  586. code += " }\n";
  587. code += " table = nullptr;\n";
  588. code += " type = ";
  589. code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
  590. code += ";\n";
  591. code += "}\n\n";
  592. }
  593. }
  594. // Generates a value with optionally a cast applied if the field has a
  595. // different underlying type from its interface type (currently only the
  596. // case for enums. "from" specify the direction, true meaning from the
  597. // underlying type to the interface type.
  598. std::string GenUnderlyingCast(const FieldDef &field, bool from,
  599. const std::string &val) {
  600. if (from && field.value.type.base_type == BASE_TYPE_BOOL) {
  601. return val + " != 0";
  602. } else if ((field.value.type.enum_def &&
  603. IsScalar(field.value.type.base_type)) ||
  604. field.value.type.base_type == BASE_TYPE_BOOL) {
  605. return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" +
  606. val + ")";
  607. } else {
  608. return val;
  609. }
  610. }
  611. std::string GenFieldOffsetName(const FieldDef &field) {
  612. std::string uname = field.name;
  613. std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper);
  614. return "VT_" + uname;
  615. }
  616. void GenFullyQualifiedNameGetter(const std::string &name, std::string &code) {
  617. if (parser_.opts.generate_name_strings) {
  618. code +=
  619. " static FLATBUFFERS_CONSTEXPR const char *GetFullyQualifiedName() "
  620. "{\n";
  621. code += " return \"" +
  622. parser_.namespaces_.back()->GetFullyQualifiedName(name) + "\";\n";
  623. code += " }\n";
  624. }
  625. }
  626. std::string GenDefaultConstant(const FieldDef &field) {
  627. return field.value.type.base_type == BASE_TYPE_FLOAT
  628. ? field.value.constant + "f"
  629. : field.value.constant;
  630. }
  631. std::string GetDefaultScalarValue(const FieldDef &field) {
  632. if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) {
  633. auto ev = field.value.type.enum_def->ReverseLookup(
  634. static_cast<int>(StringToInt(field.value.constant.c_str())), false);
  635. if (ev) {
  636. return WrapInNameSpace(
  637. field.value.type.enum_def->defined_namespace,
  638. GetEnumValUse(*field.value.type.enum_def, *ev, parser_.opts));
  639. } else {
  640. return GenUnderlyingCast(field, true, field.value.constant);
  641. }
  642. } else if (field.value.type.base_type == BASE_TYPE_BOOL) {
  643. return field.value.constant == "0" ? "false" : "true";
  644. } else {
  645. return GenDefaultConstant(field);
  646. }
  647. }
  648. void GenSimpleParam(std::string &code, FieldDef &field) {
  649. code += ",\n " + GenTypeWire(field.value.type, " ", true);
  650. code += field.name + " = " + GetDefaultScalarValue(field);
  651. }
  652. // Generate a member, including a default value for scalars and raw pointers.
  653. void GenMember(std::string& code, const FieldDef &field) {
  654. if (!field.deprecated && // Deprecated fields won't be accessible.
  655. field.value.type.base_type != BASE_TYPE_UTYPE) {
  656. auto type = GenTypeNative(field.value.type, false, field);
  657. auto cpp_type = field.attributes.Lookup("cpp_type");
  658. code += " " + (cpp_type ? cpp_type->constant + " *" : type+ " ") +
  659. field.name + ";\n";
  660. }
  661. }
  662. // Generate the default constructor for this struct. Properly initialize all
  663. // scalar members with default values.
  664. void GenDefaultConstructor(std::string& code, const StructDef& struct_def) {
  665. code += " " + NativeName(struct_def.name) + "()";
  666. std::string initializer_list;
  667. for (auto it = struct_def.fields.vec.begin();
  668. it != struct_def.fields.vec.end(); ++it) {
  669. auto &field = **it;
  670. if (!field.deprecated && // Deprecated fields won't be accessible.
  671. field.value.type.base_type != BASE_TYPE_UTYPE) {
  672. auto cpp_type = field.attributes.Lookup("cpp_type");
  673. // Scalar types get parsed defaults, raw pointers get nullptrs.
  674. if (IsScalar(field.value.type.base_type)) {
  675. if (!initializer_list.empty()) {
  676. initializer_list += ",\n ";
  677. }
  678. initializer_list += field.name + "(" +GetDefaultScalarValue(field) +
  679. ")";
  680. } else if (cpp_type) {
  681. if (!initializer_list.empty()) {
  682. code += ",\n ";
  683. }
  684. initializer_list += field.name + "(0)";
  685. }
  686. }
  687. }
  688. if (!initializer_list.empty()) {
  689. code += "\n : " + initializer_list;
  690. }
  691. code += " {}\n";
  692. }
  693. // Generate an accessor struct, builder structs & function for a table.
  694. void GenTable(StructDef &struct_def, std::string *code_ptr) {
  695. std::string &code = *code_ptr;
  696. if (parser_.opts.generate_object_based_api) {
  697. // Generate a C++ object that can hold an unpacked version of this
  698. // table.
  699. code += "struct " + NativeName(struct_def.name);
  700. code += " : public flatbuffers::NativeTable {\n";
  701. code += " typedef " + struct_def.name + " TableType;\n";
  702. // Generate GetFullyQualifiedName
  703. GenFullyQualifiedNameGetter(NativeName(struct_def.name), code);
  704. for (auto it = struct_def.fields.vec.begin();
  705. it != struct_def.fields.vec.end(); ++it) {
  706. auto &field = **it;
  707. GenMember(code, field);
  708. }
  709. GenDefaultConstructor(code, struct_def);
  710. code += "};\n\n";
  711. }
  712. // Generate an accessor struct, with methods of the form:
  713. // type name() const { return GetField<type>(offset, defaultval); }
  714. GenComment(struct_def.doc_comment, code_ptr, nullptr);
  715. code += "struct " + struct_def.name;
  716. code += " FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table";
  717. code += " {\n";
  718. if (parser_.opts.generate_object_based_api) {
  719. code += " typedef " + NativeName(struct_def.name) +
  720. " NativeTableType;\n";
  721. }
  722. // Generate GetFullyQualifiedName
  723. GenFullyQualifiedNameGetter(struct_def.name, code);
  724. // Generate field id constants.
  725. if (struct_def.fields.vec.size() > 0) {
  726. code += " enum {\n";
  727. bool is_first_field =
  728. true; // track the first field that's not deprecated
  729. for (auto it = struct_def.fields.vec.begin();
  730. it != struct_def.fields.vec.end(); ++it) {
  731. auto &field = **it;
  732. if (!field.deprecated) { // Deprecated fields won't be accessible.
  733. if (!is_first_field) {
  734. // Add trailing comma and newline to previous element. Don't add
  735. // trailing comma to
  736. // last element since older versions of gcc complain about this.
  737. code += ",\n";
  738. } else {
  739. is_first_field = false;
  740. }
  741. code += " " + GenFieldOffsetName(field) + " = ";
  742. code += NumToString(field.value.offset);
  743. }
  744. }
  745. code += "\n };\n";
  746. }
  747. // Generate the accessors.
  748. for (auto it = struct_def.fields.vec.begin();
  749. it != struct_def.fields.vec.end(); ++it) {
  750. auto &field = **it;
  751. if (!field.deprecated) { // Deprecated fields won't be accessible.
  752. auto is_scalar = IsScalar(field.value.type.base_type);
  753. GenComment(field.doc_comment, code_ptr, nullptr, " ");
  754. code += " " + GenTypeGet(field.value.type, " ", "const ", " *", true);
  755. code += field.name + "() const { return ";
  756. // Call a different accessor for pointers, that indirects.
  757. auto accessor =
  758. is_scalar
  759. ? "GetField<"
  760. : (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<");
  761. auto offsetstr = GenFieldOffsetName(field);
  762. auto call = accessor +
  763. GenTypeGet(field.value.type, "", "const ", " *", false) +
  764. ">(" + offsetstr;
  765. // Default value as second arg for non-pointer types.
  766. if (IsScalar(field.value.type.base_type))
  767. call += ", " + GenDefaultConstant(field);
  768. call += ")";
  769. code += GenUnderlyingCast(field, true, call);
  770. code += "; }\n";
  771. if (parser_.opts.mutable_buffer) {
  772. if (is_scalar) {
  773. code += " bool mutate_" + field.name + "(";
  774. code += GenTypeBasic(field.value.type, true);
  775. code +=
  776. " _" + field.name + ") { return SetField(" + offsetstr + ", ";
  777. code += GenUnderlyingCast(field, false, "_" + field.name);
  778. code += "); }\n";
  779. } else {
  780. auto type = GenTypeGet(field.value.type, " ", "", " *", true);
  781. code += " " + type + "mutable_" + field.name + "() { return ";
  782. code += GenUnderlyingCast(field, true,
  783. accessor + type + ">(" + offsetstr + ")");
  784. code += "; }\n";
  785. }
  786. }
  787. auto nested = field.attributes.Lookup("nested_flatbuffer");
  788. if (nested) {
  789. std::string qualified_name =
  790. parser_.namespaces_.back()->GetFullyQualifiedName(
  791. nested->constant);
  792. auto nested_root = parser_.structs_.Lookup(qualified_name);
  793. assert(nested_root); // Guaranteed to exist by parser.
  794. (void)nested_root;
  795. std::string cpp_qualified_name = TranslateNameSpace(qualified_name);
  796. code += " const " + cpp_qualified_name + " *" + field.name;
  797. code += "_nested_root() const { return flatbuffers::GetRoot<";
  798. code += cpp_qualified_name + ">(" + field.name + "()->Data()); }\n";
  799. }
  800. // Generate a comparison function for this field if it is a key.
  801. if (field.key) {
  802. code += " bool KeyCompareLessThan(const " + struct_def.name;
  803. code += " *o) const { return ";
  804. if (field.value.type.base_type == BASE_TYPE_STRING) code += "*";
  805. code += field.name + "() < ";
  806. if (field.value.type.base_type == BASE_TYPE_STRING) code += "*";
  807. code += "o->" + field.name + "(); }\n";
  808. code += " int KeyCompareWithValue(";
  809. if (field.value.type.base_type == BASE_TYPE_STRING) {
  810. code += "const char *val) const { return strcmp(" + field.name;
  811. code += "()->c_str(), val); }\n";
  812. } else {
  813. if (parser_.opts.scoped_enums && field.value.type.enum_def &&
  814. IsScalar(field.value.type.base_type)) {
  815. code += GenTypeGet(field.value.type, " ", "const ", " *", true);
  816. } else {
  817. code += GenTypeBasic(field.value.type, false);
  818. }
  819. code += " val) const { return " + field.name + "() < val ? -1 : ";
  820. code += field.name + "() > val; }\n";
  821. }
  822. }
  823. }
  824. }
  825. // Generate a verifier function that can check a buffer from an untrusted
  826. // source will never cause reads outside the buffer.
  827. code += " bool Verify(flatbuffers::Verifier &verifier) const {\n";
  828. code += " return VerifyTableStart(verifier)";
  829. std::string prefix = " &&\n ";
  830. for (auto it = struct_def.fields.vec.begin();
  831. it != struct_def.fields.vec.end(); ++it) {
  832. auto &field = **it;
  833. if (!field.deprecated) {
  834. code += prefix + "VerifyField";
  835. if (field.required) code += "Required";
  836. code += "<" + GenTypeSize(field.value.type);
  837. code += ">(verifier, " + GenFieldOffsetName(field) + ")";
  838. switch (field.value.type.base_type) {
  839. case BASE_TYPE_UNION:
  840. code += prefix + "Verify" + field.value.type.enum_def->name;
  841. code += "(verifier, " + field.name + "(), " + field.name +
  842. UnionTypeFieldSuffix() + "())";
  843. break;
  844. case BASE_TYPE_STRUCT:
  845. if (!field.value.type.struct_def->fixed) {
  846. code += prefix + "verifier.VerifyTable(" + field.name;
  847. code += "())";
  848. }
  849. break;
  850. case BASE_TYPE_STRING:
  851. code += prefix + "verifier.Verify(" + field.name + "())";
  852. break;
  853. case BASE_TYPE_VECTOR:
  854. code += prefix + "verifier.Verify(" + field.name + "())";
  855. switch (field.value.type.element) {
  856. case BASE_TYPE_STRING: {
  857. code += prefix + "verifier.VerifyVectorOfStrings(" + field.name;
  858. code += "())";
  859. break;
  860. }
  861. case BASE_TYPE_STRUCT: {
  862. if (!field.value.type.struct_def->fixed) {
  863. code +=
  864. prefix + "verifier.VerifyVectorOfTables(" + field.name;
  865. code += "())";
  866. }
  867. break;
  868. }
  869. default:
  870. break;
  871. }
  872. break;
  873. default:
  874. break;
  875. }
  876. }
  877. }
  878. code += prefix + "verifier.EndTable()";
  879. code += ";\n }\n";
  880. if (parser_.opts.generate_object_based_api) {
  881. // Generate the UnPack() pre declaration.
  882. code += " " + TableUnPackSignature(struct_def, true) + ";\n";
  883. code += " " + TablePackSignature(struct_def, true) + ";\n";
  884. }
  885. code += "};\n\n"; // End of table.
  886. // Generate a builder struct, with methods of the form:
  887. // void add_name(type name) { fbb_.AddElement<type>(offset, name, default);
  888. // }
  889. code += "struct " + struct_def.name;
  890. code += "Builder {\n flatbuffers::FlatBufferBuilder &fbb_;\n";
  891. code += " flatbuffers::uoffset_t start_;\n";
  892. for (auto it = struct_def.fields.vec.begin();
  893. it != struct_def.fields.vec.end(); ++it) {
  894. auto &field = **it;
  895. if (!field.deprecated) {
  896. code += " void add_" + field.name + "(";
  897. code += GenTypeWire(field.value.type, " ", true) + field.name;
  898. code += ") { fbb_.Add";
  899. if (IsScalar(field.value.type.base_type)) {
  900. code += "Element<" + GenTypeWire(field.value.type, "", false);
  901. code += ">";
  902. } else if (IsStruct(field.value.type)) {
  903. code += "Struct";
  904. } else {
  905. code += "Offset";
  906. }
  907. code += "(" + struct_def.name + "::" + GenFieldOffsetName(field) + ", ";
  908. code += GenUnderlyingCast(field, false, field.name);
  909. if (IsScalar(field.value.type.base_type))
  910. code += ", " + GenDefaultConstant(field);
  911. code += "); }\n";
  912. }
  913. }
  914. code += " " + struct_def.name;
  915. code += "Builder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) ";
  916. code += "{ start_ = fbb_.StartTable(); }\n";
  917. code += " " + struct_def.name + "Builder &operator=(const ";
  918. code += struct_def.name + "Builder &);\n";
  919. code += " flatbuffers::Offset<" + struct_def.name;
  920. code += "> Finish() {\n auto o = flatbuffers::Offset<" + struct_def.name;
  921. code += ">(fbb_.EndTable(start_, ";
  922. code += NumToString(struct_def.fields.vec.size()) + "));\n";
  923. for (auto it = struct_def.fields.vec.begin();
  924. it != struct_def.fields.vec.end(); ++it) {
  925. auto &field = **it;
  926. if (!field.deprecated && field.required) {
  927. code += " fbb_.Required(o, ";
  928. code += struct_def.name + "::" + GenFieldOffsetName(field);
  929. code += "); // " + field.name + "\n";
  930. }
  931. }
  932. code += " return o;\n }\n};\n\n";
  933. // Generate a convenient CreateX function that uses the above builder
  934. // to create a table in one go.
  935. bool gen_vector_pars = false;
  936. code += "inline flatbuffers::Offset<" + struct_def.name + "> Create";
  937. code += struct_def.name;
  938. code += "(flatbuffers::FlatBufferBuilder &_fbb";
  939. for (auto it = struct_def.fields.vec.begin();
  940. it != struct_def.fields.vec.end(); ++it) {
  941. auto &field = **it;
  942. if (!field.deprecated) {
  943. if (field.value.type.base_type == BASE_TYPE_STRING ||
  944. field.value.type.base_type == BASE_TYPE_VECTOR) {
  945. gen_vector_pars = true;
  946. }
  947. GenSimpleParam(code, field);
  948. }
  949. }
  950. code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\n";
  951. for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
  952. size; size /= 2) {
  953. for (auto it = struct_def.fields.vec.rbegin();
  954. it != struct_def.fields.vec.rend(); ++it) {
  955. auto &field = **it;
  956. if (!field.deprecated && (!struct_def.sortbysize ||
  957. size == SizeOf(field.value.type.base_type))) {
  958. code += " builder_.add_" + field.name + "(" + field.name + ");\n";
  959. }
  960. }
  961. }
  962. code += " return builder_.Finish();\n}\n\n";
  963. // Generate a CreateXDirect function with vector types as parameters
  964. if (gen_vector_pars) {
  965. code += "inline flatbuffers::Offset<" + struct_def.name + "> Create";
  966. code += struct_def.name;
  967. code += "Direct(flatbuffers::FlatBufferBuilder &_fbb";
  968. for (auto it = struct_def.fields.vec.begin();
  969. it != struct_def.fields.vec.end(); ++it) {
  970. auto &field = **it;
  971. if (!field.deprecated) {
  972. if (field.value.type.base_type == BASE_TYPE_STRING) {
  973. code += ",\n const char *";
  974. code += field.name + " = nullptr";
  975. } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
  976. code += ",\n const std::vector<";
  977. code += GenTypeWire(field.value.type.VectorType(), "", false);
  978. code += "> *" + field.name + " = nullptr";
  979. } else {
  980. GenSimpleParam(code, field);
  981. }
  982. }
  983. }
  984. code += ") {\n ";
  985. code += "return Create";
  986. code += struct_def.name;
  987. code += "(_fbb";
  988. for (auto it = struct_def.fields.vec.begin();
  989. it != struct_def.fields.vec.end(); ++it) {
  990. auto &field = **it;
  991. if (!field.deprecated) {
  992. if (field.value.type.base_type == BASE_TYPE_STRING) {
  993. code += ", " + field.name + " ? ";
  994. code += "_fbb.CreateString(" + field.name + ") : 0";
  995. } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
  996. code += ", " + field.name + " ? ";
  997. code += "_fbb.CreateVector<";
  998. code += GenTypeWire(field.value.type.VectorType(), "", false);
  999. code += ">(*" + field.name + ") : 0";
  1000. } else {
  1001. code += ", " + field.name;
  1002. }
  1003. }
  1004. }
  1005. code += ");\n}\n\n";
  1006. }
  1007. if (parser_.opts.generate_object_based_api) {
  1008. // Generate a pre-declaration for a CreateX method that works with an
  1009. // unpacked C++ object.
  1010. code += TableCreateSignature(struct_def, true) + ";\n\n";
  1011. }
  1012. }
  1013. std::string GenUnpackVal(const Type &type, const std::string &val,
  1014. bool invector, const FieldDef &afield) {
  1015. switch (type.base_type) {
  1016. case BASE_TYPE_STRING:
  1017. return val + "->str()";
  1018. case BASE_TYPE_STRUCT:
  1019. if (IsStruct(type)) {
  1020. if (invector || afield.native_inline) {
  1021. return "*" + val;
  1022. } else {
  1023. return GenTypeNativePtr(WrapInNameSpace(*type.struct_def),
  1024. &afield, true) +
  1025. "(new " +
  1026. WrapInNameSpace(*type.struct_def) + "(*" + val + "))";
  1027. }
  1028. } else {
  1029. return GenTypeNativePtr(NativeName(WrapInNameSpace(
  1030. *type.struct_def)), &afield, true) +
  1031. "(" + val + "->UnPack(resolver))";
  1032. }
  1033. default:
  1034. return val;
  1035. break;
  1036. }
  1037. };
  1038. // Generate code for tables that needs to come after the regular definition.
  1039. void GenTablePost(StructDef &struct_def, std::string *code_ptr) {
  1040. std::string &code = *code_ptr;
  1041. if (parser_.opts.generate_object_based_api) {
  1042. // Generate the UnPack() method.
  1043. code += "inline " + TableUnPackSignature(struct_def, false) + " {\n";
  1044. code += " (void)resolver;\n";
  1045. code += " auto _o = new " + NativeName(struct_def.name) + "();\n";
  1046. for (auto it = struct_def.fields.vec.begin();
  1047. it != struct_def.fields.vec.end(); ++it) {
  1048. auto &field = **it;
  1049. if (!field.deprecated) {
  1050. auto prefix = " { auto _e = " + field.name + "(); ";
  1051. if (!IsScalar(field.value.type.base_type)) prefix += "if (_e) ";
  1052. auto deref = "_o->";
  1053. auto dest = deref + field.name;
  1054. auto assign = prefix + dest + " = ";
  1055. switch (field.value.type.base_type) {
  1056. case BASE_TYPE_VECTOR: {
  1057. code += prefix;
  1058. code += "{ for (flatbuffers::uoffset_t _i = 0;";
  1059. code += " _i < _e->size(); _i++) { ";
  1060. code += dest + ".push_back(";
  1061. std::string indexing;
  1062. if (field.value.type.enum_def) {
  1063. indexing += "(" + field.value.type.enum_def->name + ")";
  1064. }
  1065. indexing += "_e->Get(_i)";
  1066. if (field.value.type.element == BASE_TYPE_BOOL)
  1067. indexing += "!=0";
  1068. code += GenUnpackVal(field.value.type.VectorType(),
  1069. indexing, true, field);
  1070. code += "); } }";
  1071. break;
  1072. }
  1073. case BASE_TYPE_UTYPE: {
  1074. auto &union_field = **(it + 1);
  1075. assert(union_field.value.type.base_type == BASE_TYPE_UNION);
  1076. code += prefix + deref + union_field.name + ".type = _e;";
  1077. break;
  1078. }
  1079. case BASE_TYPE_UNION: {
  1080. code += prefix + dest + ".table = ";
  1081. code += field.value.type.enum_def->name;
  1082. code += "Union::UnPack(_e, ";
  1083. code += field.name + UnionTypeFieldSuffix() + "(), resolver);";
  1084. break;
  1085. }
  1086. default: {
  1087. auto cpp_type = field.attributes.Lookup("cpp_type");
  1088. if (cpp_type) {
  1089. code += prefix;
  1090. code += "if (resolver) (*resolver)(reinterpret_cast<void **>(&";
  1091. code += dest;
  1092. code += "), static_cast<flatbuffers::hash_value_t>(_e)); else ";
  1093. code += dest + " = nullptr";
  1094. } else {
  1095. code += assign;
  1096. code += GenUnpackVal(field.value.type, "_e", false, field);
  1097. }
  1098. code += ";";
  1099. break;
  1100. }
  1101. }
  1102. code += " };\n";
  1103. }
  1104. }
  1105. code += " return _o;\n}\n\n";
  1106. // Generate the X::Pack member function that simply calls the global
  1107. // CreateX function.
  1108. code += "inline " + TablePackSignature(struct_def, false) + " {\n";
  1109. code += " return Create" + struct_def.name + "(_fbb, _o, _rehasher);\n";
  1110. code += "}\n\n";
  1111. // Generate a CreateX method that works with an unpacked C++ object.
  1112. code += TableCreateSignature(struct_def, false) + " {\n";
  1113. code += " (void)rehasher;\n";
  1114. auto before_return_statement = code.size();
  1115. code += " return Create";
  1116. code += struct_def.name + "(_fbb";
  1117. bool any_fields = false;
  1118. for (auto it = struct_def.fields.vec.begin();
  1119. it != struct_def.fields.vec.end(); ++it) {
  1120. auto &field = **it;
  1121. if (!field.deprecated) {
  1122. any_fields = true;
  1123. auto field_name = field.name;
  1124. if (field.value.type.base_type == BASE_TYPE_UTYPE) {
  1125. field_name = field_name.substr(0, field_name.size() -
  1126. strlen(UnionTypeFieldSuffix()));
  1127. field_name += ".type";
  1128. }
  1129. auto accessor = "_o->" + field_name;
  1130. if (field.attributes.Lookup("cpp_type"))
  1131. accessor = "rehasher ? static_cast<" +
  1132. GenTypeBasic(field.value.type, false) +
  1133. ">((*rehasher)(" + accessor + ")) : 0";
  1134. auto ptrprefix = accessor + " ? ";
  1135. auto stlprefix = accessor + ".size() ? ";
  1136. auto postfix = " : 0";
  1137. if (field.required &&
  1138. (field.value.type.base_type == BASE_TYPE_STRING ||
  1139. field.value.type.base_type == BASE_TYPE_VECTOR)) {
  1140. stlprefix = "";
  1141. postfix = "";
  1142. }
  1143. code += ",\n ";
  1144. switch (field.value.type.base_type) {
  1145. case BASE_TYPE_STRING:
  1146. code += stlprefix + "_fbb.CreateString(" + accessor + ")";
  1147. code += postfix;
  1148. break;
  1149. case BASE_TYPE_VECTOR: {
  1150. auto vector_type = field.value.type.VectorType();
  1151. code += stlprefix;
  1152. switch (vector_type.base_type) {
  1153. case BASE_TYPE_STRING:
  1154. code += "_fbb.CreateVectorOfStrings(" + accessor + ")";
  1155. break;
  1156. case BASE_TYPE_STRUCT:
  1157. if (IsStruct(vector_type)) {
  1158. code += "_fbb.CreateVectorOfStructs(" + accessor + ")";
  1159. } else {
  1160. code += "_fbb.CreateVector<flatbuffers::Offset<";
  1161. code += WrapInNameSpace(*vector_type.struct_def) + ">>(" +
  1162. accessor;
  1163. code += ".size(), [&](size_t i) { return Create";
  1164. code += vector_type.struct_def->name + "(_fbb, " + accessor;
  1165. code += "[i]" + GenPtrGet(field) + ", rehasher); })";
  1166. }
  1167. break;
  1168. case BASE_TYPE_BOOL:
  1169. code += "_fbb.CreateVector(" + accessor + ")";
  1170. break;
  1171. default: {
  1172. std::string args = accessor;
  1173. if (field.value.type.enum_def) {
  1174. const std::string basetype = GenTypeBasic(
  1175. field.value.type.enum_def->underlying_type, false);
  1176. args = "(const " + basetype + "*)" + accessor +
  1177. ".data(), " + accessor + ".size()";
  1178. }
  1179. code += "_fbb.CreateVector(" + args + ")";
  1180. break;
  1181. }
  1182. }
  1183. code += postfix;
  1184. break;
  1185. }
  1186. case BASE_TYPE_UNION:
  1187. code += accessor + ".Pack(_fbb)";
  1188. break;
  1189. case BASE_TYPE_STRUCT:
  1190. if (IsStruct(field.value.type)) {
  1191. if (field.native_inline) {
  1192. code += "&" + accessor;
  1193. } else {
  1194. code += ptrprefix + accessor + GenPtrGet(field) + postfix;
  1195. }
  1196. } else {
  1197. code += ptrprefix + "Create";
  1198. code += field.value.type.struct_def->name;
  1199. code += "(_fbb, " + accessor + GenPtrGet(field) + ", rehasher)";
  1200. code += postfix;
  1201. }
  1202. break;
  1203. default:
  1204. code += accessor;
  1205. break;
  1206. }
  1207. }
  1208. }
  1209. code += ");\n}\n\n";
  1210. if (!any_fields) code.insert(before_return_statement, " (void)_o;\n");
  1211. }
  1212. }
  1213. static void GenPadding(const FieldDef &field, std::string &code,
  1214. int &padding_id,
  1215. const std::function<void(int bits, std::string &code,
  1216. int &padding_id)> &f) {
  1217. if (field.padding) {
  1218. for (int i = 0; i < 4; i++)
  1219. if (static_cast<int>(field.padding) & (1 << i))
  1220. f((1 << i) * 8, code, padding_id);
  1221. assert(!(field.padding & ~0xF));
  1222. }
  1223. }
  1224. static void PaddingDefinition(int bits, std::string &code, int &padding_id) {
  1225. code += " int" + NumToString(bits) + "_t __padding" +
  1226. NumToString(padding_id++) + ";\n";
  1227. }
  1228. static void PaddingDeclaration(int bits, std::string &code, int &padding_id) {
  1229. (void)bits;
  1230. code += " (void)__padding" + NumToString(padding_id++) + ";";
  1231. }
  1232. static void PaddingInitializer(int bits, std::string &code, int &padding_id) {
  1233. (void)bits;
  1234. code += ", __padding" + NumToString(padding_id++) + "(0)";
  1235. }
  1236. // Generate an accessor struct with constructor for a flatbuffers struct.
  1237. void GenStruct(StructDef &struct_def, std::string *code_ptr) {
  1238. if (struct_def.generated) return;
  1239. std::string &code = *code_ptr;
  1240. // Generate an accessor struct, with private variables of the form:
  1241. // type name_;
  1242. // Generates manual padding and alignment.
  1243. // Variables are private because they contain little endian data on all
  1244. // platforms.
  1245. GenComment(struct_def.doc_comment, code_ptr, nullptr);
  1246. code +=
  1247. "MANUALLY_ALIGNED_STRUCT(" + NumToString(struct_def.minalign) + ") ";
  1248. code += struct_def.name + " FLATBUFFERS_FINAL_CLASS {\n private:\n";
  1249. int padding_id = 0;
  1250. for (auto it = struct_def.fields.vec.begin();
  1251. it != struct_def.fields.vec.end(); ++it) {
  1252. auto &field = **it;
  1253. code += " " + GenTypeGet(field.value.type, " ", "", " ", false);
  1254. code += field.name + "_;\n";
  1255. GenPadding(field, code, padding_id, PaddingDefinition);
  1256. }
  1257. // Generate GetFullyQualifiedName
  1258. code += "\n public:\n";
  1259. GenFullyQualifiedNameGetter(struct_def.name, code);
  1260. // Generate a default constructor.
  1261. code += " " + struct_def.name + "() { memset(this, 0, sizeof(";
  1262. code += struct_def.name + ")); }\n";
  1263. // Generate a copy constructor.
  1264. code += " " + struct_def.name + "(const " + struct_def.name;
  1265. code += " &_o) { memcpy(this, &_o, sizeof(";
  1266. code += struct_def.name + ")); }\n";
  1267. // Generate a constructor that takes all fields as arguments.
  1268. if (struct_def.fields.vec.size()) {
  1269. code += " " + struct_def.name + "(";
  1270. for (auto it = struct_def.fields.vec.begin();
  1271. it != struct_def.fields.vec.end(); ++it) {
  1272. auto &field = **it;
  1273. if (it != struct_def.fields.vec.begin()) code += ", ";
  1274. code += GenTypeGet(field.value.type, " ", "const ", " &", true);
  1275. code += "_" + field.name;
  1276. }
  1277. code += ")\n : ";
  1278. padding_id = 0;
  1279. for (auto it = struct_def.fields.vec.begin();
  1280. it != struct_def.fields.vec.end(); ++it) {
  1281. auto &field = **it;
  1282. if (it != struct_def.fields.vec.begin()) code += ", ";
  1283. code += field.name + "_(";
  1284. if (IsScalar(field.value.type.base_type)) {
  1285. code += "flatbuffers::EndianScalar(";
  1286. code += GenUnderlyingCast(field, false, "_" + field.name);
  1287. code += "))";
  1288. } else {
  1289. code += "_" + field.name + ")";
  1290. }
  1291. GenPadding(field, code, padding_id, PaddingInitializer);
  1292. }
  1293. code += " {";
  1294. padding_id = 0;
  1295. for (auto it = struct_def.fields.vec.begin();
  1296. it != struct_def.fields.vec.end(); ++it) {
  1297. auto &field = **it;
  1298. GenPadding(field, code, padding_id, PaddingDeclaration);
  1299. }
  1300. code += " }\n\n";
  1301. }
  1302. // Generate accessor methods of the form:
  1303. // type name() const { return flatbuffers::EndianScalar(name_); }
  1304. for (auto it = struct_def.fields.vec.begin();
  1305. it != struct_def.fields.vec.end(); ++it) {
  1306. auto &field = **it;
  1307. GenComment(field.doc_comment, code_ptr, nullptr, " ");
  1308. auto is_scalar = IsScalar(field.value.type.base_type);
  1309. code += " " + GenTypeGet(field.value.type, " ", "const ", " &", true);
  1310. code += field.name + "() const { return ";
  1311. code += GenUnderlyingCast(
  1312. field, true, is_scalar
  1313. ? "flatbuffers::EndianScalar(" + field.name + "_)"
  1314. : field.name + "_");
  1315. code += "; }\n";
  1316. if (parser_.opts.mutable_buffer) {
  1317. if (is_scalar) {
  1318. code += " void mutate_" + field.name + "(";
  1319. code += GenTypeBasic(field.value.type, true);
  1320. code += " _" + field.name + ") { flatbuffers::WriteScalar(&";
  1321. code += field.name + "_, ";
  1322. code += GenUnderlyingCast(field, false, "_" + field.name);
  1323. code += "); }\n";
  1324. } else {
  1325. code += " ";
  1326. code += GenTypeGet(field.value.type, "", "", " &", true);
  1327. code += "mutable_" + field.name + "() { return " + field.name;
  1328. code += "_; }\n";
  1329. }
  1330. }
  1331. }
  1332. code += "};\nSTRUCT_END(" + struct_def.name + ", ";
  1333. code += NumToString(struct_def.bytesize) + ");\n\n";
  1334. }
  1335. // Set up the correct namespace. Only open a namespace if
  1336. // the existing one is different (closing/opening only what is necessary) :
  1337. //
  1338. // the file must start and end with an empty (or null) namespace
  1339. // so that namespaces are properly opened and closed
  1340. void SetNameSpace(const Namespace *ns, std::string *code_ptr) {
  1341. if (cur_name_space_ == ns) return;
  1342. // compute the size of the longest common namespace prefix.
  1343. // if cur_name_space is A::B::C::D and ns is A::B::E::F::G,
  1344. // the common prefix is A::B:: and we have old_size = 4, new_size = 5
  1345. // and common_prefix_size = 2
  1346. auto old_size =
  1347. cur_name_space_ == nullptr ? 0 : cur_name_space_->components.size();
  1348. auto new_size = ns == nullptr ? 0 : ns->components.size();
  1349. std::vector<std::string>::size_type common_prefix_size = 0;
  1350. while (common_prefix_size < old_size && common_prefix_size < new_size &&
  1351. ns->components[common_prefix_size] ==
  1352. cur_name_space_->components[common_prefix_size])
  1353. common_prefix_size++;
  1354. // close cur_name_space in reverse order to reach the common prefix
  1355. // in the previous example, D then C are closed
  1356. for (auto j = old_size; j > common_prefix_size; --j)
  1357. *code_ptr +=
  1358. "} // namespace " + cur_name_space_->components[j - 1] + "\n";
  1359. if (old_size != common_prefix_size) *code_ptr += "\n";
  1360. // open namespace parts to reach the ns namespace
  1361. // in the previous example, E, then F, then G are opened
  1362. for (auto j = common_prefix_size; j != new_size; ++j)
  1363. *code_ptr += "namespace " + ns->components[j] + " {\n";
  1364. if (new_size != common_prefix_size) *code_ptr += "\n";
  1365. cur_name_space_ = ns;
  1366. }
  1367. };
  1368. } // namespace cpp
  1369. bool GenerateCPP(const Parser &parser, const std::string &path,
  1370. const std::string &file_name) {
  1371. cpp::CppGenerator generator(parser, path, file_name);
  1372. return generator.generate();
  1373. }
  1374. std::string CPPMakeRule(const Parser &parser, const std::string &path,
  1375. const std::string &file_name) {
  1376. std::string filebase =
  1377. flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
  1378. std::string make_rule = GeneratedFileName(path, filebase) + ": ";
  1379. auto included_files = parser.GetIncludedFilesRecursive(file_name);
  1380. for (auto it = included_files.begin(); it != included_files.end(); ++it) {
  1381. make_rule += " " + *it;
  1382. }
  1383. return make_rule;
  1384. }
  1385. } // namespace flatbuffers