2 * Copyright 2014 Google Inc. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 // independent from idl_parser, since this code is not needed for most clients
22 #include "flatbuffers/code_generators.h"
23 #include "flatbuffers/flatbuffers.h"
24 #include "flatbuffers/idl.h"
25 #include "flatbuffers/util.h"
29 # define PATH_SEPARATOR "\\"
30 # define mkdir(n, m) _mkdir(n)
32 # include <sys/stat.h>
33 # define PATH_SEPARATOR "/"
36 namespace flatbuffers {
38 static std::string GeneratedFileName(const std::string &path,
39 const std::string &file_name) {
40 return path + file_name + "_generated.go";
45 // see https://golang.org/ref/spec#Keywords
46 static const char * const g_golang_keywords[] = {
47 "break", "default", "func", "interface", "select", "case", "defer",
48 "go", "map", "struct", "chan", "else", "goto", "package",
49 "switch", "const", "fallthrough", "if", "range", "type", "continue",
50 "for", "import", "return", "var",
53 static std::string GoIdentity(const std::string &name) {
55 i < sizeof(g_golang_keywords) / sizeof(g_golang_keywords[0]); i++) {
56 if (name == g_golang_keywords[i]) { return MakeCamel(name + "_", false); }
59 return MakeCamel(name, false);
62 class GoGenerator : public BaseGenerator {
64 GoGenerator(const Parser &parser, const std::string &path,
65 const std::string &file_name, const std::string &go_namespace)
66 : BaseGenerator(parser, path, file_name, "" /* not used*/,
68 cur_name_space_(nullptr) {
69 std::istringstream iss(go_namespace);
70 std::string component;
71 while (std::getline(iss, component, '.')) {
72 go_namespace_.components.push_back(component);
77 std::string one_file_code;
78 bool needs_imports = false;
79 for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
81 tracked_imported_namespaces_.clear();
82 needs_imports = false;
84 if ((*it)->is_union && parser_.opts.generate_object_based_api) {
85 GenNativeUnion(**it, &enumcode);
86 GenNativeUnionPack(**it, &enumcode);
87 GenNativeUnionUnPack(**it, &enumcode);
90 GenEnum(**it, &enumcode);
91 if (parser_.opts.one_file) {
92 one_file_code += enumcode;
94 if (!SaveType(**it, enumcode, needs_imports, true)) return false;
98 for (auto it = parser_.structs_.vec.begin();
99 it != parser_.structs_.vec.end(); ++it) {
100 tracked_imported_namespaces_.clear();
101 std::string declcode;
102 GenStruct(**it, &declcode);
103 if (parser_.opts.one_file) {
104 one_file_code += declcode;
106 if (!SaveType(**it, declcode, true, false)) return false;
110 if (parser_.opts.one_file) {
111 std::string code = "";
112 const bool is_enum = !parser_.enums_.vec.empty();
113 BeginFile(LastNamespacePart(go_namespace_), true, is_enum, &code);
114 code += one_file_code;
115 const std::string filename = GeneratedFileName(path_, file_name_);
116 return SaveFile(filename.c_str(), code, false);
123 Namespace go_namespace_;
124 Namespace *cur_name_space_;
126 struct NamespacePtrLess {
127 bool operator()(const Namespace *a, const Namespace *b) const {
131 std::set<const Namespace *, NamespacePtrLess> tracked_imported_namespaces_;
133 // Most field accessors need to retrieve and test the field offset first,
134 // this is the prefix code for that.
135 std::string OffsetPrefix(const FieldDef &field) {
136 return "{\n\to := flatbuffers.UOffsetT(rcv._tab.Offset(" +
137 NumToString(field.value.offset) + "))\n\tif o != 0 {\n";
140 // Begin a class declaration.
141 void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
142 std::string &code = *code_ptr;
144 code += "type " + struct_def.name + " struct {\n\t";
146 // _ is reserved in flatbuffers field names, so no chance of name conflict:
148 code += struct_def.fixed ? "flatbuffers.Struct" : "flatbuffers.Table";
152 // Construct the name of the type for this enum.
153 std::string GetEnumTypeName(const EnumDef &enum_def) {
154 return WrapInNameSpaceAndTrack(enum_def.defined_namespace, GoIdentity(enum_def.name));
157 // Create a type for the enum values.
158 void GenEnumType(const EnumDef &enum_def, std::string *code_ptr) {
159 std::string &code = *code_ptr;
160 code += "type " + GetEnumTypeName(enum_def) + " ";
161 code += GenTypeBasic(enum_def.underlying_type) + "\n\n";
164 // Begin enum code with a class declaration.
165 void BeginEnum(std::string *code_ptr) {
166 std::string &code = *code_ptr;
170 // A single enum member.
171 void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
172 size_t max_name_length, std::string *code_ptr) {
173 std::string &code = *code_ptr;
175 code += enum_def.name;
178 code += std::string(max_name_length - ev.name.length(), ' ');
179 code += GetEnumTypeName(enum_def);
181 code += enum_def.ToString(ev) + "\n";
185 void EndEnum(std::string *code_ptr) {
186 std::string &code = *code_ptr;
190 // Begin enum name map.
191 void BeginEnumNames(const EnumDef &enum_def, std::string *code_ptr) {
192 std::string &code = *code_ptr;
193 code += "var EnumNames";
194 code += enum_def.name;
195 code += " = map[" + GetEnumTypeName(enum_def) + "]string{\n";
198 // A single enum name member.
199 void EnumNameMember(const EnumDef &enum_def, const EnumVal &ev,
200 size_t max_name_length, std::string *code_ptr) {
201 std::string &code = *code_ptr;
203 code += enum_def.name;
206 code += std::string(max_name_length - ev.name.length(), ' ');
212 // End enum name map.
213 void EndEnumNames(std::string *code_ptr) {
214 std::string &code = *code_ptr;
218 // Generate String() method on enum type.
219 void EnumStringer(const EnumDef &enum_def, std::string *code_ptr) {
220 std::string &code = *code_ptr;
221 code += "func (v " + enum_def.name + ") String() string {\n";
222 code += "\tif s, ok := EnumNames" + enum_def.name + "[v]; ok {\n";
223 code += "\t\treturn s\n";
225 code += "\treturn \""+ enum_def.name;
226 code += "(\" + strconv.FormatInt(int64(v), 10) + \")\"\n";
230 // Begin enum value map.
231 void BeginEnumValues(const EnumDef &enum_def, std::string *code_ptr) {
232 std::string &code = *code_ptr;
233 code += "var EnumValues";
234 code += enum_def.name;
235 code += " = map[string]" + GetEnumTypeName(enum_def) + "{\n";
238 // A single enum value member.
239 void EnumValueMember(const EnumDef &enum_def, const EnumVal &ev,
240 size_t max_name_length, std::string *code_ptr) {
241 std::string &code = *code_ptr;
245 code += std::string(max_name_length - ev.name.length(), ' ');
246 code += enum_def.name;
251 // End enum value map.
252 void EndEnumValues(std::string *code_ptr) {
253 std::string &code = *code_ptr;
257 // Initialize a new struct or table from existing data.
258 void NewRootTypeFromBuffer(const StructDef &struct_def,
259 std::string *code_ptr) {
260 std::string &code = *code_ptr;
262 code += "func GetRootAs";
263 code += struct_def.name;
264 code += "(buf []byte, offset flatbuffers.UOffsetT) ";
265 code += "*" + struct_def.name + "";
267 code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
268 code += "\tx := &" + struct_def.name + "{}\n";
269 code += "\tx.Init(buf, n+offset)\n";
270 code += "\treturn x\n";
274 // Initialize an existing object with other data, to avoid an allocation.
275 void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
276 std::string &code = *code_ptr;
278 GenReceiver(struct_def, code_ptr);
279 code += " Init(buf []byte, i flatbuffers.UOffsetT) ";
281 code += "\trcv._tab.Bytes = buf\n";
282 code += "\trcv._tab.Pos = i\n";
286 // Implement the table accessor
287 void GenTableAccessor(const StructDef &struct_def, std::string *code_ptr) {
288 std::string &code = *code_ptr;
290 GenReceiver(struct_def, code_ptr);
291 code += " Table() flatbuffers.Table ";
294 if (struct_def.fixed) {
295 code += "\treturn rcv._tab.Table\n";
297 code += "\treturn rcv._tab\n";
302 // Get the length of a vector.
303 void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
304 std::string *code_ptr) {
305 std::string &code = *code_ptr;
307 GenReceiver(struct_def, code_ptr);
308 code += " " + MakeCamel(field.name) + "Length(";
309 code += ") int " + OffsetPrefix(field);
310 code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
311 code += "\treturn 0\n}\n\n";
314 // Get a [ubyte] vector as a byte slice.
315 void GetUByteSlice(const StructDef &struct_def, const FieldDef &field,
316 std::string *code_ptr) {
317 std::string &code = *code_ptr;
319 GenReceiver(struct_def, code_ptr);
320 code += " " + MakeCamel(field.name) + "Bytes(";
321 code += ") []byte " + OffsetPrefix(field);
322 code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
323 code += "\treturn nil\n}\n\n";
326 // Get the value of a struct's scalar.
327 void GetScalarFieldOfStruct(const StructDef &struct_def,
328 const FieldDef &field,
329 std::string *code_ptr) {
330 std::string &code = *code_ptr;
331 std::string getter = GenGetter(field.value.type);
332 GenReceiver(struct_def, code_ptr);
333 code += " " + MakeCamel(field.name);
334 code += "() " + TypeName(field) + " {\n";
335 code += "\treturn " + CastToEnum(
337 getter + "(rcv._tab.Pos + flatbuffers.UOffsetT(" +
338 NumToString(field.value.offset) + "))");
342 // Get the value of a table's scalar.
343 void GetScalarFieldOfTable(const StructDef &struct_def,
344 const FieldDef &field,
345 std::string *code_ptr) {
346 std::string &code = *code_ptr;
347 std::string getter = GenGetter(field.value.type);
348 GenReceiver(struct_def, code_ptr);
349 code += " " + MakeCamel(field.name);
350 code += "() " + TypeName(field) + " ";
351 code += OffsetPrefix(field) + "\t\treturn ";
352 code += CastToEnum(field.value.type, getter + "(o + rcv._tab.Pos)");
354 code += "\treturn " + GenConstant(field) + "\n";
358 // Get a struct by initializing an existing struct.
359 // Specific to Struct.
360 void GetStructFieldOfStruct(const StructDef &struct_def,
361 const FieldDef &field,
362 std::string *code_ptr) {
363 std::string &code = *code_ptr;
364 GenReceiver(struct_def, code_ptr);
365 code += " " + MakeCamel(field.name);
366 code += "(obj *" + TypeName(field);
367 code += ") *" + TypeName(field);
369 code += "\tif obj == nil {\n";
370 code += "\t\tobj = new(" + TypeName(field) + ")\n";
372 code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos+";
373 code += NumToString(field.value.offset) + ")";
374 code += "\n\treturn obj\n";
378 // Get a struct by initializing an existing struct.
379 // Specific to Table.
380 void GetStructFieldOfTable(const StructDef &struct_def,
381 const FieldDef &field,
382 std::string *code_ptr) {
383 std::string &code = *code_ptr;
384 GenReceiver(struct_def, code_ptr);
385 code += " " + MakeCamel(field.name);
387 code += TypeName(field);
388 code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
389 if (field.value.type.struct_def->fixed) {
390 code += "\t\tx := o + rcv._tab.Pos\n";
392 code += "\t\tx := rcv._tab.Indirect(o + rcv._tab.Pos)\n";
394 code += "\t\tif obj == nil {\n";
395 code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
397 code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
398 code += "\t\treturn obj\n\t}\n\treturn nil\n";
402 // Get the value of a string.
403 void GetStringField(const StructDef &struct_def,
404 const FieldDef &field,
405 std::string *code_ptr) {
406 std::string &code = *code_ptr;
407 GenReceiver(struct_def, code_ptr);
408 code += " " + MakeCamel(field.name);
409 code += "() " + TypeName(field) + " ";
410 code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
411 code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
415 // Get the value of a union from an object.
416 void GetUnionField(const StructDef &struct_def, const FieldDef &field,
417 std::string *code_ptr) {
418 std::string &code = *code_ptr;
419 GenReceiver(struct_def, code_ptr);
420 code += " " + MakeCamel(field.name) + "(";
421 code += "obj " + GenTypePointer(field.value.type) + ") bool ";
422 code += OffsetPrefix(field);
423 code += "\t\t" + GenGetter(field.value.type);
424 code += "(obj, o)\n\t\treturn true\n\t}\n";
425 code += "\treturn false\n";
429 // Get the value of a vector's struct member.
430 void GetMemberOfVectorOfStruct(const StructDef &struct_def,
431 const FieldDef &field,
432 std::string *code_ptr) {
433 std::string &code = *code_ptr;
434 auto vectortype = field.value.type.VectorType();
436 GenReceiver(struct_def, code_ptr);
437 code += " " + MakeCamel(field.name);
438 code += "(obj *" + TypeName(field);
439 code += ", j int) bool " + OffsetPrefix(field);
440 code += "\t\tx := rcv._tab.Vector(o)\n";
441 code += "\t\tx += flatbuffers.UOffsetT(j) * ";
442 code += NumToString(InlineSize(vectortype)) + "\n";
443 if (!(vectortype.struct_def->fixed)) {
444 code += "\t\tx = rcv._tab.Indirect(x)\n";
446 code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
447 code += "\t\treturn true\n\t}\n";
448 code += "\treturn false\n";
452 // Get the value of a vector's non-struct member.
453 void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
454 const FieldDef &field,
455 std::string *code_ptr) {
456 std::string &code = *code_ptr;
457 auto vectortype = field.value.type.VectorType();
459 GenReceiver(struct_def, code_ptr);
460 code += " " + MakeCamel(field.name);
461 code += "(j int) " + TypeName(field) + " ";
462 code += OffsetPrefix(field);
463 code += "\t\ta := rcv._tab.Vector(o)\n";
464 code += "\t\treturn " + CastToEnum(
466 GenGetter(field.value.type) + "(a + flatbuffers.UOffsetT(j*" +
467 NumToString(InlineSize(vectortype)) + "))");
469 if (vectortype.base_type == BASE_TYPE_STRING) {
470 code += "\treturn nil\n";
471 } else if (vectortype.base_type == BASE_TYPE_BOOL) {
472 code += "\treturn false\n";
474 code += "\treturn 0\n";
479 // Begin the creator function signature.
480 void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
481 std::string &code = *code_ptr;
483 if (code.substr(code.length() - 2) != "\n\n") {
484 // a previous mutate has not put an extra new line
487 code += "func Create" + struct_def.name;
488 code += "(builder *flatbuffers.Builder";
491 // Recursively generate arguments for a constructor, to deal with nested
493 void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
494 std::string *code_ptr) {
495 for (auto it = struct_def.fields.vec.begin();
496 it != struct_def.fields.vec.end(); ++it) {
498 if (IsStruct(field.value.type)) {
499 // Generate arguments for a struct inside a struct. To ensure names
500 // don't clash, and to make it obvious these arguments are constructing
501 // a nested struct, prefix the name with the field name.
502 StructBuilderArgs(*field.value.type.struct_def,
503 (nameprefix + (field.name + "_")).c_str(), code_ptr);
505 std::string &code = *code_ptr;
506 code += std::string(", ") + nameprefix;
507 code += GoIdentity(field.name);
508 code += " " + TypeName(field);
513 // End the creator function signature.
514 void EndBuilderArgs(std::string *code_ptr) {
515 std::string &code = *code_ptr;
516 code += ") flatbuffers.UOffsetT {\n";
519 // Recursively generate struct construction statements and instert manual
521 void StructBuilderBody(const StructDef &struct_def,
522 const char *nameprefix, std::string *code_ptr) {
523 std::string &code = *code_ptr;
524 code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", ";
525 code += NumToString(struct_def.bytesize) + ")\n";
526 for (auto it = struct_def.fields.vec.rbegin();
527 it != struct_def.fields.vec.rend(); ++it) {
530 code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n";
531 if (IsStruct(field.value.type)) {
532 StructBuilderBody(*field.value.type.struct_def,
533 (nameprefix + (field.name + "_")).c_str(), code_ptr);
535 code += "\tbuilder.Prepend" + GenMethod(field) + "(";
536 code += CastToBaseType(field.value.type, nameprefix + GoIdentity(field.name)) + ")\n";
541 void EndBuilderBody(std::string *code_ptr) {
542 std::string &code = *code_ptr;
543 code += "\treturn builder.Offset()\n";
547 // Get the value of a table's starting offset.
548 void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
549 std::string &code = *code_ptr;
550 code += "func " + struct_def.name + "Start";
551 code += "(builder *flatbuffers.Builder) {\n";
552 code += "\tbuilder.StartObject(";
553 code += NumToString(struct_def.fields.vec.size());
557 // Set the value of a table's field.
558 void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
559 const size_t offset, std::string *code_ptr) {
560 std::string &code = *code_ptr;
561 code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
562 code += "(builder *flatbuffers.Builder, ";
563 code += GoIdentity(field.name) + " ";
564 if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
565 code += "flatbuffers.UOffsetT";
567 code += TypeName(field);
570 code += "\tbuilder.Prepend";
571 code += GenMethod(field) + "Slot(";
572 code += NumToString(offset) + ", ";
573 if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
574 code += "flatbuffers.UOffsetT";
576 code += GoIdentity(field.name) + ")";
578 code += CastToBaseType(field.value.type, GoIdentity(field.name));
580 code += ", " + GenConstant(field);
584 // Set the value of one of the members of a table's vector.
585 void BuildVectorOfTable(const StructDef &struct_def,
586 const FieldDef &field, std::string *code_ptr) {
587 std::string &code = *code_ptr;
588 code += "func " + struct_def.name + "Start";
589 code += MakeCamel(field.name);
590 code += "Vector(builder *flatbuffers.Builder, numElems int) ";
591 code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
592 auto vector_type = field.value.type.VectorType();
593 auto alignment = InlineAlignment(vector_type);
594 auto elem_size = InlineSize(vector_type);
595 code += NumToString(elem_size);
596 code += ", numElems, " + NumToString(alignment);
600 // Get the offset of the end of a table.
601 void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
602 std::string &code = *code_ptr;
603 code += "func " + struct_def.name + "End";
604 code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
605 code += "{\n\treturn builder.EndObject()\n}\n";
608 // Generate the receiver for function signatures.
609 void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
610 std::string &code = *code_ptr;
611 code += "func (rcv *" + struct_def.name + ")";
614 // Generate a struct field getter, conditioned on its child type(s).
615 void GenStructAccessor(const StructDef &struct_def,
616 const FieldDef &field, std::string *code_ptr) {
617 GenComment(field.doc_comment, code_ptr, nullptr, "");
618 if (IsScalar(field.value.type.base_type)) {
619 if (struct_def.fixed) {
620 GetScalarFieldOfStruct(struct_def, field, code_ptr);
622 GetScalarFieldOfTable(struct_def, field, code_ptr);
625 switch (field.value.type.base_type) {
626 case BASE_TYPE_STRUCT:
627 if (struct_def.fixed) {
628 GetStructFieldOfStruct(struct_def, field, code_ptr);
630 GetStructFieldOfTable(struct_def, field, code_ptr);
633 case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break;
634 case BASE_TYPE_VECTOR: {
635 auto vectortype = field.value.type.VectorType();
636 if (vectortype.base_type == BASE_TYPE_STRUCT) {
637 GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
639 GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
643 case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
644 default: FLATBUFFERS_ASSERT(0);
647 if (field.value.type.base_type == BASE_TYPE_VECTOR) {
648 GetVectorLen(struct_def, field, code_ptr);
649 if (field.value.type.element == BASE_TYPE_UCHAR) {
650 GetUByteSlice(struct_def, field, code_ptr);
655 // Mutate the value of a struct's scalar.
656 void MutateScalarFieldOfStruct(const StructDef &struct_def,
657 const FieldDef &field,
658 std::string *code_ptr) {
659 std::string &code = *code_ptr;
660 std::string type = MakeCamel(GenTypeBasic(field.value.type));
661 std::string setter = "rcv._tab.Mutate" + type;
662 GenReceiver(struct_def, code_ptr);
663 code += " Mutate" + MakeCamel(field.name);
664 code += "(n " + TypeName(field) + ") bool {\n\treturn " + setter;
665 code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
666 code += NumToString(field.value.offset) + "), ";
667 code += CastToBaseType(field.value.type, "n") + ")\n}\n\n";
670 // Mutate the value of a table's scalar.
671 void MutateScalarFieldOfTable(const StructDef &struct_def,
672 const FieldDef &field,
673 std::string *code_ptr) {
674 std::string &code = *code_ptr;
675 std::string type = MakeCamel(GenTypeBasic(field.value.type));
676 std::string setter = "rcv._tab.Mutate" + type + "Slot";
677 GenReceiver(struct_def, code_ptr);
678 code += " Mutate" + MakeCamel(field.name);
679 code += "(n " + TypeName(field) + ") bool {\n\treturn ";
680 code += setter + "(" + NumToString(field.value.offset) + ", ";
681 code += CastToBaseType(field.value.type, "n") + ")\n";
685 // Mutate an element of a vector of scalars.
686 void MutateElementOfVectorOfNonStruct(const StructDef &struct_def,
687 const FieldDef &field,
688 std::string *code_ptr) {
689 std::string &code = *code_ptr;
690 auto vectortype = field.value.type.VectorType();
691 std::string type = MakeCamel(GenTypeBasic(vectortype));
692 std::string setter = "rcv._tab.Mutate" + type;
693 GenReceiver(struct_def, code_ptr);
694 code += " Mutate" + MakeCamel(field.name);
695 code += "(j int, n " + TypeName(field) + ") bool ";
696 code += OffsetPrefix(field);
697 code += "\t\ta := rcv._tab.Vector(o)\n";
698 code += "\t\treturn " + setter + "(";
699 code += "a+flatbuffers.UOffsetT(j*";
700 code += NumToString(InlineSize(vectortype)) + "), ";
701 code += CastToBaseType(vectortype, "n") + ")\n";
703 code += "\treturn false\n";
707 // Generate a struct field setter, conditioned on its child type(s).
708 void GenStructMutator(const StructDef &struct_def, const FieldDef &field,
709 std::string *code_ptr) {
710 GenComment(field.doc_comment, code_ptr, nullptr, "");
711 if (IsScalar(field.value.type.base_type)) {
712 if (struct_def.fixed) {
713 MutateScalarFieldOfStruct(struct_def, field, code_ptr);
715 MutateScalarFieldOfTable(struct_def, field, code_ptr);
717 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
718 if (IsScalar(field.value.type.element)) {
719 MutateElementOfVectorOfNonStruct(struct_def, field, code_ptr);
724 // Generate table constructors, conditioned on its members' types.
725 void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
726 GetStartOfTable(struct_def, code_ptr);
728 for (auto it = struct_def.fields.vec.begin();
729 it != struct_def.fields.vec.end(); ++it) {
731 if (field.deprecated) continue;
733 auto offset = it - struct_def.fields.vec.begin();
734 BuildFieldOfTable(struct_def, field, offset, code_ptr);
735 if (field.value.type.base_type == BASE_TYPE_VECTOR) {
736 BuildVectorOfTable(struct_def, field, code_ptr);
740 GetEndOffsetOnTable(struct_def, code_ptr);
743 // Generate struct or table methods.
744 void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
745 if (struct_def.generated) return;
747 cur_name_space_ = struct_def.defined_namespace;
749 GenComment(struct_def.doc_comment, code_ptr, nullptr);
750 if (parser_.opts.generate_object_based_api) {
751 GenNativeStruct(struct_def, code_ptr);
753 BeginClass(struct_def, code_ptr);
754 if (!struct_def.fixed) {
755 // Generate a special accessor for the table that has been declared as
757 NewRootTypeFromBuffer(struct_def, code_ptr);
759 // Generate the Init method that sets the field in a pre-existing
760 // accessor object. This is to allow object reuse.
761 InitializeExisting(struct_def, code_ptr);
762 // Generate _tab accessor
763 GenTableAccessor(struct_def, code_ptr);
765 // Generate struct fields accessors
766 for (auto it = struct_def.fields.vec.begin();
767 it != struct_def.fields.vec.end(); ++it) {
769 if (field.deprecated) continue;
771 GenStructAccessor(struct_def, field, code_ptr);
772 GenStructMutator(struct_def, field, code_ptr);
776 if (struct_def.fixed) {
777 // create a struct constructor function
778 GenStructBuilder(struct_def, code_ptr);
780 // Create a set of functions that allow table construction.
781 GenTableBuilders(struct_def, code_ptr);
785 void GenNativeStruct(const StructDef &struct_def, std::string *code_ptr) {
786 std::string &code = *code_ptr;
788 code += "type " + NativeName(struct_def) + " struct {\n";
789 for (auto it = struct_def.fields.vec.begin();
790 it != struct_def.fields.vec.end(); ++it) {
791 const FieldDef &field = **it;
792 if (field.deprecated) continue;
793 if (IsScalar(field.value.type.base_type) &&
794 field.value.type.enum_def != nullptr &&
795 field.value.type.enum_def->is_union)
797 code += "\t" + MakeCamel(field.name) + " " +
798 NativeType(field.value.type) + "\n";
802 if (!struct_def.fixed) {
803 GenNativeTablePack(struct_def, code_ptr);
804 GenNativeTableUnPack(struct_def, code_ptr);
806 GenNativeStructPack(struct_def, code_ptr);
807 GenNativeStructUnPack(struct_def, code_ptr);
811 void GenNativeUnion(const EnumDef &enum_def, std::string *code_ptr) {
812 std::string &code = *code_ptr;
813 code += "type " + NativeName(enum_def) + " struct {\n";
814 code += "\tType " + enum_def.name + "\n";
815 code += "\tValue interface{}\n";
819 void GenNativeUnionPack(const EnumDef &enum_def, std::string *code_ptr) {
820 std::string &code = *code_ptr;
821 code += "func " + enum_def.name + "Pack(builder *flatbuffers.Builder, t *" +
822 NativeName(enum_def) + ") flatbuffers.UOffsetT {\n";
823 code += "\tif t == nil {\n\t\treturn 0\n\t}\n";
825 code += "\tswitch t.Type {\n";
826 for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end();
828 const EnumVal &ev = **it2;
829 if (ev.IsZero()) continue;
830 code += "\tcase " + enum_def.name + ev.name + ":\n";
831 code += "\t\treturn " +
832 WrapInNameSpaceAndTrack(*ev.union_type.struct_def) +
833 "Pack(builder, t.Value.(" + NativeType(ev.union_type) + "))\n";
836 code += "\treturn 0\n";
840 void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) {
841 std::string &code = *code_ptr;
843 code += "func " + enum_def.name + "UnPack(t " + enum_def.name +
844 ", table flatbuffers.Table) *" + NativeName(enum_def) + " {\n";
845 code += "\tswitch t {\n";
847 for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end();
849 const EnumVal &ev = **it2;
850 if (ev.IsZero()) continue;
851 code += "\tcase " + enum_def.name + ev.name + ":\n";
852 code += "\t\tx := " + ev.union_type.struct_def->name + "{_tab: table}\n";
854 code += "\t\treturn &" +
855 WrapInNameSpaceAndTrack(enum_def.defined_namespace,
856 NativeName(enum_def)) +
857 "{ Type: " + enum_def.name + ev.name + ", Value: x.UnPack() }\n";
860 code += "\treturn nil\n";
864 void GenNativeTablePack(const StructDef &struct_def, std::string *code_ptr) {
865 std::string &code = *code_ptr;
867 code += "func " + struct_def.name +
868 "Pack(builder *flatbuffers.Builder, t *" + NativeName(struct_def) +
869 ") flatbuffers.UOffsetT {\n";
870 code += "\tif t == nil { return 0 }\n";
871 for (auto it = struct_def.fields.vec.begin();
872 it != struct_def.fields.vec.end(); ++it) {
873 const FieldDef &field = **it;
874 if (field.deprecated) continue;
875 if (IsScalar(field.value.type.base_type)) continue;
877 std::string offset = MakeCamel(field.name, false) + "Offset";
879 if (field.value.type.base_type == BASE_TYPE_STRING) {
880 code += "\t" + offset + " := builder.CreateString(t." +
881 MakeCamel(field.name) + ")\n";
882 } else if (field.value.type.base_type == BASE_TYPE_VECTOR &&
883 field.value.type.element == BASE_TYPE_UCHAR &&
884 field.value.type.enum_def == nullptr) {
885 code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
886 code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
887 code += "\t\t" + offset + " = builder.CreateByteString(t." +
888 MakeCamel(field.name) + ")\n";
890 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
891 code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
892 code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
893 std::string length = MakeCamel(field.name, false) + "Length";
894 std::string offsets = MakeCamel(field.name, false) + "Offsets";
895 code += "\t\t" + length + " := len(t." + MakeCamel(field.name) + ")\n";
896 if (field.value.type.element == BASE_TYPE_STRING) {
897 code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " +
899 code += "\t\tfor j := 0; j < " + length + "; j++ {\n";
900 code += "\t\t\t" + offsets + "[j] = builder.CreateString(t." +
901 MakeCamel(field.name) + "[j])\n";
903 } else if (field.value.type.element == BASE_TYPE_STRUCT &&
904 !field.value.type.struct_def->fixed) {
905 code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " +
907 code += "\t\tfor j := 0; j < " + length + "; j++ {\n";
908 code += "\t\t\t" + offsets + "[j] = " +
909 WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
910 "Pack(builder, t." + MakeCamel(field.name) + "[j])\n";
913 code += "\t\t" + struct_def.name + "Start" + MakeCamel(field.name) +
914 "Vector(builder, " + length + ")\n";
915 code += "\t\tfor j := " + length + " - 1; j >= 0; j-- {\n";
916 if (IsScalar(field.value.type.element)) {
917 code += "\t\t\tbuilder.Prepend" +
918 MakeCamel(GenTypeBasic(field.value.type.VectorType())) + "(" +
920 field.value.type.VectorType(),
921 "t." + MakeCamel(field.name) + "[j]") + ")\n";
922 } else if (field.value.type.element == BASE_TYPE_STRUCT &&
923 field.value.type.struct_def->fixed) {
925 WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
926 "Pack(builder, t." + MakeCamel(field.name) + "[j])\n";
928 code += "\t\t\tbuilder.PrependUOffsetT(" + offsets + "[j])\n";
931 code += "\t\t" + offset + " = builder.EndVector(" + length + ")\n";
933 } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
934 if (field.value.type.struct_def->fixed) continue;
935 code += "\t" + offset +
936 " := " + WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
937 "Pack(builder, t." + MakeCamel(field.name) + ")\n";
938 } else if (field.value.type.base_type == BASE_TYPE_UNION) {
939 code += "\t" + offset +
940 " := " + WrapInNameSpaceAndTrack(*field.value.type.enum_def) +
941 "Pack(builder, t." + MakeCamel(field.name) + ")\n";
944 FLATBUFFERS_ASSERT(0);
947 code += "\t" + struct_def.name + "Start(builder)\n";
948 for (auto it = struct_def.fields.vec.begin();
949 it != struct_def.fields.vec.end(); ++it) {
950 const FieldDef &field = **it;
951 if (field.deprecated) continue;
953 std::string offset = MakeCamel(field.name, false) + "Offset";
954 if (IsScalar(field.value.type.base_type)) {
955 if (field.value.type.enum_def == nullptr ||
956 !field.value.type.enum_def->is_union) {
957 code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
958 "(builder, t." + MakeCamel(field.name) + ")\n";
961 if (field.value.type.base_type == BASE_TYPE_STRUCT &&
962 field.value.type.struct_def->fixed) {
963 code += "\t" + offset + " := " +
964 WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
965 "Pack(builder, t." + MakeCamel(field.name) + ")\n";
966 } else if (field.value.type.enum_def != nullptr &&
967 field.value.type.enum_def->is_union) {
968 code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
969 code += "\t\t" + struct_def.name + "Add" +
970 MakeCamel(field.name + UnionTypeFieldSuffix()) +
971 "(builder, t." + MakeCamel(field.name) + ".Type)\n";
974 code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
975 "(builder, " + offset + ")\n";
978 code += "\treturn " + struct_def.name + "End(builder)\n";
982 void GenNativeTableUnPack(
983 const StructDef &struct_def, std::string *code_ptr) {
984 std::string &code = *code_ptr;
986 code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
987 NativeName(struct_def) + ") {\n";
988 for (auto it = struct_def.fields.vec.begin();
989 it != struct_def.fields.vec.end(); ++it) {
990 const FieldDef &field = **it;
991 if (field.deprecated) continue;
992 std::string field_name_camel = MakeCamel(field.name);
993 std::string length = MakeCamel(field.name, false) + "Length";
994 if (IsScalar(field.value.type.base_type)) {
995 if (field.value.type.enum_def != nullptr &&
996 field.value.type.enum_def->is_union)
998 code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
1000 } else if (field.value.type.base_type == BASE_TYPE_STRING) {
1001 code += "\tt." + field_name_camel + " = string(rcv." +
1002 field_name_camel + "())\n";
1003 } else if (field.value.type.base_type == BASE_TYPE_VECTOR &&
1004 field.value.type.element == BASE_TYPE_UCHAR &&
1005 field.value.type.enum_def == nullptr) {
1006 code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
1008 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
1009 code += "\t" + length + " := rcv." + field_name_camel + "Length()\n";
1010 code += "\tt." + field_name_camel + " = make(" +
1011 NativeType(field.value.type) + ", " + length + ")\n";
1012 code += "\tfor j := 0; j < " + length + "; j++ {\n";
1013 if (field.value.type.element == BASE_TYPE_STRUCT) {
1014 code += "\t\tx := " + field.value.type.struct_def->name + "{}\n";
1015 code += "\t\trcv." + field_name_camel + "(&x, j)\n";
1017 code += "\t\tt." + field_name_camel + "[j] = ";
1018 if (IsScalar(field.value.type.element)) {
1019 code += "rcv." + field_name_camel + "(j)";
1020 } else if (field.value.type.element == BASE_TYPE_STRING) {
1021 code += "string(rcv." + field_name_camel + "(j))";
1022 } else if (field.value.type.element == BASE_TYPE_STRUCT) {
1023 code += "x.UnPack()";
1025 // TODO(iceboy): Support vector of unions.
1026 FLATBUFFERS_ASSERT(0);
1030 } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1031 code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
1033 } else if (field.value.type.base_type == BASE_TYPE_UNION) {
1034 const EnumDef &enum_def = *field.value.type.enum_def;
1035 std::string field_table = MakeCamel(field.name, false) + "Table";
1036 code += "\t" + field_table + " := flatbuffers.Table{}\n";
1038 "\tif rcv." + MakeCamel(field.name) + "(&" + field_table + ") {\n";
1039 code += "\t\tt." + field_name_camel + " = " + enum_def.name +
1040 "UnPack(rcv." + MakeCamel(field.name + UnionTypeFieldSuffix()) +
1041 "(), " + field_table + ")\n";
1044 FLATBUFFERS_ASSERT(0);
1049 code += "func (rcv *" + struct_def.name + ") UnPack() *" +
1050 NativeName(struct_def) + " {\n";
1051 code += "\tif rcv == nil { return nil }\n";
1052 code += "\tt := &" + NativeName(struct_def) + "{}\n";
1053 code += "\trcv.UnPackTo(t)\n";
1054 code += "\treturn t\n";
1058 void GenNativeStructPack(const StructDef &struct_def, std::string *code_ptr) {
1059 std::string &code = *code_ptr;
1061 code += "func " + struct_def.name +
1062 "Pack(builder *flatbuffers.Builder, t *" + NativeName(struct_def) +
1063 ") flatbuffers.UOffsetT {\n";
1064 code += "\tif t == nil { return 0 }\n";
1065 code += "\treturn Create" + struct_def.name + "(builder";
1066 StructPackArgs(struct_def, "", code_ptr);
1071 void StructPackArgs(const StructDef &struct_def, const char *nameprefix,
1072 std::string *code_ptr) {
1073 std::string &code = *code_ptr;
1074 for (auto it = struct_def.fields.vec.begin();
1075 it != struct_def.fields.vec.end(); ++it) {
1076 const FieldDef &field = **it;
1077 if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1078 StructPackArgs(*field.value.type.struct_def,
1079 (nameprefix + MakeCamel(field.name) + ".").c_str(),
1082 code += std::string(", t.") + nameprefix + MakeCamel(field.name);
1087 void GenNativeStructUnPack(
1088 const StructDef &struct_def, std::string *code_ptr) {
1089 std::string &code = *code_ptr;
1091 code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
1092 NativeName(struct_def) + ") {\n";
1093 for (auto it = struct_def.fields.vec.begin();
1094 it != struct_def.fields.vec.end(); ++it) {
1095 const FieldDef &field = **it;
1096 if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1097 code += "\tt." + MakeCamel(field.name) + " = rcv." +
1098 MakeCamel(field.name) + "(nil).UnPack()\n";
1100 code += "\tt." + MakeCamel(field.name) + " = rcv." +
1101 MakeCamel(field.name) + "()\n";
1106 code += "func (rcv *" + struct_def.name + ") UnPack() *" +
1107 NativeName(struct_def) + " {\n";
1108 code += "\tif rcv == nil { return nil }\n";
1109 code += "\tt := &" + NativeName(struct_def) + "{}\n";
1110 code += "\trcv.UnPackTo(t)\n";
1111 code += "\treturn t\n";
1115 // Generate enum declarations.
1116 void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
1117 if (enum_def.generated) return;
1119 auto max_name_length = MaxNameLength(enum_def);
1120 cur_name_space_ = enum_def.defined_namespace;
1122 GenComment(enum_def.doc_comment, code_ptr, nullptr);
1123 GenEnumType(enum_def, code_ptr);
1124 BeginEnum(code_ptr);
1125 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1126 const EnumVal &ev = **it;
1127 GenComment(ev.doc_comment, code_ptr, nullptr, "\t");
1128 EnumMember(enum_def, ev, max_name_length, code_ptr);
1132 BeginEnumNames(enum_def, code_ptr);
1133 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1134 const EnumVal &ev = **it;
1135 EnumNameMember(enum_def, ev, max_name_length, code_ptr);
1137 EndEnumNames(code_ptr);
1139 BeginEnumValues(enum_def, code_ptr);
1140 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1143 EnumValueMember(enum_def, ev, max_name_length, code_ptr);
1145 EndEnumValues(code_ptr);
1147 EnumStringer(enum_def, code_ptr);
1150 // Returns the function name that is able to read a value of the given type.
1151 std::string GenGetter(const Type &type) {
1152 switch (type.base_type) {
1153 case BASE_TYPE_STRING: return "rcv._tab.ByteVector";
1154 case BASE_TYPE_UNION: return "rcv._tab.Union";
1155 case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
1156 default: return "rcv._tab.Get" + MakeCamel(GenTypeBasic(type));
1160 // Returns the method name for use with add/put calls.
1161 std::string GenMethod(const FieldDef &field) {
1162 return IsScalar(field.value.type.base_type)
1163 ? MakeCamel(GenTypeBasic(field.value.type))
1164 : (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
1167 std::string GenTypeBasic(const Type &type) {
1168 static const char *ctypename[] = {
1170 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
1171 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
1173 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
1174 #undef FLATBUFFERS_TD
1177 return ctypename[type.base_type];
1180 std::string GenTypePointer(const Type &type) {
1181 switch (type.base_type) {
1182 case BASE_TYPE_STRING: return "[]byte";
1183 case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
1184 case BASE_TYPE_STRUCT: return WrapInNameSpaceAndTrack(*type.struct_def);
1185 case BASE_TYPE_UNION:
1187 default: return "*flatbuffers.Table";
1191 std::string GenTypeGet(const Type &type) {
1192 if (type.enum_def != nullptr) {
1193 return GetEnumTypeName(*type.enum_def);
1195 return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
1198 std::string TypeName(const FieldDef &field) {
1199 return GenTypeGet(field.value.type);
1202 // If type is an enum, returns value with a cast to the enum type, otherwise
1203 // returns value as-is.
1204 std::string CastToEnum(const Type &type, std::string value) {
1205 if (type.enum_def == nullptr) {
1208 return GenTypeGet(type) + "(" + value + ")";
1212 // If type is an enum, returns value with a cast to the enum base type,
1213 // otherwise returns value as-is.
1214 std::string CastToBaseType(const Type &type, std::string value) {
1215 if (type.enum_def == nullptr) {
1218 return GenTypeBasic(type) + "(" + value + ")";
1222 std::string GenConstant(const FieldDef &field) {
1223 switch (field.value.type.base_type) {
1224 case BASE_TYPE_BOOL: return field.value.constant == "0" ? "false" : "true";
1225 default: return field.value.constant;
1229 std::string NativeName(const StructDef &struct_def) {
1230 return parser_.opts.object_prefix + struct_def.name +
1231 parser_.opts.object_suffix;
1234 std::string NativeName(const EnumDef &enum_def) {
1235 return parser_.opts.object_prefix + enum_def.name +
1236 parser_.opts.object_suffix;
1239 std::string NativeType(const Type &type) {
1240 if (IsScalar(type.base_type)) {
1241 if (type.enum_def == nullptr) {
1242 return GenTypeBasic(type);
1244 return GetEnumTypeName(*type.enum_def);
1246 } else if (type.base_type == BASE_TYPE_STRING) {
1248 } else if (type.base_type == BASE_TYPE_VECTOR) {
1249 return "[]" + NativeType(type.VectorType());
1250 } else if (type.base_type == BASE_TYPE_STRUCT) {
1251 return "*" + WrapInNameSpaceAndTrack(
1252 type.struct_def->defined_namespace, NativeName(*type.struct_def));
1253 } else if (type.base_type == BASE_TYPE_UNION) {
1254 return "*" + WrapInNameSpaceAndTrack(
1255 type.enum_def->defined_namespace, NativeName(*type.enum_def));
1257 FLATBUFFERS_ASSERT(0);
1258 return std::string();
1261 // Create a struct with a builder and the struct's arguments.
1262 void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
1263 BeginBuilderArgs(struct_def, code_ptr);
1264 StructBuilderArgs(struct_def, "", code_ptr);
1265 EndBuilderArgs(code_ptr);
1267 StructBuilderBody(struct_def, "", code_ptr);
1268 EndBuilderBody(code_ptr);
1270 // Begin by declaring namespace and imports.
1271 void BeginFile(const std::string &name_space_name, const bool needs_imports,
1272 const bool is_enum, std::string *code_ptr) {
1273 std::string &code = *code_ptr;
1274 code = code + "// Code generated by the FlatBuffers compiler. DO NOT EDIT.\n\n";
1275 code += "package " + name_space_name + "\n\n";
1276 if (needs_imports) {
1277 code += "import (\n";
1279 code += "\t\"strconv\"\n\n";
1281 if (!parser_.opts.go_import.empty()) {
1282 code += "\tflatbuffers \"" + parser_.opts.go_import + "\"\n";
1284 code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
1286 if (tracked_imported_namespaces_.size() > 0) {
1288 for (auto it = tracked_imported_namespaces_.begin();
1289 it != tracked_imported_namespaces_.end();
1291 code += "\t" + NamespaceImportName(*it) + " \"" + \
1292 NamespaceImportPath(*it) + "\"\n";
1298 code += "import \"strconv\"\n\n";
1303 // Save out the generated code for a Go Table type.
1304 bool SaveType(const Definition &def, const std::string &classcode,
1305 const bool needs_imports, const bool is_enum) {
1306 if (!classcode.length()) return true;
1308 Namespace &ns = go_namespace_.components.empty() ? *def.defined_namespace
1310 std::string code = "";
1311 BeginFile(LastNamespacePart(ns), needs_imports, is_enum, &code);
1313 // Strip extra newlines at end of file to make it gofmt-clean.
1314 while (code.length() > 2 && code.substr(code.length() - 2) == "\n\n") {
1317 std::string filename = NamespaceDir(ns) + def.name + ".go";
1318 return SaveFile(filename.c_str(), code, false);
1321 // Create the full name of the imported namespace (format: A__B__C).
1322 std::string NamespaceImportName(const Namespace *ns) {
1324 for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
1325 if (s.size() == 0) {
1334 // Create the full path for the imported namespace (format: A/B/C).
1335 std::string NamespaceImportPath(const Namespace *ns) {
1337 for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
1338 if (s.size() == 0) {
1347 // Ensure that a type is prefixed with its go package import name if it is
1348 // used outside of its namespace.
1349 std::string WrapInNameSpaceAndTrack(const Namespace *ns,
1350 const std::string &name) {
1351 if (CurrentNameSpace() == ns) return name;
1353 tracked_imported_namespaces_.insert(ns);
1355 std::string import_name = NamespaceImportName(ns);
1356 return import_name + "." + name;
1359 std::string WrapInNameSpaceAndTrack(const Definition &def) {
1360 return WrapInNameSpaceAndTrack(def.defined_namespace, def.name);
1363 const Namespace *CurrentNameSpace() const { return cur_name_space_; }
1365 static size_t MaxNameLength(const EnumDef &enum_def) {
1367 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
1369 max = std::max((*it)->name.length(), max);
1376 bool GenerateGo(const Parser &parser, const std::string &path,
1377 const std::string &file_name) {
1378 go::GoGenerator generator(parser, path, file_name, parser.opts.go_namespace);
1379 return generator.generate();
1382 } // namespace flatbuffers