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,
155 GoIdentity(enum_def.name));
158 // Create a type for the enum values.
159 void GenEnumType(const EnumDef &enum_def, std::string *code_ptr) {
160 std::string &code = *code_ptr;
161 code += "type " + GetEnumTypeName(enum_def) + " ";
162 code += GenTypeBasic(enum_def.underlying_type) + "\n\n";
165 // Begin enum code with a class declaration.
166 void BeginEnum(std::string *code_ptr) {
167 std::string &code = *code_ptr;
171 // A single enum member.
172 void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
173 size_t max_name_length, std::string *code_ptr) {
174 std::string &code = *code_ptr;
176 code += enum_def.name;
179 code += std::string(max_name_length - ev.name.length(), ' ');
180 code += GetEnumTypeName(enum_def);
182 code += enum_def.ToString(ev) + "\n";
186 void EndEnum(std::string *code_ptr) {
187 std::string &code = *code_ptr;
191 // Begin enum name map.
192 void BeginEnumNames(const EnumDef &enum_def, std::string *code_ptr) {
193 std::string &code = *code_ptr;
194 code += "var EnumNames";
195 code += enum_def.name;
196 code += " = map[" + GetEnumTypeName(enum_def) + "]string{\n";
199 // A single enum name member.
200 void EnumNameMember(const EnumDef &enum_def, const EnumVal &ev,
201 size_t max_name_length, std::string *code_ptr) {
202 std::string &code = *code_ptr;
204 code += enum_def.name;
207 code += std::string(max_name_length - ev.name.length(), ' ');
213 // End enum name map.
214 void EndEnumNames(std::string *code_ptr) {
215 std::string &code = *code_ptr;
219 // Generate String() method on enum type.
220 void EnumStringer(const EnumDef &enum_def, std::string *code_ptr) {
221 std::string &code = *code_ptr;
222 code += "func (v " + enum_def.name + ") String() string {\n";
223 code += "\tif s, ok := EnumNames" + enum_def.name + "[v]; ok {\n";
224 code += "\t\treturn s\n";
226 code += "\treturn \"" + enum_def.name;
227 code += "(\" + strconv.FormatInt(int64(v), 10) + \")\"\n";
231 // Begin enum value map.
232 void BeginEnumValues(const EnumDef &enum_def, std::string *code_ptr) {
233 std::string &code = *code_ptr;
234 code += "var EnumValues";
235 code += enum_def.name;
236 code += " = map[string]" + GetEnumTypeName(enum_def) + "{\n";
239 // A single enum value member.
240 void EnumValueMember(const EnumDef &enum_def, const EnumVal &ev,
241 size_t max_name_length, std::string *code_ptr) {
242 std::string &code = *code_ptr;
246 code += std::string(max_name_length - ev.name.length(), ' ');
247 code += enum_def.name;
252 // End enum value map.
253 void EndEnumValues(std::string *code_ptr) {
254 std::string &code = *code_ptr;
258 // Initialize a new struct or table from existing data.
259 void NewRootTypeFromBuffer(const StructDef &struct_def,
260 std::string *code_ptr) {
261 std::string &code = *code_ptr;
263 code += "func GetRootAs";
264 code += struct_def.name;
265 code += "(buf []byte, offset flatbuffers.UOffsetT) ";
266 code += "*" + struct_def.name + "";
268 code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
269 code += "\tx := &" + struct_def.name + "{}\n";
270 code += "\tx.Init(buf, n+offset)\n";
271 code += "\treturn x\n";
275 // Initialize an existing object with other data, to avoid an allocation.
276 void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
277 std::string &code = *code_ptr;
279 GenReceiver(struct_def, code_ptr);
280 code += " Init(buf []byte, i flatbuffers.UOffsetT) ";
282 code += "\trcv._tab.Bytes = buf\n";
283 code += "\trcv._tab.Pos = i\n";
287 // Implement the table accessor
288 void GenTableAccessor(const StructDef &struct_def, std::string *code_ptr) {
289 std::string &code = *code_ptr;
291 GenReceiver(struct_def, code_ptr);
292 code += " Table() flatbuffers.Table ";
295 if (struct_def.fixed) {
296 code += "\treturn rcv._tab.Table\n";
298 code += "\treturn rcv._tab\n";
303 // Get the length of a vector.
304 void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
305 std::string *code_ptr) {
306 std::string &code = *code_ptr;
308 GenReceiver(struct_def, code_ptr);
309 code += " " + MakeCamel(field.name) + "Length(";
310 code += ") int " + OffsetPrefix(field);
311 code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
312 code += "\treturn 0\n}\n\n";
315 // Get a [ubyte] vector as a byte slice.
316 void GetUByteSlice(const StructDef &struct_def, const FieldDef &field,
317 std::string *code_ptr) {
318 std::string &code = *code_ptr;
320 GenReceiver(struct_def, code_ptr);
321 code += " " + MakeCamel(field.name) + "Bytes(";
322 code += ") []byte " + OffsetPrefix(field);
323 code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
324 code += "\treturn nil\n}\n\n";
327 // Get the value of a struct's scalar.
328 void GetScalarFieldOfStruct(const StructDef &struct_def,
329 const FieldDef &field, 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 " +
336 CastToEnum(field.value.type,
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, const FieldDef &field,
344 std::string *code_ptr) {
345 std::string &code = *code_ptr;
346 std::string getter = GenGetter(field.value.type);
347 GenReceiver(struct_def, code_ptr);
348 code += " " + MakeCamel(field.name);
349 code += "() " + TypeName(field) + " ";
350 code += OffsetPrefix(field) + "\t\treturn ";
351 code += CastToEnum(field.value.type, getter + "(o + rcv._tab.Pos)");
353 code += "\treturn " + GenConstant(field) + "\n";
357 // Get a struct by initializing an existing struct.
358 // Specific to Struct.
359 void GetStructFieldOfStruct(const StructDef &struct_def,
360 const FieldDef &field, std::string *code_ptr) {
361 std::string &code = *code_ptr;
362 GenReceiver(struct_def, code_ptr);
363 code += " " + MakeCamel(field.name);
364 code += "(obj *" + TypeName(field);
365 code += ") *" + TypeName(field);
367 code += "\tif obj == nil {\n";
368 code += "\t\tobj = new(" + TypeName(field) + ")\n";
370 code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos+";
371 code += NumToString(field.value.offset) + ")";
372 code += "\n\treturn obj\n";
376 // Get a struct by initializing an existing struct.
377 // Specific to Table.
378 void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
379 std::string *code_ptr) {
380 std::string &code = *code_ptr;
381 GenReceiver(struct_def, code_ptr);
382 code += " " + MakeCamel(field.name);
384 code += TypeName(field);
385 code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
386 if (field.value.type.struct_def->fixed) {
387 code += "\t\tx := o + rcv._tab.Pos\n";
389 code += "\t\tx := rcv._tab.Indirect(o + rcv._tab.Pos)\n";
391 code += "\t\tif obj == nil {\n";
392 code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
394 code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
395 code += "\t\treturn obj\n\t}\n\treturn nil\n";
399 // Get the value of a string.
400 void GetStringField(const StructDef &struct_def, const FieldDef &field,
401 std::string *code_ptr) {
402 std::string &code = *code_ptr;
403 GenReceiver(struct_def, code_ptr);
404 code += " " + MakeCamel(field.name);
405 code += "() " + TypeName(field) + " ";
406 code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
407 code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
411 // Get the value of a union from an object.
412 void GetUnionField(const StructDef &struct_def, const FieldDef &field,
413 std::string *code_ptr) {
414 std::string &code = *code_ptr;
415 GenReceiver(struct_def, code_ptr);
416 code += " " + MakeCamel(field.name) + "(";
417 code += "obj " + GenTypePointer(field.value.type) + ") bool ";
418 code += OffsetPrefix(field);
419 code += "\t\t" + GenGetter(field.value.type);
420 code += "(obj, o)\n\t\treturn true\n\t}\n";
421 code += "\treturn false\n";
425 // Get the value of a vector's struct member.
426 void GetMemberOfVectorOfStruct(const StructDef &struct_def,
427 const FieldDef &field, std::string *code_ptr) {
428 std::string &code = *code_ptr;
429 auto vectortype = field.value.type.VectorType();
431 GenReceiver(struct_def, code_ptr);
432 code += " " + MakeCamel(field.name);
433 code += "(obj *" + TypeName(field);
434 code += ", j int) bool " + OffsetPrefix(field);
435 code += "\t\tx := rcv._tab.Vector(o)\n";
436 code += "\t\tx += flatbuffers.UOffsetT(j) * ";
437 code += NumToString(InlineSize(vectortype)) + "\n";
438 if (!(vectortype.struct_def->fixed)) {
439 code += "\t\tx = rcv._tab.Indirect(x)\n";
441 code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
442 code += "\t\treturn true\n\t}\n";
443 code += "\treturn false\n";
447 // Get the value of a vector's non-struct member.
448 void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
449 const FieldDef &field,
450 std::string *code_ptr) {
451 std::string &code = *code_ptr;
452 auto vectortype = field.value.type.VectorType();
454 GenReceiver(struct_def, code_ptr);
455 code += " " + MakeCamel(field.name);
456 code += "(j int) " + TypeName(field) + " ";
457 code += OffsetPrefix(field);
458 code += "\t\ta := rcv._tab.Vector(o)\n";
459 code += "\t\treturn " +
460 CastToEnum(field.value.type,
461 GenGetter(field.value.type) +
462 "(a + flatbuffers.UOffsetT(j*" +
463 NumToString(InlineSize(vectortype)) + "))");
465 if (vectortype.base_type == BASE_TYPE_STRING) {
466 code += "\treturn nil\n";
467 } else if (vectortype.base_type == BASE_TYPE_BOOL) {
468 code += "\treturn false\n";
470 code += "\treturn 0\n";
475 // Begin the creator function signature.
476 void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
477 std::string &code = *code_ptr;
479 if (code.substr(code.length() - 2) != "\n\n") {
480 // a previous mutate has not put an extra new line
483 code += "func Create" + struct_def.name;
484 code += "(builder *flatbuffers.Builder";
487 // Recursively generate arguments for a constructor, to deal with nested
489 void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
490 std::string *code_ptr) {
491 for (auto it = struct_def.fields.vec.begin();
492 it != struct_def.fields.vec.end(); ++it) {
494 if (IsStruct(field.value.type)) {
495 // Generate arguments for a struct inside a struct. To ensure names
496 // don't clash, and to make it obvious these arguments are constructing
497 // a nested struct, prefix the name with the field name.
498 StructBuilderArgs(*field.value.type.struct_def,
499 (nameprefix + (field.name + "_")).c_str(), code_ptr);
501 std::string &code = *code_ptr;
502 code += std::string(", ") + nameprefix;
503 code += GoIdentity(field.name);
504 code += " " + TypeName(field);
509 // End the creator function signature.
510 void EndBuilderArgs(std::string *code_ptr) {
511 std::string &code = *code_ptr;
512 code += ") flatbuffers.UOffsetT {\n";
515 // Recursively generate struct construction statements and instert manual
517 void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
518 std::string *code_ptr) {
519 std::string &code = *code_ptr;
520 code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", ";
521 code += NumToString(struct_def.bytesize) + ")\n";
522 for (auto it = struct_def.fields.vec.rbegin();
523 it != struct_def.fields.vec.rend(); ++it) {
526 code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n";
527 if (IsStruct(field.value.type)) {
528 StructBuilderBody(*field.value.type.struct_def,
529 (nameprefix + (field.name + "_")).c_str(), code_ptr);
531 code += "\tbuilder.Prepend" + GenMethod(field) + "(";
532 code += CastToBaseType(field.value.type,
533 nameprefix + GoIdentity(field.name)) +
539 void EndBuilderBody(std::string *code_ptr) {
540 std::string &code = *code_ptr;
541 code += "\treturn builder.Offset()\n";
545 // Get the value of a table's starting offset.
546 void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
547 std::string &code = *code_ptr;
548 code += "func " + struct_def.name + "Start";
549 code += "(builder *flatbuffers.Builder) {\n";
550 code += "\tbuilder.StartObject(";
551 code += NumToString(struct_def.fields.vec.size());
555 // Set the value of a table's field.
556 void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
557 const size_t offset, std::string *code_ptr) {
558 std::string &code = *code_ptr;
559 code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
560 code += "(builder *flatbuffers.Builder, ";
561 code += GoIdentity(field.name) + " ";
562 if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
563 code += "flatbuffers.UOffsetT";
565 code += TypeName(field);
568 code += "\tbuilder.Prepend";
569 code += GenMethod(field) + "Slot(";
570 code += NumToString(offset) + ", ";
571 if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
572 code += "flatbuffers.UOffsetT";
574 code += GoIdentity(field.name) + ")";
576 code += CastToBaseType(field.value.type, GoIdentity(field.name));
578 code += ", " + GenConstant(field);
582 // Set the value of one of the members of a table's vector.
583 void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
584 std::string *code_ptr) {
585 std::string &code = *code_ptr;
586 code += "func " + struct_def.name + "Start";
587 code += MakeCamel(field.name);
588 code += "Vector(builder *flatbuffers.Builder, numElems int) ";
589 code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
590 auto vector_type = field.value.type.VectorType();
591 auto alignment = InlineAlignment(vector_type);
592 auto elem_size = InlineSize(vector_type);
593 code += NumToString(elem_size);
594 code += ", numElems, " + NumToString(alignment);
598 // Get the offset of the end of a table.
599 void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
600 std::string &code = *code_ptr;
601 code += "func " + struct_def.name + "End";
602 code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
603 code += "{\n\treturn builder.EndObject()\n}\n";
606 // Generate the receiver for function signatures.
607 void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
608 std::string &code = *code_ptr;
609 code += "func (rcv *" + struct_def.name + ")";
612 // Generate a struct field getter, conditioned on its child type(s).
613 void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
614 std::string *code_ptr) {
615 GenComment(field.doc_comment, code_ptr, nullptr, "");
616 if (IsScalar(field.value.type.base_type)) {
617 if (struct_def.fixed) {
618 GetScalarFieldOfStruct(struct_def, field, code_ptr);
620 GetScalarFieldOfTable(struct_def, field, code_ptr);
623 switch (field.value.type.base_type) {
624 case BASE_TYPE_STRUCT:
625 if (struct_def.fixed) {
626 GetStructFieldOfStruct(struct_def, field, code_ptr);
628 GetStructFieldOfTable(struct_def, field, code_ptr);
631 case BASE_TYPE_STRING:
632 GetStringField(struct_def, field, code_ptr);
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, std::string *code_ptr) {
658 std::string &code = *code_ptr;
659 std::string type = MakeCamel(GenTypeBasic(field.value.type));
660 std::string setter = "rcv._tab.Mutate" + type;
661 GenReceiver(struct_def, code_ptr);
662 code += " Mutate" + MakeCamel(field.name);
663 code += "(n " + TypeName(field) + ") bool {\n\treturn " + setter;
664 code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
665 code += NumToString(field.value.offset) + "), ";
666 code += CastToBaseType(field.value.type, "n") + ")\n}\n\n";
669 // Mutate the value of a table's scalar.
670 void MutateScalarFieldOfTable(const StructDef &struct_def,
671 const FieldDef &field, std::string *code_ptr) {
672 std::string &code = *code_ptr;
673 std::string type = MakeCamel(GenTypeBasic(field.value.type));
674 std::string setter = "rcv._tab.Mutate" + type + "Slot";
675 GenReceiver(struct_def, code_ptr);
676 code += " Mutate" + MakeCamel(field.name);
677 code += "(n " + TypeName(field) + ") bool {\n\treturn ";
678 code += setter + "(" + NumToString(field.value.offset) + ", ";
679 code += CastToBaseType(field.value.type, "n") + ")\n";
683 // Mutate an element of a vector of scalars.
684 void MutateElementOfVectorOfNonStruct(const StructDef &struct_def,
685 const FieldDef &field,
686 std::string *code_ptr) {
687 std::string &code = *code_ptr;
688 auto vectortype = field.value.type.VectorType();
689 std::string type = MakeCamel(GenTypeBasic(vectortype));
690 std::string setter = "rcv._tab.Mutate" + type;
691 GenReceiver(struct_def, code_ptr);
692 code += " Mutate" + MakeCamel(field.name);
693 code += "(j int, n " + TypeName(field) + ") bool ";
694 code += OffsetPrefix(field);
695 code += "\t\ta := rcv._tab.Vector(o)\n";
696 code += "\t\treturn " + setter + "(";
697 code += "a+flatbuffers.UOffsetT(j*";
698 code += NumToString(InlineSize(vectortype)) + "), ";
699 code += CastToBaseType(vectortype, "n") + ")\n";
701 code += "\treturn false\n";
705 // Generate a struct field setter, conditioned on its child type(s).
706 void GenStructMutator(const StructDef &struct_def, const FieldDef &field,
707 std::string *code_ptr) {
708 GenComment(field.doc_comment, code_ptr, nullptr, "");
709 if (IsScalar(field.value.type.base_type)) {
710 if (struct_def.fixed) {
711 MutateScalarFieldOfStruct(struct_def, field, code_ptr);
713 MutateScalarFieldOfTable(struct_def, field, code_ptr);
715 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
716 if (IsScalar(field.value.type.element)) {
717 MutateElementOfVectorOfNonStruct(struct_def, field, code_ptr);
722 // Generate table constructors, conditioned on its members' types.
723 void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
724 GetStartOfTable(struct_def, code_ptr);
726 for (auto it = struct_def.fields.vec.begin();
727 it != struct_def.fields.vec.end(); ++it) {
729 if (field.deprecated) continue;
731 auto offset = it - struct_def.fields.vec.begin();
732 BuildFieldOfTable(struct_def, field, offset, code_ptr);
733 if (field.value.type.base_type == BASE_TYPE_VECTOR) {
734 BuildVectorOfTable(struct_def, field, code_ptr);
738 GetEndOffsetOnTable(struct_def, code_ptr);
741 // Generate struct or table methods.
742 void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
743 if (struct_def.generated) return;
745 cur_name_space_ = struct_def.defined_namespace;
747 GenComment(struct_def.doc_comment, code_ptr, nullptr);
748 if (parser_.opts.generate_object_based_api) {
749 GenNativeStruct(struct_def, code_ptr);
751 BeginClass(struct_def, code_ptr);
752 if (!struct_def.fixed) {
753 // Generate a special accessor for the table that has been declared as
755 NewRootTypeFromBuffer(struct_def, code_ptr);
757 // Generate the Init method that sets the field in a pre-existing
758 // accessor object. This is to allow object reuse.
759 InitializeExisting(struct_def, code_ptr);
760 // Generate _tab accessor
761 GenTableAccessor(struct_def, code_ptr);
763 // Generate struct fields accessors
764 for (auto it = struct_def.fields.vec.begin();
765 it != struct_def.fields.vec.end(); ++it) {
767 if (field.deprecated) continue;
769 GenStructAccessor(struct_def, field, code_ptr);
770 GenStructMutator(struct_def, field, code_ptr);
774 if (struct_def.fixed) {
775 // create a struct constructor function
776 GenStructBuilder(struct_def, code_ptr);
778 // Create a set of functions that allow table construction.
779 GenTableBuilders(struct_def, code_ptr);
783 void GenNativeStruct(const StructDef &struct_def, std::string *code_ptr) {
784 std::string &code = *code_ptr;
786 code += "type " + NativeName(struct_def) + " struct {\n";
787 for (auto it = struct_def.fields.vec.begin();
788 it != struct_def.fields.vec.end(); ++it) {
789 const FieldDef &field = **it;
790 if (field.deprecated) continue;
791 if (IsScalar(field.value.type.base_type) &&
792 field.value.type.enum_def != nullptr &&
793 field.value.type.enum_def->is_union)
795 code += "\t" + MakeCamel(field.name) + " " +
796 NativeType(field.value.type) + "\n";
800 if (!struct_def.fixed) {
801 GenNativeTablePack(struct_def, code_ptr);
802 GenNativeTableUnPack(struct_def, code_ptr);
804 GenNativeStructPack(struct_def, code_ptr);
805 GenNativeStructUnPack(struct_def, code_ptr);
809 void GenNativeUnion(const EnumDef &enum_def, std::string *code_ptr) {
810 std::string &code = *code_ptr;
811 code += "type " + NativeName(enum_def) + " struct {\n";
812 code += "\tType " + enum_def.name + "\n";
813 code += "\tValue interface{}\n";
817 void GenNativeUnionPack(const EnumDef &enum_def, std::string *code_ptr) {
818 std::string &code = *code_ptr;
819 code += "func " + enum_def.name + "Pack(builder *flatbuffers.Builder, t *" +
820 NativeName(enum_def) + ") flatbuffers.UOffsetT {\n";
821 code += "\tif t == nil {\n\t\treturn 0\n\t}\n";
823 code += "\tswitch t.Type {\n";
824 for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end();
826 const EnumVal &ev = **it2;
827 if (ev.IsZero()) continue;
828 code += "\tcase " + enum_def.name + ev.name + ":\n";
829 code += "\t\treturn " +
830 WrapInNameSpaceAndTrack(*ev.union_type.struct_def) +
831 "Pack(builder, t.Value.(" + NativeType(ev.union_type) + "))\n";
834 code += "\treturn 0\n";
838 void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) {
839 std::string &code = *code_ptr;
841 code += "func " + enum_def.name + "UnPack(t " + enum_def.name +
842 ", table flatbuffers.Table) *" + NativeName(enum_def) + " {\n";
843 code += "\tswitch t {\n";
845 for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end();
847 const EnumVal &ev = **it2;
848 if (ev.IsZero()) continue;
849 code += "\tcase " + enum_def.name + ev.name + ":\n";
850 code += "\t\tx := " + ev.union_type.struct_def->name + "{_tab: table}\n";
852 code += "\t\treturn &" +
853 WrapInNameSpaceAndTrack(enum_def.defined_namespace,
854 NativeName(enum_def)) +
855 "{ Type: " + enum_def.name + ev.name + ", Value: x.UnPack() }\n";
858 code += "\treturn nil\n";
862 void GenNativeTablePack(const StructDef &struct_def, std::string *code_ptr) {
863 std::string &code = *code_ptr;
865 code += "func " + struct_def.name +
866 "Pack(builder *flatbuffers.Builder, t *" + NativeName(struct_def) +
867 ") flatbuffers.UOffsetT {\n";
868 code += "\tif t == nil { return 0 }\n";
869 for (auto it = struct_def.fields.vec.begin();
870 it != struct_def.fields.vec.end(); ++it) {
871 const FieldDef &field = **it;
872 if (field.deprecated) continue;
873 if (IsScalar(field.value.type.base_type)) continue;
875 std::string offset = MakeCamel(field.name, false) + "Offset";
877 if (field.value.type.base_type == BASE_TYPE_STRING) {
878 code += "\t" + offset + " := builder.CreateString(t." +
879 MakeCamel(field.name) + ")\n";
880 } else if (field.value.type.base_type == BASE_TYPE_VECTOR &&
881 field.value.type.element == BASE_TYPE_UCHAR &&
882 field.value.type.enum_def == nullptr) {
883 code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
884 code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
885 code += "\t\t" + offset + " = builder.CreateByteString(t." +
886 MakeCamel(field.name) + ")\n";
888 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
889 code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
890 code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
891 std::string length = MakeCamel(field.name, false) + "Length";
892 std::string offsets = MakeCamel(field.name, false) + "Offsets";
893 code += "\t\t" + length + " := len(t." + MakeCamel(field.name) + ")\n";
894 if (field.value.type.element == BASE_TYPE_STRING) {
895 code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " +
897 code += "\t\tfor j := 0; j < " + length + "; j++ {\n";
898 code += "\t\t\t" + offsets + "[j] = builder.CreateString(t." +
899 MakeCamel(field.name) + "[j])\n";
901 } else if (field.value.type.element == BASE_TYPE_STRUCT &&
902 !field.value.type.struct_def->fixed) {
903 code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " +
905 code += "\t\tfor j := 0; j < " + length + "; j++ {\n";
906 code += "\t\t\t" + offsets + "[j] = " +
907 WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
908 "Pack(builder, t." + MakeCamel(field.name) + "[j])\n";
911 code += "\t\t" + struct_def.name + "Start" + MakeCamel(field.name) +
912 "Vector(builder, " + length + ")\n";
913 code += "\t\tfor j := " + length + " - 1; j >= 0; j-- {\n";
914 if (IsScalar(field.value.type.element)) {
915 code += "\t\t\tbuilder.Prepend" +
916 MakeCamel(GenTypeBasic(field.value.type.VectorType())) + "(" +
917 CastToBaseType(field.value.type.VectorType(),
918 "t." + MakeCamel(field.name) + "[j]") +
920 } else if (field.value.type.element == BASE_TYPE_STRUCT &&
921 field.value.type.struct_def->fixed) {
923 WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
924 "Pack(builder, t." + MakeCamel(field.name) + "[j])\n";
926 code += "\t\t\tbuilder.PrependUOffsetT(" + offsets + "[j])\n";
929 code += "\t\t" + offset + " = builder.EndVector(" + length + ")\n";
931 } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
932 if (field.value.type.struct_def->fixed) continue;
933 code += "\t" + offset +
934 " := " + WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
935 "Pack(builder, t." + MakeCamel(field.name) + ")\n";
936 } else if (field.value.type.base_type == BASE_TYPE_UNION) {
937 code += "\t" + offset +
938 " := " + WrapInNameSpaceAndTrack(*field.value.type.enum_def) +
939 "Pack(builder, t." + MakeCamel(field.name) + ")\n";
942 FLATBUFFERS_ASSERT(0);
945 code += "\t" + struct_def.name + "Start(builder)\n";
946 for (auto it = struct_def.fields.vec.begin();
947 it != struct_def.fields.vec.end(); ++it) {
948 const FieldDef &field = **it;
949 if (field.deprecated) continue;
951 std::string offset = MakeCamel(field.name, false) + "Offset";
952 if (IsScalar(field.value.type.base_type)) {
953 if (field.value.type.enum_def == nullptr ||
954 !field.value.type.enum_def->is_union) {
955 code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
956 "(builder, t." + MakeCamel(field.name) + ")\n";
959 if (field.value.type.base_type == BASE_TYPE_STRUCT &&
960 field.value.type.struct_def->fixed) {
961 code += "\t" + offset + " := " +
962 WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
963 "Pack(builder, t." + MakeCamel(field.name) + ")\n";
964 } else if (field.value.type.enum_def != nullptr &&
965 field.value.type.enum_def->is_union) {
966 code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
967 code += "\t\t" + struct_def.name + "Add" +
968 MakeCamel(field.name + UnionTypeFieldSuffix()) +
969 "(builder, t." + MakeCamel(field.name) + ".Type)\n";
972 code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
973 "(builder, " + offset + ")\n";
976 code += "\treturn " + struct_def.name + "End(builder)\n";
980 void GenNativeTableUnPack(const StructDef &struct_def,
981 std::string *code_ptr) {
982 std::string &code = *code_ptr;
984 code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
985 NativeName(struct_def) + ") {\n";
986 for (auto it = struct_def.fields.vec.begin();
987 it != struct_def.fields.vec.end(); ++it) {
988 const FieldDef &field = **it;
989 if (field.deprecated) continue;
990 std::string field_name_camel = MakeCamel(field.name);
991 std::string length = MakeCamel(field.name, false) + "Length";
992 if (IsScalar(field.value.type.base_type)) {
993 if (field.value.type.enum_def != nullptr &&
994 field.value.type.enum_def->is_union)
997 "\tt." + field_name_camel + " = rcv." + field_name_camel + "()\n";
998 } else if (field.value.type.base_type == BASE_TYPE_STRING) {
999 code += "\tt." + field_name_camel + " = string(rcv." +
1000 field_name_camel + "())\n";
1001 } else if (field.value.type.base_type == BASE_TYPE_VECTOR &&
1002 field.value.type.element == BASE_TYPE_UCHAR &&
1003 field.value.type.enum_def == nullptr) {
1004 code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
1006 } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
1007 code += "\t" + length + " := rcv." + field_name_camel + "Length()\n";
1008 code += "\tt." + field_name_camel + " = make(" +
1009 NativeType(field.value.type) + ", " + length + ")\n";
1010 code += "\tfor j := 0; j < " + length + "; j++ {\n";
1011 if (field.value.type.element == BASE_TYPE_STRUCT) {
1012 code += "\t\tx := " + field.value.type.struct_def->name + "{}\n";
1013 code += "\t\trcv." + field_name_camel + "(&x, j)\n";
1015 code += "\t\tt." + field_name_camel + "[j] = ";
1016 if (IsScalar(field.value.type.element)) {
1017 code += "rcv." + field_name_camel + "(j)";
1018 } else if (field.value.type.element == BASE_TYPE_STRING) {
1019 code += "string(rcv." + field_name_camel + "(j))";
1020 } else if (field.value.type.element == BASE_TYPE_STRUCT) {
1021 code += "x.UnPack()";
1023 // TODO(iceboy): Support vector of unions.
1024 FLATBUFFERS_ASSERT(0);
1028 } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1029 code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
1031 } else if (field.value.type.base_type == BASE_TYPE_UNION) {
1032 const EnumDef &enum_def = *field.value.type.enum_def;
1033 std::string field_table = MakeCamel(field.name, false) + "Table";
1034 code += "\t" + field_table + " := flatbuffers.Table{}\n";
1036 "\tif rcv." + MakeCamel(field.name) + "(&" + field_table + ") {\n";
1037 code += "\t\tt." + field_name_camel + " = " + enum_def.name +
1038 "UnPack(rcv." + MakeCamel(field.name + UnionTypeFieldSuffix()) +
1039 "(), " + field_table + ")\n";
1042 FLATBUFFERS_ASSERT(0);
1047 code += "func (rcv *" + struct_def.name + ") UnPack() *" +
1048 NativeName(struct_def) + " {\n";
1049 code += "\tif rcv == nil { return nil }\n";
1050 code += "\tt := &" + NativeName(struct_def) + "{}\n";
1051 code += "\trcv.UnPackTo(t)\n";
1052 code += "\treturn t\n";
1056 void GenNativeStructPack(const StructDef &struct_def, std::string *code_ptr) {
1057 std::string &code = *code_ptr;
1059 code += "func " + struct_def.name +
1060 "Pack(builder *flatbuffers.Builder, t *" + NativeName(struct_def) +
1061 ") flatbuffers.UOffsetT {\n";
1062 code += "\tif t == nil { return 0 }\n";
1063 code += "\treturn Create" + struct_def.name + "(builder";
1064 StructPackArgs(struct_def, "", code_ptr);
1069 void StructPackArgs(const StructDef &struct_def, const char *nameprefix,
1070 std::string *code_ptr) {
1071 std::string &code = *code_ptr;
1072 for (auto it = struct_def.fields.vec.begin();
1073 it != struct_def.fields.vec.end(); ++it) {
1074 const FieldDef &field = **it;
1075 if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1076 StructPackArgs(*field.value.type.struct_def,
1077 (nameprefix + MakeCamel(field.name) + ".").c_str(),
1080 code += std::string(", t.") + nameprefix + MakeCamel(field.name);
1085 void GenNativeStructUnPack(const StructDef &struct_def,
1086 std::string *code_ptr) {
1087 std::string &code = *code_ptr;
1089 code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
1090 NativeName(struct_def) + ") {\n";
1091 for (auto it = struct_def.fields.vec.begin();
1092 it != struct_def.fields.vec.end(); ++it) {
1093 const FieldDef &field = **it;
1094 if (field.value.type.base_type == BASE_TYPE_STRUCT) {
1095 code += "\tt." + MakeCamel(field.name) + " = rcv." +
1096 MakeCamel(field.name) + "(nil).UnPack()\n";
1098 code += "\tt." + MakeCamel(field.name) + " = rcv." +
1099 MakeCamel(field.name) + "()\n";
1104 code += "func (rcv *" + struct_def.name + ") UnPack() *" +
1105 NativeName(struct_def) + " {\n";
1106 code += "\tif rcv == nil { return nil }\n";
1107 code += "\tt := &" + NativeName(struct_def) + "{}\n";
1108 code += "\trcv.UnPackTo(t)\n";
1109 code += "\treturn t\n";
1113 // Generate enum declarations.
1114 void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
1115 if (enum_def.generated) return;
1117 auto max_name_length = MaxNameLength(enum_def);
1118 cur_name_space_ = enum_def.defined_namespace;
1120 GenComment(enum_def.doc_comment, code_ptr, nullptr);
1121 GenEnumType(enum_def, code_ptr);
1122 BeginEnum(code_ptr);
1123 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1124 const EnumVal &ev = **it;
1125 GenComment(ev.doc_comment, code_ptr, nullptr, "\t");
1126 EnumMember(enum_def, ev, max_name_length, code_ptr);
1130 BeginEnumNames(enum_def, code_ptr);
1131 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1132 const EnumVal &ev = **it;
1133 EnumNameMember(enum_def, ev, max_name_length, code_ptr);
1135 EndEnumNames(code_ptr);
1137 BeginEnumValues(enum_def, code_ptr);
1138 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1140 EnumValueMember(enum_def, ev, max_name_length, code_ptr);
1142 EndEnumValues(code_ptr);
1144 EnumStringer(enum_def, code_ptr);
1147 // Returns the function name that is able to read a value of the given type.
1148 std::string GenGetter(const Type &type) {
1149 switch (type.base_type) {
1150 case BASE_TYPE_STRING: return "rcv._tab.ByteVector";
1151 case BASE_TYPE_UNION: return "rcv._tab.Union";
1152 case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
1153 default: return "rcv._tab.Get" + MakeCamel(GenTypeBasic(type));
1157 // Returns the method name for use with add/put calls.
1158 std::string GenMethod(const FieldDef &field) {
1159 return IsScalar(field.value.type.base_type)
1160 ? MakeCamel(GenTypeBasic(field.value.type))
1161 : (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
1164 std::string GenTypeBasic(const Type &type) {
1165 static const char *ctypename[] = {
1167 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
1168 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
1170 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
1171 #undef FLATBUFFERS_TD
1174 return ctypename[type.base_type];
1177 std::string GenTypePointer(const Type &type) {
1178 switch (type.base_type) {
1179 case BASE_TYPE_STRING: return "[]byte";
1180 case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
1181 case BASE_TYPE_STRUCT: return WrapInNameSpaceAndTrack(*type.struct_def);
1182 case BASE_TYPE_UNION:
1184 default: return "*flatbuffers.Table";
1188 std::string GenTypeGet(const Type &type) {
1189 if (type.enum_def != nullptr) { return GetEnumTypeName(*type.enum_def); }
1190 return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
1193 std::string TypeName(const FieldDef &field) {
1194 return GenTypeGet(field.value.type);
1197 // If type is an enum, returns value with a cast to the enum type, otherwise
1198 // returns value as-is.
1199 std::string CastToEnum(const Type &type, std::string value) {
1200 if (type.enum_def == nullptr) {
1203 return GenTypeGet(type) + "(" + value + ")";
1207 // If type is an enum, returns value with a cast to the enum base type,
1208 // otherwise returns value as-is.
1209 std::string CastToBaseType(const Type &type, std::string value) {
1210 if (type.enum_def == nullptr) {
1213 return GenTypeBasic(type) + "(" + value + ")";
1217 std::string GenConstant(const FieldDef &field) {
1218 switch (field.value.type.base_type) {
1219 case BASE_TYPE_BOOL:
1220 return field.value.constant == "0" ? "false" : "true";
1221 default: return field.value.constant;
1225 std::string NativeName(const StructDef &struct_def) {
1226 return parser_.opts.object_prefix + struct_def.name +
1227 parser_.opts.object_suffix;
1230 std::string NativeName(const EnumDef &enum_def) {
1231 return parser_.opts.object_prefix + enum_def.name +
1232 parser_.opts.object_suffix;
1235 std::string NativeType(const Type &type) {
1236 if (IsScalar(type.base_type)) {
1237 if (type.enum_def == nullptr) {
1238 return GenTypeBasic(type);
1240 return GetEnumTypeName(*type.enum_def);
1242 } else if (type.base_type == BASE_TYPE_STRING) {
1244 } else if (type.base_type == BASE_TYPE_VECTOR) {
1245 return "[]" + NativeType(type.VectorType());
1246 } else if (type.base_type == BASE_TYPE_STRUCT) {
1247 return "*" + WrapInNameSpaceAndTrack(type.struct_def->defined_namespace,
1248 NativeName(*type.struct_def));
1249 } else if (type.base_type == BASE_TYPE_UNION) {
1250 return "*" + WrapInNameSpaceAndTrack(type.enum_def->defined_namespace,
1251 NativeName(*type.enum_def));
1253 FLATBUFFERS_ASSERT(0);
1254 return std::string();
1257 // Create a struct with a builder and the struct's arguments.
1258 void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
1259 BeginBuilderArgs(struct_def, code_ptr);
1260 StructBuilderArgs(struct_def, "", code_ptr);
1261 EndBuilderArgs(code_ptr);
1263 StructBuilderBody(struct_def, "", code_ptr);
1264 EndBuilderBody(code_ptr);
1266 // Begin by declaring namespace and imports.
1267 void BeginFile(const std::string &name_space_name, const bool needs_imports,
1268 const bool is_enum, std::string *code_ptr) {
1269 std::string &code = *code_ptr;
1271 "// Code generated by the FlatBuffers compiler. DO NOT EDIT.\n\n";
1272 code += "package " + name_space_name + "\n\n";
1273 if (needs_imports) {
1274 code += "import (\n";
1275 if (is_enum) { code += "\t\"strconv\"\n\n"; }
1276 if (!parser_.opts.go_import.empty()) {
1277 code += "\tflatbuffers \"" + parser_.opts.go_import + "\"\n";
1279 code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
1281 if (tracked_imported_namespaces_.size() > 0) {
1283 for (auto it = tracked_imported_namespaces_.begin();
1284 it != tracked_imported_namespaces_.end(); ++it) {
1285 code += "\t" + NamespaceImportName(*it) + " \"" +
1286 NamespaceImportPath(*it) + "\"\n";
1291 if (is_enum) { code += "import \"strconv\"\n\n"; }
1295 // Save out the generated code for a Go Table type.
1296 bool SaveType(const Definition &def, const std::string &classcode,
1297 const bool needs_imports, const bool is_enum) {
1298 if (!classcode.length()) return true;
1300 Namespace &ns = go_namespace_.components.empty() ? *def.defined_namespace
1302 std::string code = "";
1303 BeginFile(LastNamespacePart(ns), needs_imports, is_enum, &code);
1305 // Strip extra newlines at end of file to make it gofmt-clean.
1306 while (code.length() > 2 && code.substr(code.length() - 2) == "\n\n") {
1309 std::string filename = NamespaceDir(ns) + def.name + ".go";
1310 return SaveFile(filename.c_str(), code, false);
1313 // Create the full name of the imported namespace (format: A__B__C).
1314 std::string NamespaceImportName(const Namespace *ns) {
1316 for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
1317 if (s.size() == 0) {
1326 // Create the full path for the imported namespace (format: A/B/C).
1327 std::string NamespaceImportPath(const Namespace *ns) {
1329 for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
1330 if (s.size() == 0) {
1339 // Ensure that a type is prefixed with its go package import name if it is
1340 // used outside of its namespace.
1341 std::string WrapInNameSpaceAndTrack(const Namespace *ns,
1342 const std::string &name) {
1343 if (CurrentNameSpace() == ns) return name;
1345 tracked_imported_namespaces_.insert(ns);
1347 std::string import_name = NamespaceImportName(ns);
1348 return import_name + "." + name;
1351 std::string WrapInNameSpaceAndTrack(const Definition &def) {
1352 return WrapInNameSpaceAndTrack(def.defined_namespace, def.name);
1355 const Namespace *CurrentNameSpace() const { return cur_name_space_; }
1357 static size_t MaxNameLength(const EnumDef &enum_def) {
1359 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1360 max = std::max((*it)->name.length(), max);
1367 bool GenerateGo(const Parser &parser, const std::string &path,
1368 const std::string &file_name) {
1369 go::GoGenerator generator(parser, path, file_name, parser.opts.go_namespace);
1370 return generator.generate();
1373 } // namespace flatbuffers