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