idl_gen_go.cpp 26 KB

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