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