idl_gen_go.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  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 <string>
  18. #include "flatbuffers/flatbuffers.h"
  19. #include "flatbuffers/idl.h"
  20. #include "flatbuffers/util.h"
  21. #ifdef _WIN32
  22. #include <direct.h>
  23. #define PATH_SEPARATOR "\\"
  24. #define mkdir(n, m) _mkdir(n)
  25. #else
  26. #include <sys/stat.h>
  27. #define PATH_SEPARATOR "/"
  28. #endif
  29. namespace flatbuffers {
  30. namespace go {
  31. static std::string GenGetter(const Type &type);
  32. static std::string GenMethod(const FieldDef &field);
  33. static void GenStructBuilder(const StructDef &struct_def,
  34. std::string *code_ptr);
  35. static void GenReceiver(const StructDef &struct_def, std::string *code_ptr);
  36. static std::string GenTypeBasic(const Type &type);
  37. static std::string GenTypeGet(const Type &type);
  38. static std::string TypeName(const FieldDef &field);
  39. // Most field accessors need to retrieve and test the field offset first,
  40. // this is the prefix code for that.
  41. std::string OffsetPrefix(const FieldDef &field) {
  42. return "{\n\to := flatbuffers.UOffsetT(rcv._tab.Offset(" +
  43. NumToString(field.value.offset) +
  44. "))\n\tif o != 0 {\n";
  45. }
  46. // Begin by declaring namespace and imports.
  47. static void BeginFile(const std::string name_space_name,
  48. const bool needs_imports,
  49. std::string *code_ptr) {
  50. std::string &code = *code_ptr;
  51. code += "// automatically generated, do not modify\n\n";
  52. code += "package " + name_space_name + "\n\n";
  53. if (needs_imports) {
  54. code += "import (\n";
  55. code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
  56. code += ")\n";
  57. }
  58. }
  59. // Begin a class declaration.
  60. static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
  61. std::string &code = *code_ptr;
  62. code += "type " + struct_def.name + " struct {\n\t";
  63. // _ is reserved in flatbuffers field names, so no chance of name conflict:
  64. code += "_tab ";
  65. code += struct_def.fixed ? "flatbuffers.Struct" : "flatbuffers.Table";
  66. code += "\n}\n\n";
  67. }
  68. // Begin enum code with a class declaration.
  69. static void BeginEnum(std::string *code_ptr) {
  70. std::string &code = *code_ptr;
  71. code += "const (\n";
  72. }
  73. // A single enum member.
  74. static void EnumMember(const EnumDef &enum_def, const EnumVal ev,
  75. std::string *code_ptr) {
  76. std::string &code = *code_ptr;
  77. code += "\t";
  78. code += enum_def.name;
  79. code += ev.name;
  80. code += " = ";
  81. code += NumToString(ev.value) + "\n";
  82. }
  83. // End enum code.
  84. static void EndEnum(std::string *code_ptr) {
  85. std::string &code = *code_ptr;
  86. code += ")\n";
  87. }
  88. // Initialize a new struct or table from existing data.
  89. static void NewRootTypeFromBuffer(const StructDef &struct_def,
  90. std::string *code_ptr) {
  91. std::string &code = *code_ptr;
  92. code += "func GetRootAs";
  93. code += struct_def.name;
  94. code += "(buf []byte, offset flatbuffers.UOffsetT) ";
  95. code += "*" + struct_def.name + "";
  96. code += " {\n";
  97. code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
  98. code += "\tx := &" + struct_def.name + "{}\n";
  99. code += "\tx.Init(buf, n + offset)\n";
  100. code += "\treturn x\n";
  101. code += "}\n\n";
  102. }
  103. // Initialize an existing object with other data, to avoid an allocation.
  104. static void InitializeExisting(const StructDef &struct_def,
  105. std::string *code_ptr) {
  106. std::string &code = *code_ptr;
  107. GenReceiver(struct_def, code_ptr);
  108. code += " Init(buf []byte, i flatbuffers.UOffsetT) ";
  109. code += "{\n";
  110. code += "\trcv._tab.Bytes = buf\n";
  111. code += "\trcv._tab.Pos = i\n";
  112. code += "}\n\n";
  113. }
  114. // Get the length of a vector.
  115. static void GetVectorLen(const StructDef &struct_def,
  116. const FieldDef &field,
  117. std::string *code_ptr) {
  118. std::string &code = *code_ptr;
  119. GenReceiver(struct_def, code_ptr);
  120. code += " " + MakeCamel(field.name) + "Length(";
  121. code += ") int " + OffsetPrefix(field);
  122. code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
  123. code += "\treturn 0\n}\n\n";
  124. }
  125. // Get the value of a struct's scalar.
  126. static void GetScalarFieldOfStruct(const StructDef &struct_def,
  127. const FieldDef &field,
  128. std::string *code_ptr) {
  129. std::string &code = *code_ptr;
  130. std::string getter = GenGetter(field.value.type);
  131. GenReceiver(struct_def, code_ptr);
  132. code += " " + MakeCamel(field.name);
  133. code += "() " + TypeName(field) + " { return " + getter;
  134. code += "(rcv._tab.Pos + flatbuffers.UOffsetT(";
  135. code += NumToString(field.value.offset) + ")) }\n";
  136. }
  137. // Get the value of a table's scalar.
  138. static void GetScalarFieldOfTable(const StructDef &struct_def,
  139. const FieldDef &field,
  140. std::string *code_ptr) {
  141. std::string &code = *code_ptr;
  142. std::string getter = GenGetter(field.value.type);
  143. GenReceiver(struct_def, code_ptr);
  144. code += " " + MakeCamel(field.name);
  145. code += "() " + TypeName(field) + " ";
  146. code += OffsetPrefix(field) + "\t\treturn " + getter;
  147. code += "(o + rcv._tab.Pos)\n\t}\n";
  148. code += "\treturn " + field.value.constant + "\n";
  149. code += "}\n\n";
  150. }
  151. // Get a struct by initializing an existing struct.
  152. // Specific to Struct.
  153. static void GetStructFieldOfStruct(const StructDef &struct_def,
  154. const FieldDef &field,
  155. std::string *code_ptr) {
  156. std::string &code = *code_ptr;
  157. GenReceiver(struct_def, code_ptr);
  158. code += " " + MakeCamel(field.name);
  159. code += "(obj *" + TypeName(field);
  160. code += ") *" + TypeName(field);
  161. code += " {\n";
  162. code += "\tif obj == nil {\n";
  163. code += "\t\tobj = new(" + TypeName(field) + ")\n";
  164. code += "\t}\n";
  165. code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos + ";
  166. code += NumToString(field.value.offset) + ")";
  167. code += "\n\treturn obj\n";
  168. code += "}\n";
  169. }
  170. // Get a struct by initializing an existing struct.
  171. // Specific to Table.
  172. static void GetStructFieldOfTable(const StructDef &struct_def,
  173. const FieldDef &field,
  174. std::string *code_ptr) {
  175. std::string &code = *code_ptr;
  176. GenReceiver(struct_def, code_ptr);
  177. code += " " + MakeCamel(field.name);
  178. code += "(obj *";
  179. code += TypeName(field);
  180. code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
  181. if (field.value.type.struct_def->fixed) {
  182. code += "\t\tx := o + rcv._tab.Pos\n";
  183. } else {
  184. code += "\t\tx := rcv._tab.Indirect(o + rcv._tab.Pos)\n";
  185. }
  186. code += "\t\tif obj == nil {\n";
  187. code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
  188. code += "\t\t}\n";
  189. code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
  190. code += "\t\treturn obj\n\t}\n\treturn nil\n";
  191. code += "}\n\n";
  192. }
  193. // Get the value of a string.
  194. static void GetStringField(const StructDef &struct_def,
  195. const FieldDef &field,
  196. std::string *code_ptr) {
  197. std::string &code = *code_ptr;
  198. GenReceiver(struct_def, code_ptr);
  199. code += " " + MakeCamel(field.name);
  200. code += "() " + TypeName(field) + " ";
  201. code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
  202. code += "(o + rcv._tab.Pos)\n\t}\n\treturn \"\"\n";
  203. code += "}\n\n";
  204. }
  205. // Get the value of a union from an object.
  206. static void GetUnionField(const StructDef &struct_def,
  207. const FieldDef &field,
  208. std::string *code_ptr) {
  209. std::string &code = *code_ptr;
  210. GenReceiver(struct_def, code_ptr);
  211. code += " " + MakeCamel(field.name) + "(";
  212. code += "obj " + TypeName(field) + ") bool ";
  213. code += OffsetPrefix(field);
  214. code += "\t\t" + GenGetter(field.value.type);
  215. code += "(obj, o)\n\t\treturn true\n\t}\n";
  216. code += "\treturn false\n";
  217. code += "}\n\n";
  218. }
  219. // Get the value of a vector's struct member.
  220. static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
  221. const FieldDef &field,
  222. std::string *code_ptr) {
  223. std::string &code = *code_ptr;
  224. auto vectortype = field.value.type.VectorType();
  225. GenReceiver(struct_def, code_ptr);
  226. code += " " + MakeCamel(field.name);
  227. code += "(obj *" + TypeName(field);
  228. code += ", j int) bool " + OffsetPrefix(field);
  229. code += "\t\tx := rcv._tab.Vector(o)\n";
  230. code += "\t\tx += flatbuffers.UOffsetT(j) * ";
  231. code += NumToString(InlineSize(vectortype)) + "\n";
  232. if (!(vectortype.struct_def->fixed)) {
  233. code += "\t\tx = rcv._tab.Indirect(x)\n";
  234. }
  235. code += "\tif obj == nil {\n";
  236. code += "\t\tobj = new(" + TypeName(field) + ")\n";
  237. code += "\t}\n";
  238. code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
  239. code += "\t\treturn true\n\t}\n";
  240. code += "\treturn false\n";
  241. code += "}\n\n";
  242. }
  243. // Get the value of a vector's non-struct member. Uses a named return
  244. // argument to conveniently set the zero value for the result.
  245. static void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
  246. const FieldDef &field,
  247. std::string *code_ptr) {
  248. std::string &code = *code_ptr;
  249. auto vectortype = field.value.type.VectorType();
  250. GenReceiver(struct_def, code_ptr);
  251. code += " " + MakeCamel(field.name);
  252. code += "(j int) " + TypeName(field) + " ";
  253. code += OffsetPrefix(field);
  254. code += "\t\ta := rcv._tab.Vector(o)\n";
  255. code += "\t\treturn " + GenGetter(field.value.type) + "(";
  256. code += "a + flatbuffers.UOffsetT(j * ";
  257. code += NumToString(InlineSize(vectortype)) + "))\n";
  258. code += "\t}\n";
  259. if (vectortype.base_type == BASE_TYPE_STRING) {
  260. code += "\treturn \"\"\n";
  261. } else {
  262. code += "\treturn 0\n";
  263. }
  264. code += "}\n\n";
  265. }
  266. // Begin the creator function signature.
  267. static void BeginBuilderArgs(const StructDef &struct_def,
  268. std::string *code_ptr) {
  269. std::string &code = *code_ptr;
  270. code += "\n";
  271. code += "func Create" + struct_def.name;
  272. code += "(builder *flatbuffers.Builder";
  273. }
  274. // Recursively generate arguments for a constructor, to deal with nested
  275. // structs.
  276. static void StructBuilderArgs(const StructDef &struct_def,
  277. const char *nameprefix,
  278. std::string *code_ptr) {
  279. for (auto it = struct_def.fields.vec.begin();
  280. it != struct_def.fields.vec.end();
  281. ++it) {
  282. auto &field = **it;
  283. if (IsStruct(field.value.type)) {
  284. // Generate arguments for a struct inside a struct. To ensure names
  285. // don't clash, and to make it obvious these arguments are constructing
  286. // a nested struct, prefix the name with the struct name.
  287. StructBuilderArgs(*field.value.type.struct_def,
  288. (field.value.type.struct_def->name + "_").c_str(),
  289. code_ptr);
  290. } else {
  291. std::string &code = *code_ptr;
  292. code += (std::string)", " + nameprefix;
  293. code += MakeCamel(field.name, false);
  294. code += " " + GenTypeBasic(field.value.type);
  295. }
  296. }
  297. }
  298. // End the creator function signature.
  299. static void EndBuilderArgs(std::string *code_ptr) {
  300. std::string &code = *code_ptr;
  301. code += ") flatbuffers.UOffsetT {\n";
  302. }
  303. // Recursively generate struct construction statements and instert manual
  304. // padding.
  305. static void StructBuilderBody(const StructDef &struct_def,
  306. const char *nameprefix,
  307. std::string *code_ptr) {
  308. std::string &code = *code_ptr;
  309. code += " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
  310. code += NumToString(struct_def.bytesize) + ")\n";
  311. for (auto it = struct_def.fields.vec.rbegin();
  312. it != struct_def.fields.vec.rend();
  313. ++it) {
  314. auto &field = **it;
  315. if (field.padding)
  316. code += " builder.Pad(" + NumToString(field.padding) + ")\n";
  317. if (IsStruct(field.value.type)) {
  318. StructBuilderBody(*field.value.type.struct_def,
  319. (field.value.type.struct_def->name + "_").c_str(),
  320. code_ptr);
  321. } else {
  322. code += " builder.Prepend" + GenMethod(field) + "(";
  323. code += nameprefix + MakeCamel(field.name, false) + ")\n";
  324. }
  325. }
  326. }
  327. static void EndBuilderBody(std::string *code_ptr) {
  328. std::string &code = *code_ptr;
  329. code += " return builder.Offset()\n";
  330. code += "}\n";
  331. }
  332. // Get the value of a table's starting offset.
  333. static void GetStartOfTable(const StructDef &struct_def,
  334. std::string *code_ptr) {
  335. std::string &code = *code_ptr;
  336. code += "func " + struct_def.name + "Start";
  337. code += "(builder *flatbuffers.Builder) { ";
  338. code += "builder.StartObject(";
  339. code += NumToString(struct_def.fields.vec.size());
  340. code += ") }\n";
  341. }
  342. // Set the value of a table's field.
  343. static void BuildFieldOfTable(const StructDef &struct_def,
  344. const FieldDef &field,
  345. const size_t offset,
  346. std::string *code_ptr) {
  347. std::string &code = *code_ptr;
  348. code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
  349. code += "(builder *flatbuffers.Builder, ";
  350. code += MakeCamel(field.name, false) + " ";
  351. if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
  352. code += "flatbuffers.UOffsetT";
  353. } else {
  354. code += GenTypeBasic(field.value.type);
  355. }
  356. code += ") ";
  357. code += "{ builder.Prepend";
  358. code += GenMethod(field) + "Slot(";
  359. code += NumToString(offset) + ", ";
  360. if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
  361. code += "flatbuffers.UOffsetT";
  362. code += "(";
  363. code += MakeCamel(field.name, false) + ")";
  364. } else {
  365. code += MakeCamel(field.name, false);
  366. }
  367. code += ", " + field.value.constant;
  368. code += ") }\n";
  369. }
  370. // Set the value of one of the members of a table's vector.
  371. static void BuildVectorOfTable(const StructDef &struct_def,
  372. const FieldDef &field,
  373. std::string *code_ptr) {
  374. std::string &code = *code_ptr;
  375. code += "func " + struct_def.name + "Start";
  376. code += MakeCamel(field.name);
  377. code += "Vector(builder *flatbuffers.Builder, numElems int) ";
  378. code += "flatbuffers.UOffsetT { return builder.StartVector(";
  379. auto vector_type = field.value.type.VectorType();
  380. auto alignment = InlineAlignment(vector_type);
  381. auto elem_size = InlineSize(vector_type);
  382. code += NumToString(elem_size);
  383. code += ", numElems, " + NumToString(alignment);
  384. code += ")\n}\n";
  385. }
  386. // Get the offset of the end of a table.
  387. static void GetEndOffsetOnTable(const StructDef &struct_def,
  388. std::string *code_ptr) {
  389. std::string &code = *code_ptr;
  390. code += "func " + struct_def.name + "End";
  391. code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
  392. code += "{ return builder.EndObject() }\n";
  393. }
  394. // Generate the receiver for function signatures.
  395. static void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
  396. std::string &code = *code_ptr;
  397. code += "func (rcv *" + struct_def.name + ")";
  398. }
  399. // Generate a struct field, conditioned on its child type(s).
  400. static void GenStructAccessor(const StructDef &struct_def,
  401. const FieldDef &field,
  402. std::string *code_ptr) {
  403. GenComment(field.doc_comment, code_ptr, "");
  404. if (IsScalar(field.value.type.base_type)) {
  405. if (struct_def.fixed) {
  406. GetScalarFieldOfStruct(struct_def, field, code_ptr);
  407. } else {
  408. GetScalarFieldOfTable(struct_def, field, code_ptr);
  409. }
  410. } else {
  411. switch (field.value.type.base_type) {
  412. case BASE_TYPE_STRUCT:
  413. if (struct_def.fixed) {
  414. GetStructFieldOfStruct(struct_def, field, code_ptr);
  415. } else {
  416. GetStructFieldOfTable(struct_def, field, code_ptr);
  417. }
  418. break;
  419. case BASE_TYPE_STRING:
  420. GetStringField(struct_def, field, code_ptr);
  421. break;
  422. case BASE_TYPE_VECTOR: {
  423. auto vectortype = field.value.type.VectorType();
  424. if (vectortype.base_type == BASE_TYPE_STRUCT) {
  425. GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
  426. } else {
  427. GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
  428. }
  429. break;
  430. }
  431. case BASE_TYPE_UNION:
  432. GetUnionField(struct_def, field, code_ptr);
  433. break;
  434. default:
  435. assert(0);
  436. }
  437. }
  438. if (field.value.type.base_type == BASE_TYPE_VECTOR) {
  439. GetVectorLen(struct_def, field, code_ptr);
  440. }
  441. }
  442. // Generate table constructors, conditioned on its members' types.
  443. static void GenTableBuilders(const StructDef &struct_def,
  444. std::string *code_ptr) {
  445. GetStartOfTable(struct_def, code_ptr);
  446. for (auto it = struct_def.fields.vec.begin();
  447. it != struct_def.fields.vec.end();
  448. ++it) {
  449. auto &field = **it;
  450. if (field.deprecated) continue;
  451. auto offset = it - struct_def.fields.vec.begin();
  452. BuildFieldOfTable(struct_def, field, offset, code_ptr);
  453. if (field.value.type.base_type == BASE_TYPE_VECTOR) {
  454. BuildVectorOfTable(struct_def, field, code_ptr);
  455. }
  456. }
  457. GetEndOffsetOnTable(struct_def, code_ptr);
  458. }
  459. // Generate struct or table methods.
  460. static void GenStruct(const StructDef &struct_def,
  461. std::string *code_ptr,
  462. StructDef *root_struct_def) {
  463. if (struct_def.generated) return;
  464. GenComment(struct_def.doc_comment, code_ptr);
  465. BeginClass(struct_def, code_ptr);
  466. if (&struct_def == root_struct_def) {
  467. // Generate a special accessor for the table that has been declared as
  468. // the root type.
  469. NewRootTypeFromBuffer(struct_def, code_ptr);
  470. }
  471. // Generate the Init method that sets the field in a pre-existing
  472. // accessor object. This is to allow object reuse.
  473. InitializeExisting(struct_def, code_ptr);
  474. for (auto it = struct_def.fields.vec.begin();
  475. it != struct_def.fields.vec.end();
  476. ++it) {
  477. auto &field = **it;
  478. if (field.deprecated) continue;
  479. GenStructAccessor(struct_def, field, code_ptr);
  480. }
  481. if (struct_def.fixed) {
  482. // create a struct constructor function
  483. GenStructBuilder(struct_def, code_ptr);
  484. } else {
  485. // Create a set of functions that allow table construction.
  486. GenTableBuilders(struct_def, code_ptr);
  487. }
  488. }
  489. // Generate enum declarations.
  490. static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
  491. if (enum_def.generated) return;
  492. GenComment(enum_def.doc_comment, code_ptr);
  493. BeginEnum(code_ptr);
  494. for (auto it = enum_def.vals.vec.begin();
  495. it != enum_def.vals.vec.end();
  496. ++it) {
  497. auto &ev = **it;
  498. GenComment(ev.doc_comment, code_ptr, "\t");
  499. EnumMember(enum_def, ev, code_ptr);
  500. }
  501. EndEnum(code_ptr);
  502. }
  503. // Returns the function name that is able to read a value of the given type.
  504. static std::string GenGetter(const Type &type) {
  505. switch (type.base_type) {
  506. case BASE_TYPE_STRING: return "rcv._tab.String";
  507. case BASE_TYPE_UNION: return "rcv._tab.Union";
  508. case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
  509. default:
  510. return "rcv._tab.Get" + MakeCamel(GenTypeGet(type));
  511. }
  512. }
  513. // Returns the method name for use with add/put calls.
  514. static std::string GenMethod(const FieldDef &field) {
  515. return IsScalar(field.value.type.base_type)
  516. ? MakeCamel(GenTypeBasic(field.value.type))
  517. : (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
  518. }
  519. // Save out the generated code for a Go Table type.
  520. static bool SaveType(const Parser &parser, const Definition &def,
  521. const std::string &classcode, const std::string &path,
  522. bool needs_imports) {
  523. if (!classcode.length()) return true;
  524. std::string namespace_name;
  525. std::string namespace_dir = path;
  526. auto &namespaces = parser.namespaces_.back()->components;
  527. for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
  528. if (namespace_name.length()) {
  529. namespace_name += ".";
  530. namespace_dir += PATH_SEPARATOR;
  531. }
  532. namespace_name = *it;
  533. namespace_dir += *it;
  534. mkdir(namespace_dir.c_str(), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
  535. }
  536. std::string code = "";
  537. BeginFile(namespace_name, needs_imports, &code);
  538. code += classcode;
  539. std::string filename = namespace_dir + PATH_SEPARATOR + def.name + ".go";
  540. return SaveFile(filename.c_str(), code, false);
  541. }
  542. static std::string GenTypeBasic(const Type &type) {
  543. static const char *ctypename[] = {
  544. #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) #GTYPE,
  545. FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
  546. #undef FLATBUFFERS_TD
  547. };
  548. return ctypename[type.base_type];
  549. }
  550. static std::string GenTypePointer(const Type &type) {
  551. switch (type.base_type) {
  552. case BASE_TYPE_STRING:
  553. return "string";
  554. case BASE_TYPE_VECTOR:
  555. return GenTypeGet(type.VectorType());
  556. case BASE_TYPE_STRUCT:
  557. return type.struct_def->name;
  558. case BASE_TYPE_UNION:
  559. // fall through
  560. default:
  561. return "*flatbuffers.Table";
  562. }
  563. }
  564. static std::string GenTypeGet(const Type &type) {
  565. return IsScalar(type.base_type)
  566. ? GenTypeBasic(type)
  567. : GenTypePointer(type);
  568. }
  569. static std::string TypeName(const FieldDef &field) {
  570. return GenTypeGet(field.value.type);
  571. }
  572. // Create a struct with a builder and the struct's arguments.
  573. static void GenStructBuilder(const StructDef &struct_def,
  574. std::string *code_ptr) {
  575. BeginBuilderArgs(struct_def, code_ptr);
  576. StructBuilderArgs(struct_def, "", code_ptr);
  577. EndBuilderArgs(code_ptr);
  578. StructBuilderBody(struct_def, "", code_ptr);
  579. EndBuilderBody(code_ptr);
  580. }
  581. } // namespace go
  582. bool GenerateGo(const Parser &parser,
  583. const std::string &path,
  584. const std::string & /*file_name*/,
  585. const GeneratorOptions & /*opts*/) {
  586. for (auto it = parser.enums_.vec.begin();
  587. it != parser.enums_.vec.end(); ++it) {
  588. std::string enumcode;
  589. go::GenEnum(**it, &enumcode);
  590. if (!go::SaveType(parser, **it, enumcode, path, false))
  591. return false;
  592. }
  593. for (auto it = parser.structs_.vec.begin();
  594. it != parser.structs_.vec.end(); ++it) {
  595. std::string declcode;
  596. go::GenStruct(**it, &declcode, parser.root_struct_def);
  597. if (!go::SaveType(parser, **it, declcode, path, true))
  598. return false;
  599. }
  600. return true;
  601. }
  602. } // namespace flatbuffers