1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker *
4*890232f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker *
8*890232f2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker *
10*890232f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker */
16*890232f2SAndroid Build Coastguard Worker
17*890232f2SAndroid Build Coastguard Worker // independent from idl_parser, since this code is not needed for most clients
18*890232f2SAndroid Build Coastguard Worker
19*890232f2SAndroid Build Coastguard Worker #include <string>
20*890232f2SAndroid Build Coastguard Worker #include <unordered_set>
21*890232f2SAndroid Build Coastguard Worker
22*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/code_generators.h"
23*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/flatbuffers.h"
24*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/idl.h"
25*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/util.h"
26*890232f2SAndroid Build Coastguard Worker
27*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
28*890232f2SAndroid Build Coastguard Worker namespace lua {
29*890232f2SAndroid Build Coastguard Worker
30*890232f2SAndroid Build Coastguard Worker // Hardcode spaces per indentation.
31*890232f2SAndroid Build Coastguard Worker const CommentConfig def_comment = { nullptr, "--", nullptr };
32*890232f2SAndroid Build Coastguard Worker const char *Indent = " ";
33*890232f2SAndroid Build Coastguard Worker const char *Comment = "-- ";
34*890232f2SAndroid Build Coastguard Worker const char *End = "end\n";
35*890232f2SAndroid Build Coastguard Worker const char *EndFunc = "end\n";
36*890232f2SAndroid Build Coastguard Worker const char *SelfData = "self.view";
37*890232f2SAndroid Build Coastguard Worker const char *SelfDataPos = "self.view.pos";
38*890232f2SAndroid Build Coastguard Worker const char *SelfDataBytes = "self.view.bytes";
39*890232f2SAndroid Build Coastguard Worker
40*890232f2SAndroid Build Coastguard Worker class LuaGenerator : public BaseGenerator {
41*890232f2SAndroid Build Coastguard Worker public:
LuaGenerator(const Parser & parser,const std::string & path,const std::string & file_name)42*890232f2SAndroid Build Coastguard Worker LuaGenerator(const Parser &parser, const std::string &path,
43*890232f2SAndroid Build Coastguard Worker const std::string &file_name)
44*890232f2SAndroid Build Coastguard Worker : BaseGenerator(parser, path, file_name, "" /* not used */,
45*890232f2SAndroid Build Coastguard Worker "" /* not used */, "lua") {
46*890232f2SAndroid Build Coastguard Worker static const char *const keywords[] = {
47*890232f2SAndroid Build Coastguard Worker "and", "break", "do", "else", "elseif", "end", "false", "for",
48*890232f2SAndroid Build Coastguard Worker "function", "goto", "if", "in", "local", "nil", "not", "or",
49*890232f2SAndroid Build Coastguard Worker "repeat", "return", "then", "true", "until", "while"
50*890232f2SAndroid Build Coastguard Worker };
51*890232f2SAndroid Build Coastguard Worker keywords_.insert(std::begin(keywords), std::end(keywords));
52*890232f2SAndroid Build Coastguard Worker }
53*890232f2SAndroid Build Coastguard Worker
54*890232f2SAndroid Build Coastguard Worker // Most field accessors need to retrieve and test the field offset first,
55*890232f2SAndroid Build Coastguard Worker // this is the prefix code for that.
OffsetPrefix(const FieldDef & field)56*890232f2SAndroid Build Coastguard Worker std::string OffsetPrefix(const FieldDef &field) {
57*890232f2SAndroid Build Coastguard Worker return std::string(Indent) + "local o = " + SelfData + ":Offset(" +
58*890232f2SAndroid Build Coastguard Worker NumToString(field.value.offset) + ")\n" + Indent +
59*890232f2SAndroid Build Coastguard Worker "if o ~= 0 then\n";
60*890232f2SAndroid Build Coastguard Worker }
61*890232f2SAndroid Build Coastguard Worker
62*890232f2SAndroid Build Coastguard Worker // Begin a class declaration.
BeginClass(const StructDef & struct_def,std::string * code_ptr)63*890232f2SAndroid Build Coastguard Worker void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
64*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
65*890232f2SAndroid Build Coastguard Worker code += "local " + NormalizedName(struct_def) + " = {} -- the module\n";
66*890232f2SAndroid Build Coastguard Worker code += "local " + NormalizedMetaName(struct_def) +
67*890232f2SAndroid Build Coastguard Worker " = {} -- the class metatable\n";
68*890232f2SAndroid Build Coastguard Worker code += "\n";
69*890232f2SAndroid Build Coastguard Worker }
70*890232f2SAndroid Build Coastguard Worker
71*890232f2SAndroid Build Coastguard Worker // Begin enum code with a class declaration.
BeginEnum(const std::string & class_name,std::string * code_ptr)72*890232f2SAndroid Build Coastguard Worker void BeginEnum(const std::string &class_name, std::string *code_ptr) {
73*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
74*890232f2SAndroid Build Coastguard Worker code += "local " + class_name + " = {\n";
75*890232f2SAndroid Build Coastguard Worker }
76*890232f2SAndroid Build Coastguard Worker
EscapeKeyword(const std::string & name) const77*890232f2SAndroid Build Coastguard Worker std::string EscapeKeyword(const std::string &name) const {
78*890232f2SAndroid Build Coastguard Worker return keywords_.find(name) == keywords_.end() ? name : "_" + name;
79*890232f2SAndroid Build Coastguard Worker }
80*890232f2SAndroid Build Coastguard Worker
NormalizedName(const Definition & definition) const81*890232f2SAndroid Build Coastguard Worker std::string NormalizedName(const Definition &definition) const {
82*890232f2SAndroid Build Coastguard Worker return EscapeKeyword(definition.name);
83*890232f2SAndroid Build Coastguard Worker }
84*890232f2SAndroid Build Coastguard Worker
NormalizedName(const EnumVal & ev) const85*890232f2SAndroid Build Coastguard Worker std::string NormalizedName(const EnumVal &ev) const {
86*890232f2SAndroid Build Coastguard Worker return EscapeKeyword(ev.name);
87*890232f2SAndroid Build Coastguard Worker }
88*890232f2SAndroid Build Coastguard Worker
NormalizedMetaName(const Definition & definition) const89*890232f2SAndroid Build Coastguard Worker std::string NormalizedMetaName(const Definition &definition) const {
90*890232f2SAndroid Build Coastguard Worker return EscapeKeyword(definition.name) + "_mt";
91*890232f2SAndroid Build Coastguard Worker }
92*890232f2SAndroid Build Coastguard Worker
93*890232f2SAndroid Build Coastguard Worker // A single enum member.
EnumMember(const EnumDef & enum_def,const EnumVal & ev,std::string * code_ptr)94*890232f2SAndroid Build Coastguard Worker void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
95*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
96*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
97*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + NormalizedName(ev) + " = " +
98*890232f2SAndroid Build Coastguard Worker enum_def.ToString(ev) + ",\n";
99*890232f2SAndroid Build Coastguard Worker }
100*890232f2SAndroid Build Coastguard Worker
101*890232f2SAndroid Build Coastguard Worker // End enum code.
EndEnum(std::string * code_ptr)102*890232f2SAndroid Build Coastguard Worker void EndEnum(std::string *code_ptr) {
103*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
104*890232f2SAndroid Build Coastguard Worker code += "}\n";
105*890232f2SAndroid Build Coastguard Worker }
106*890232f2SAndroid Build Coastguard Worker
GenerateNewObjectPrototype(const StructDef & struct_def,std::string * code_ptr)107*890232f2SAndroid Build Coastguard Worker void GenerateNewObjectPrototype(const StructDef &struct_def,
108*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
109*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
110*890232f2SAndroid Build Coastguard Worker
111*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".New()\n";
112*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "local o = {}\n";
113*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) +
114*890232f2SAndroid Build Coastguard Worker "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) +
115*890232f2SAndroid Build Coastguard Worker "})\n";
116*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return o\n";
117*890232f2SAndroid Build Coastguard Worker code += EndFunc;
118*890232f2SAndroid Build Coastguard Worker }
119*890232f2SAndroid Build Coastguard Worker
120*890232f2SAndroid Build Coastguard Worker // Initialize a new struct or table from existing data.
NewRootTypeFromBuffer(const StructDef & struct_def,std::string * code_ptr)121*890232f2SAndroid Build Coastguard Worker void NewRootTypeFromBuffer(const StructDef &struct_def,
122*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
123*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
124*890232f2SAndroid Build Coastguard Worker
125*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".GetRootAs" +
126*890232f2SAndroid Build Coastguard Worker NormalizedName(struct_def) + "(buf, offset)\n";
127*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "if type(buf) == \"string\" then\n";
128*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent +
129*890232f2SAndroid Build Coastguard Worker "buf = flatbuffers.binaryArray.New(buf)\n";
130*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "end\n";
131*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) +
132*890232f2SAndroid Build Coastguard Worker "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
133*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "local o = " + NormalizedName(struct_def) +
134*890232f2SAndroid Build Coastguard Worker ".New()\n";
135*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "o:Init(buf, n + offset)\n";
136*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return o\n";
137*890232f2SAndroid Build Coastguard Worker code += EndFunc;
138*890232f2SAndroid Build Coastguard Worker }
139*890232f2SAndroid Build Coastguard Worker
140*890232f2SAndroid Build Coastguard Worker // Initialize an existing object with other data, to avoid an allocation.
InitializeExisting(const StructDef & struct_def,std::string * code_ptr)141*890232f2SAndroid Build Coastguard Worker void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
142*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
143*890232f2SAndroid Build Coastguard Worker
144*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
145*890232f2SAndroid Build Coastguard Worker code += "Init(buf, pos)\n";
146*890232f2SAndroid Build Coastguard Worker code +=
147*890232f2SAndroid Build Coastguard Worker std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n";
148*890232f2SAndroid Build Coastguard Worker code += EndFunc;
149*890232f2SAndroid Build Coastguard Worker }
150*890232f2SAndroid Build Coastguard Worker
151*890232f2SAndroid Build Coastguard Worker // Get the length of a vector.
GetVectorLen(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)152*890232f2SAndroid Build Coastguard Worker void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
153*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
154*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
155*890232f2SAndroid Build Coastguard Worker
156*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
157*890232f2SAndroid Build Coastguard Worker code +=
158*890232f2SAndroid Build Coastguard Worker ConvertCase(NormalizedName(field), Case::kUpperCamel) + "Length()\n";
159*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
160*890232f2SAndroid Build Coastguard Worker code +=
161*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
162*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
163*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return 0\n";
164*890232f2SAndroid Build Coastguard Worker code += EndFunc;
165*890232f2SAndroid Build Coastguard Worker }
166*890232f2SAndroid Build Coastguard Worker
167*890232f2SAndroid Build Coastguard Worker // Get the value of a struct's scalar.
GetScalarFieldOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)168*890232f2SAndroid Build Coastguard Worker void GetScalarFieldOfStruct(const StructDef &struct_def,
169*890232f2SAndroid Build Coastguard Worker const FieldDef &field, std::string *code_ptr) {
170*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
171*890232f2SAndroid Build Coastguard Worker std::string getter = GenGetter(field.value.type);
172*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
173*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
174*890232f2SAndroid Build Coastguard Worker code += "()\n";
175*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return " + getter;
176*890232f2SAndroid Build Coastguard Worker code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) +
177*890232f2SAndroid Build Coastguard Worker ")\n";
178*890232f2SAndroid Build Coastguard Worker code += EndFunc;
179*890232f2SAndroid Build Coastguard Worker }
180*890232f2SAndroid Build Coastguard Worker
181*890232f2SAndroid Build Coastguard Worker // Get the value of a table's scalar.
GetScalarFieldOfTable(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)182*890232f2SAndroid Build Coastguard Worker void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
183*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
184*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
185*890232f2SAndroid Build Coastguard Worker std::string getter = GenGetter(field.value.type);
186*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
187*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
188*890232f2SAndroid Build Coastguard Worker code += "()\n";
189*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
190*890232f2SAndroid Build Coastguard Worker getter += std::string("o + ") + SelfDataPos + ")";
191*890232f2SAndroid Build Coastguard Worker auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
192*890232f2SAndroid Build Coastguard Worker if (is_bool) { getter = "(" + getter + " ~= 0)"; }
193*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "return " + getter + "\n";
194*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
195*890232f2SAndroid Build Coastguard Worker std::string default_value;
196*890232f2SAndroid Build Coastguard Worker if (is_bool) {
197*890232f2SAndroid Build Coastguard Worker default_value = field.value.constant == "0" ? "false" : "true";
198*890232f2SAndroid Build Coastguard Worker } else {
199*890232f2SAndroid Build Coastguard Worker default_value = field.value.constant;
200*890232f2SAndroid Build Coastguard Worker }
201*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return " + default_value + "\n";
202*890232f2SAndroid Build Coastguard Worker code += EndFunc;
203*890232f2SAndroid Build Coastguard Worker }
204*890232f2SAndroid Build Coastguard Worker
205*890232f2SAndroid Build Coastguard Worker // Get a struct by initializing an existing struct.
206*890232f2SAndroid Build Coastguard Worker // Specific to Struct.
GetStructFieldOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)207*890232f2SAndroid Build Coastguard Worker void GetStructFieldOfStruct(const StructDef &struct_def,
208*890232f2SAndroid Build Coastguard Worker const FieldDef &field, std::string *code_ptr) {
209*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
210*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
211*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
212*890232f2SAndroid Build Coastguard Worker code += "(obj)\n";
213*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " +
214*890232f2SAndroid Build Coastguard Worker SelfDataPos + " + ";
215*890232f2SAndroid Build Coastguard Worker code += NumToString(field.value.offset) + ")\n";
216*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return obj\n";
217*890232f2SAndroid Build Coastguard Worker code += EndFunc;
218*890232f2SAndroid Build Coastguard Worker }
219*890232f2SAndroid Build Coastguard Worker
220*890232f2SAndroid Build Coastguard Worker // Get a struct by initializing an existing struct.
221*890232f2SAndroid Build Coastguard Worker // Specific to Table.
GetStructFieldOfTable(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)222*890232f2SAndroid Build Coastguard Worker void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
223*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
224*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
225*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
226*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
227*890232f2SAndroid Build Coastguard Worker code += "()\n";
228*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
229*890232f2SAndroid Build Coastguard Worker if (field.value.type.struct_def->fixed) {
230*890232f2SAndroid Build Coastguard Worker code +=
231*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n";
232*890232f2SAndroid Build Coastguard Worker } else {
233*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "local x = " + SelfData +
234*890232f2SAndroid Build Coastguard Worker ":Indirect(o + " + SelfDataPos + ")\n";
235*890232f2SAndroid Build Coastguard Worker }
236*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "local obj = require('" +
237*890232f2SAndroid Build Coastguard Worker TypeNameWithNamespace(field) + "').New()\n";
238*890232f2SAndroid Build Coastguard Worker code +=
239*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
240*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "return obj\n";
241*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
242*890232f2SAndroid Build Coastguard Worker code += EndFunc;
243*890232f2SAndroid Build Coastguard Worker }
244*890232f2SAndroid Build Coastguard Worker
245*890232f2SAndroid Build Coastguard Worker // Get the value of a string.
GetStringField(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)246*890232f2SAndroid Build Coastguard Worker void GetStringField(const StructDef &struct_def, const FieldDef &field,
247*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
248*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
249*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
250*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
251*890232f2SAndroid Build Coastguard Worker code += "()\n";
252*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
253*890232f2SAndroid Build Coastguard Worker code +=
254*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "return " + GenGetter(field.value.type);
255*890232f2SAndroid Build Coastguard Worker code += std::string("o + ") + SelfDataPos + ")\n";
256*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
257*890232f2SAndroid Build Coastguard Worker code += EndFunc;
258*890232f2SAndroid Build Coastguard Worker }
259*890232f2SAndroid Build Coastguard Worker
260*890232f2SAndroid Build Coastguard Worker // Get the value of a union from an object.
GetUnionField(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)261*890232f2SAndroid Build Coastguard Worker void GetUnionField(const StructDef &struct_def, const FieldDef &field,
262*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
263*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
264*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
265*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel) + "()\n";
266*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
267*890232f2SAndroid Build Coastguard Worker
268*890232f2SAndroid Build Coastguard Worker // TODO(rw): this works and is not the good way to it:
269*890232f2SAndroid Build Coastguard Worker // bool is_native_table = TypeName(field) == "*flatbuffers.Table";
270*890232f2SAndroid Build Coastguard Worker // if (is_native_table) {
271*890232f2SAndroid Build Coastguard Worker // code += std::string(Indent) + Indent + "from flatbuffers.table import
272*890232f2SAndroid Build Coastguard Worker // Table\n";
273*890232f2SAndroid Build Coastguard Worker //} else {
274*890232f2SAndroid Build Coastguard Worker // code += std::string(Indent) + Indent +
275*890232f2SAndroid Build Coastguard Worker // code += "from ." + TypeName(field) + " import " + TypeName(field) +
276*890232f2SAndroid Build Coastguard Worker // "\n";
277*890232f2SAndroid Build Coastguard Worker //}
278*890232f2SAndroid Build Coastguard Worker code +=
279*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent +
280*890232f2SAndroid Build Coastguard Worker "local obj = "
281*890232f2SAndroid Build Coastguard Worker "flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n";
282*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + GenGetter(field.value.type) +
283*890232f2SAndroid Build Coastguard Worker "obj, o)\n";
284*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "return obj\n";
285*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
286*890232f2SAndroid Build Coastguard Worker code += EndFunc;
287*890232f2SAndroid Build Coastguard Worker }
288*890232f2SAndroid Build Coastguard Worker
289*890232f2SAndroid Build Coastguard Worker // Get the value of a vector's struct member.
GetMemberOfVectorOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)290*890232f2SAndroid Build Coastguard Worker void GetMemberOfVectorOfStruct(const StructDef &struct_def,
291*890232f2SAndroid Build Coastguard Worker const FieldDef &field, std::string *code_ptr) {
292*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
293*890232f2SAndroid Build Coastguard Worker auto vectortype = field.value.type.VectorType();
294*890232f2SAndroid Build Coastguard Worker
295*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
296*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
297*890232f2SAndroid Build Coastguard Worker code += "(j)\n";
298*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
299*890232f2SAndroid Build Coastguard Worker code +=
300*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n";
301*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "x = x + ((j-1) * ";
302*890232f2SAndroid Build Coastguard Worker code += NumToString(InlineSize(vectortype)) + ")\n";
303*890232f2SAndroid Build Coastguard Worker if (!(vectortype.struct_def->fixed)) {
304*890232f2SAndroid Build Coastguard Worker code +=
305*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n";
306*890232f2SAndroid Build Coastguard Worker }
307*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "local obj = require('" +
308*890232f2SAndroid Build Coastguard Worker TypeNameWithNamespace(field) + "').New()\n";
309*890232f2SAndroid Build Coastguard Worker code +=
310*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
311*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent + "return obj\n";
312*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
313*890232f2SAndroid Build Coastguard Worker code += EndFunc;
314*890232f2SAndroid Build Coastguard Worker }
315*890232f2SAndroid Build Coastguard Worker
316*890232f2SAndroid Build Coastguard Worker // Get the value of a vector's non-struct member. Uses a named return
317*890232f2SAndroid Build Coastguard Worker // argument to conveniently set the zero value for the result.
GetMemberOfVectorOfNonStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)318*890232f2SAndroid Build Coastguard Worker void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
319*890232f2SAndroid Build Coastguard Worker const FieldDef &field,
320*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
321*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
322*890232f2SAndroid Build Coastguard Worker auto vectortype = field.value.type.VectorType();
323*890232f2SAndroid Build Coastguard Worker
324*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
325*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
326*890232f2SAndroid Build Coastguard Worker code += "(j)\n";
327*890232f2SAndroid Build Coastguard Worker code += OffsetPrefix(field);
328*890232f2SAndroid Build Coastguard Worker code +=
329*890232f2SAndroid Build Coastguard Worker std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n";
330*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + Indent;
331*890232f2SAndroid Build Coastguard Worker code += "return " + GenGetter(field.value.type);
332*890232f2SAndroid Build Coastguard Worker code += "a + ((j-1) * ";
333*890232f2SAndroid Build Coastguard Worker code += NumToString(InlineSize(vectortype)) + "))\n";
334*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + End;
335*890232f2SAndroid Build Coastguard Worker if (IsString(vectortype)) {
336*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return ''\n";
337*890232f2SAndroid Build Coastguard Worker } else {
338*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return 0\n";
339*890232f2SAndroid Build Coastguard Worker }
340*890232f2SAndroid Build Coastguard Worker code += EndFunc;
341*890232f2SAndroid Build Coastguard Worker }
342*890232f2SAndroid Build Coastguard Worker
343*890232f2SAndroid Build Coastguard Worker // Access a byte/ubyte vector as a string
AccessByteVectorAsString(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)344*890232f2SAndroid Build Coastguard Worker void AccessByteVectorAsString(const StructDef &struct_def,
345*890232f2SAndroid Build Coastguard Worker const FieldDef &field, std::string *code_ptr) {
346*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
347*890232f2SAndroid Build Coastguard Worker GenReceiver(struct_def, code_ptr);
348*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
349*890232f2SAndroid Build Coastguard Worker code += "AsString(start, stop)\n";
350*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return " + SelfData + ":VectorAsString(" +
351*890232f2SAndroid Build Coastguard Worker NumToString(field.value.offset) + ", start, stop)\n";
352*890232f2SAndroid Build Coastguard Worker code += EndFunc;
353*890232f2SAndroid Build Coastguard Worker }
354*890232f2SAndroid Build Coastguard Worker
355*890232f2SAndroid Build Coastguard Worker // Begin the creator function signature.
BeginBuilderArgs(const StructDef & struct_def,std::string * code_ptr)356*890232f2SAndroid Build Coastguard Worker void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
357*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
358*890232f2SAndroid Build Coastguard Worker
359*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".Create" +
360*890232f2SAndroid Build Coastguard Worker NormalizedName(struct_def);
361*890232f2SAndroid Build Coastguard Worker code += "(builder";
362*890232f2SAndroid Build Coastguard Worker }
363*890232f2SAndroid Build Coastguard Worker
364*890232f2SAndroid Build Coastguard Worker // Recursively generate arguments for a constructor, to deal with nested
365*890232f2SAndroid Build Coastguard Worker // structs.
StructBuilderArgs(const StructDef & struct_def,const char * nameprefix,std::string * code_ptr)366*890232f2SAndroid Build Coastguard Worker void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
367*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
368*890232f2SAndroid Build Coastguard Worker for (auto it = struct_def.fields.vec.begin();
369*890232f2SAndroid Build Coastguard Worker it != struct_def.fields.vec.end(); ++it) {
370*890232f2SAndroid Build Coastguard Worker auto &field = **it;
371*890232f2SAndroid Build Coastguard Worker if (IsStruct(field.value.type)) {
372*890232f2SAndroid Build Coastguard Worker // Generate arguments for a struct inside a struct. To ensure names
373*890232f2SAndroid Build Coastguard Worker // don't clash, and to make it obvious these arguments are constructing
374*890232f2SAndroid Build Coastguard Worker // a nested struct, prefix the name with the field name.
375*890232f2SAndroid Build Coastguard Worker StructBuilderArgs(*field.value.type.struct_def,
376*890232f2SAndroid Build Coastguard Worker (nameprefix + (NormalizedName(field) + "_")).c_str(),
377*890232f2SAndroid Build Coastguard Worker code_ptr);
378*890232f2SAndroid Build Coastguard Worker } else {
379*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
380*890232f2SAndroid Build Coastguard Worker code += std::string(", ") + nameprefix;
381*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
382*890232f2SAndroid Build Coastguard Worker }
383*890232f2SAndroid Build Coastguard Worker }
384*890232f2SAndroid Build Coastguard Worker }
385*890232f2SAndroid Build Coastguard Worker
386*890232f2SAndroid Build Coastguard Worker // End the creator function signature.
EndBuilderArgs(std::string * code_ptr)387*890232f2SAndroid Build Coastguard Worker void EndBuilderArgs(std::string *code_ptr) {
388*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
389*890232f2SAndroid Build Coastguard Worker code += ")\n";
390*890232f2SAndroid Build Coastguard Worker }
391*890232f2SAndroid Build Coastguard Worker
392*890232f2SAndroid Build Coastguard Worker // Recursively generate struct construction statements and instert manual
393*890232f2SAndroid Build Coastguard Worker // padding.
StructBuilderBody(const StructDef & struct_def,const char * nameprefix,std::string * code_ptr)394*890232f2SAndroid Build Coastguard Worker void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
395*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
396*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
397*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "builder:Prep(" +
398*890232f2SAndroid Build Coastguard Worker NumToString(struct_def.minalign) + ", ";
399*890232f2SAndroid Build Coastguard Worker code += NumToString(struct_def.bytesize) + ")\n";
400*890232f2SAndroid Build Coastguard Worker for (auto it = struct_def.fields.vec.rbegin();
401*890232f2SAndroid Build Coastguard Worker it != struct_def.fields.vec.rend(); ++it) {
402*890232f2SAndroid Build Coastguard Worker auto &field = **it;
403*890232f2SAndroid Build Coastguard Worker if (field.padding)
404*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "builder:Pad(" +
405*890232f2SAndroid Build Coastguard Worker NumToString(field.padding) + ")\n";
406*890232f2SAndroid Build Coastguard Worker if (IsStruct(field.value.type)) {
407*890232f2SAndroid Build Coastguard Worker StructBuilderBody(*field.value.type.struct_def,
408*890232f2SAndroid Build Coastguard Worker (nameprefix + (NormalizedName(field) + "_")).c_str(),
409*890232f2SAndroid Build Coastguard Worker code_ptr);
410*890232f2SAndroid Build Coastguard Worker } else {
411*890232f2SAndroid Build Coastguard Worker code +=
412*890232f2SAndroid Build Coastguard Worker std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
413*890232f2SAndroid Build Coastguard Worker code += nameprefix +
414*890232f2SAndroid Build Coastguard Worker ConvertCase(NormalizedName(field), Case::kLowerCamel) + ")\n";
415*890232f2SAndroid Build Coastguard Worker }
416*890232f2SAndroid Build Coastguard Worker }
417*890232f2SAndroid Build Coastguard Worker }
418*890232f2SAndroid Build Coastguard Worker
EndBuilderBody(std::string * code_ptr)419*890232f2SAndroid Build Coastguard Worker void EndBuilderBody(std::string *code_ptr) {
420*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
421*890232f2SAndroid Build Coastguard Worker code += std::string(Indent) + "return builder:Offset()\n";
422*890232f2SAndroid Build Coastguard Worker code += EndFunc;
423*890232f2SAndroid Build Coastguard Worker }
424*890232f2SAndroid Build Coastguard Worker
425*890232f2SAndroid Build Coastguard Worker // Get the value of a table's starting offset.
GetStartOfTable(const StructDef & struct_def,std::string * code_ptr)426*890232f2SAndroid Build Coastguard Worker void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
427*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
428*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".Start";
429*890232f2SAndroid Build Coastguard Worker code += "(builder) ";
430*890232f2SAndroid Build Coastguard Worker code += "builder:StartObject(";
431*890232f2SAndroid Build Coastguard Worker code += NumToString(struct_def.fields.vec.size());
432*890232f2SAndroid Build Coastguard Worker code += ") end\n";
433*890232f2SAndroid Build Coastguard Worker }
434*890232f2SAndroid Build Coastguard Worker
435*890232f2SAndroid Build Coastguard Worker // Set the value of a table's field.
BuildFieldOfTable(const StructDef & struct_def,const FieldDef & field,const size_t offset,std::string * code_ptr)436*890232f2SAndroid Build Coastguard Worker void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
437*890232f2SAndroid Build Coastguard Worker const size_t offset, std::string *code_ptr) {
438*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
439*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".Add" +
440*890232f2SAndroid Build Coastguard Worker ConvertCase(NormalizedName(field), Case::kUpperCamel);
441*890232f2SAndroid Build Coastguard Worker code += "(builder, ";
442*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
443*890232f2SAndroid Build Coastguard Worker code += ") ";
444*890232f2SAndroid Build Coastguard Worker code += "builder:Prepend";
445*890232f2SAndroid Build Coastguard Worker code += GenMethod(field) + "Slot(";
446*890232f2SAndroid Build Coastguard Worker code += NumToString(offset) + ", ";
447*890232f2SAndroid Build Coastguard Worker // todo: i don't need to cast in Lua, but am I missing something?
448*890232f2SAndroid Build Coastguard Worker // if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
449*890232f2SAndroid Build Coastguard Worker // code += "flatbuffers.N.UOffsetTFlags.py_type";
450*890232f2SAndroid Build Coastguard Worker // code += "(";
451*890232f2SAndroid Build Coastguard Worker // code += ConvertCase(NormalizedName(field), Case::kLowerCamel) + ")";
452*890232f2SAndroid Build Coastguard Worker // } else {
453*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
454*890232f2SAndroid Build Coastguard Worker // }
455*890232f2SAndroid Build Coastguard Worker code += ", " + field.value.constant;
456*890232f2SAndroid Build Coastguard Worker code += ") end\n";
457*890232f2SAndroid Build Coastguard Worker }
458*890232f2SAndroid Build Coastguard Worker
459*890232f2SAndroid Build Coastguard Worker // Set the value of one of the members of a table's vector.
BuildVectorOfTable(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)460*890232f2SAndroid Build Coastguard Worker void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
461*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
462*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
463*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".Start";
464*890232f2SAndroid Build Coastguard Worker code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
465*890232f2SAndroid Build Coastguard Worker code += "Vector(builder, numElems) return builder:StartVector(";
466*890232f2SAndroid Build Coastguard Worker auto vector_type = field.value.type.VectorType();
467*890232f2SAndroid Build Coastguard Worker auto alignment = InlineAlignment(vector_type);
468*890232f2SAndroid Build Coastguard Worker auto elem_size = InlineSize(vector_type);
469*890232f2SAndroid Build Coastguard Worker code += NumToString(elem_size);
470*890232f2SAndroid Build Coastguard Worker code += ", numElems, " + NumToString(alignment);
471*890232f2SAndroid Build Coastguard Worker code += ") end\n";
472*890232f2SAndroid Build Coastguard Worker }
473*890232f2SAndroid Build Coastguard Worker
474*890232f2SAndroid Build Coastguard Worker // Get the offset of the end of a table.
GetEndOffsetOnTable(const StructDef & struct_def,std::string * code_ptr)475*890232f2SAndroid Build Coastguard Worker void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
476*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
477*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedName(struct_def) + ".End";
478*890232f2SAndroid Build Coastguard Worker code += "(builder) ";
479*890232f2SAndroid Build Coastguard Worker code += "return builder:EndObject() end\n";
480*890232f2SAndroid Build Coastguard Worker }
481*890232f2SAndroid Build Coastguard Worker
482*890232f2SAndroid Build Coastguard Worker // Generate the receiver for function signatures.
GenReceiver(const StructDef & struct_def,std::string * code_ptr)483*890232f2SAndroid Build Coastguard Worker void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
484*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
485*890232f2SAndroid Build Coastguard Worker code += "function " + NormalizedMetaName(struct_def) + ":";
486*890232f2SAndroid Build Coastguard Worker }
487*890232f2SAndroid Build Coastguard Worker
488*890232f2SAndroid Build Coastguard Worker // Generate a struct field, conditioned on its child type(s).
GenStructAccessor(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr)489*890232f2SAndroid Build Coastguard Worker void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
490*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
491*890232f2SAndroid Build Coastguard Worker GenComment(field.doc_comment, code_ptr, &def_comment);
492*890232f2SAndroid Build Coastguard Worker if (IsScalar(field.value.type.base_type)) {
493*890232f2SAndroid Build Coastguard Worker if (struct_def.fixed) {
494*890232f2SAndroid Build Coastguard Worker GetScalarFieldOfStruct(struct_def, field, code_ptr);
495*890232f2SAndroid Build Coastguard Worker } else {
496*890232f2SAndroid Build Coastguard Worker GetScalarFieldOfTable(struct_def, field, code_ptr);
497*890232f2SAndroid Build Coastguard Worker }
498*890232f2SAndroid Build Coastguard Worker } else {
499*890232f2SAndroid Build Coastguard Worker switch (field.value.type.base_type) {
500*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRUCT:
501*890232f2SAndroid Build Coastguard Worker if (struct_def.fixed) {
502*890232f2SAndroid Build Coastguard Worker GetStructFieldOfStruct(struct_def, field, code_ptr);
503*890232f2SAndroid Build Coastguard Worker } else {
504*890232f2SAndroid Build Coastguard Worker GetStructFieldOfTable(struct_def, field, code_ptr);
505*890232f2SAndroid Build Coastguard Worker }
506*890232f2SAndroid Build Coastguard Worker break;
507*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRING:
508*890232f2SAndroid Build Coastguard Worker GetStringField(struct_def, field, code_ptr);
509*890232f2SAndroid Build Coastguard Worker break;
510*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_VECTOR: {
511*890232f2SAndroid Build Coastguard Worker auto vectortype = field.value.type.VectorType();
512*890232f2SAndroid Build Coastguard Worker if (vectortype.base_type == BASE_TYPE_STRUCT) {
513*890232f2SAndroid Build Coastguard Worker GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
514*890232f2SAndroid Build Coastguard Worker } else {
515*890232f2SAndroid Build Coastguard Worker GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
516*890232f2SAndroid Build Coastguard Worker if (vectortype.base_type == BASE_TYPE_CHAR ||
517*890232f2SAndroid Build Coastguard Worker vectortype.base_type == BASE_TYPE_UCHAR) {
518*890232f2SAndroid Build Coastguard Worker AccessByteVectorAsString(struct_def, field, code_ptr);
519*890232f2SAndroid Build Coastguard Worker }
520*890232f2SAndroid Build Coastguard Worker }
521*890232f2SAndroid Build Coastguard Worker break;
522*890232f2SAndroid Build Coastguard Worker }
523*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
524*890232f2SAndroid Build Coastguard Worker default: FLATBUFFERS_ASSERT(0);
525*890232f2SAndroid Build Coastguard Worker }
526*890232f2SAndroid Build Coastguard Worker }
527*890232f2SAndroid Build Coastguard Worker if (IsVector(field.value.type)) {
528*890232f2SAndroid Build Coastguard Worker GetVectorLen(struct_def, field, code_ptr);
529*890232f2SAndroid Build Coastguard Worker }
530*890232f2SAndroid Build Coastguard Worker }
531*890232f2SAndroid Build Coastguard Worker
532*890232f2SAndroid Build Coastguard Worker // Generate table constructors, conditioned on its members' types.
GenTableBuilders(const StructDef & struct_def,std::string * code_ptr)533*890232f2SAndroid Build Coastguard Worker void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
534*890232f2SAndroid Build Coastguard Worker GetStartOfTable(struct_def, code_ptr);
535*890232f2SAndroid Build Coastguard Worker
536*890232f2SAndroid Build Coastguard Worker for (auto it = struct_def.fields.vec.begin();
537*890232f2SAndroid Build Coastguard Worker it != struct_def.fields.vec.end(); ++it) {
538*890232f2SAndroid Build Coastguard Worker auto &field = **it;
539*890232f2SAndroid Build Coastguard Worker if (field.deprecated) continue;
540*890232f2SAndroid Build Coastguard Worker
541*890232f2SAndroid Build Coastguard Worker auto offset = it - struct_def.fields.vec.begin();
542*890232f2SAndroid Build Coastguard Worker BuildFieldOfTable(struct_def, field, offset, code_ptr);
543*890232f2SAndroid Build Coastguard Worker if (IsVector(field.value.type)) {
544*890232f2SAndroid Build Coastguard Worker BuildVectorOfTable(struct_def, field, code_ptr);
545*890232f2SAndroid Build Coastguard Worker }
546*890232f2SAndroid Build Coastguard Worker }
547*890232f2SAndroid Build Coastguard Worker
548*890232f2SAndroid Build Coastguard Worker GetEndOffsetOnTable(struct_def, code_ptr);
549*890232f2SAndroid Build Coastguard Worker }
550*890232f2SAndroid Build Coastguard Worker
551*890232f2SAndroid Build Coastguard Worker // Generate struct or table methods.
GenStruct(const StructDef & struct_def,std::string * code_ptr)552*890232f2SAndroid Build Coastguard Worker void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
553*890232f2SAndroid Build Coastguard Worker if (struct_def.generated) return;
554*890232f2SAndroid Build Coastguard Worker
555*890232f2SAndroid Build Coastguard Worker GenComment(struct_def.doc_comment, code_ptr, &def_comment);
556*890232f2SAndroid Build Coastguard Worker BeginClass(struct_def, code_ptr);
557*890232f2SAndroid Build Coastguard Worker
558*890232f2SAndroid Build Coastguard Worker GenerateNewObjectPrototype(struct_def, code_ptr);
559*890232f2SAndroid Build Coastguard Worker
560*890232f2SAndroid Build Coastguard Worker if (!struct_def.fixed) {
561*890232f2SAndroid Build Coastguard Worker // Generate a special accessor for the table that has been declared as
562*890232f2SAndroid Build Coastguard Worker // the root type.
563*890232f2SAndroid Build Coastguard Worker NewRootTypeFromBuffer(struct_def, code_ptr);
564*890232f2SAndroid Build Coastguard Worker }
565*890232f2SAndroid Build Coastguard Worker
566*890232f2SAndroid Build Coastguard Worker // Generate the Init method that sets the field in a pre-existing
567*890232f2SAndroid Build Coastguard Worker // accessor object. This is to allow object reuse.
568*890232f2SAndroid Build Coastguard Worker InitializeExisting(struct_def, code_ptr);
569*890232f2SAndroid Build Coastguard Worker for (auto it = struct_def.fields.vec.begin();
570*890232f2SAndroid Build Coastguard Worker it != struct_def.fields.vec.end(); ++it) {
571*890232f2SAndroid Build Coastguard Worker auto &field = **it;
572*890232f2SAndroid Build Coastguard Worker if (field.deprecated) continue;
573*890232f2SAndroid Build Coastguard Worker
574*890232f2SAndroid Build Coastguard Worker GenStructAccessor(struct_def, field, code_ptr);
575*890232f2SAndroid Build Coastguard Worker }
576*890232f2SAndroid Build Coastguard Worker
577*890232f2SAndroid Build Coastguard Worker if (struct_def.fixed) {
578*890232f2SAndroid Build Coastguard Worker // create a struct constructor function
579*890232f2SAndroid Build Coastguard Worker GenStructBuilder(struct_def, code_ptr);
580*890232f2SAndroid Build Coastguard Worker } else {
581*890232f2SAndroid Build Coastguard Worker // Create a set of functions that allow table construction.
582*890232f2SAndroid Build Coastguard Worker GenTableBuilders(struct_def, code_ptr);
583*890232f2SAndroid Build Coastguard Worker }
584*890232f2SAndroid Build Coastguard Worker }
585*890232f2SAndroid Build Coastguard Worker
586*890232f2SAndroid Build Coastguard Worker // Generate enum declarations.
GenEnum(const EnumDef & enum_def,std::string * code_ptr)587*890232f2SAndroid Build Coastguard Worker void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
588*890232f2SAndroid Build Coastguard Worker if (enum_def.generated) return;
589*890232f2SAndroid Build Coastguard Worker
590*890232f2SAndroid Build Coastguard Worker GenComment(enum_def.doc_comment, code_ptr, &def_comment);
591*890232f2SAndroid Build Coastguard Worker BeginEnum(NormalizedName(enum_def), code_ptr);
592*890232f2SAndroid Build Coastguard Worker for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
593*890232f2SAndroid Build Coastguard Worker auto &ev = **it;
594*890232f2SAndroid Build Coastguard Worker GenComment(ev.doc_comment, code_ptr, &def_comment, Indent);
595*890232f2SAndroid Build Coastguard Worker EnumMember(enum_def, ev, code_ptr);
596*890232f2SAndroid Build Coastguard Worker }
597*890232f2SAndroid Build Coastguard Worker EndEnum(code_ptr);
598*890232f2SAndroid Build Coastguard Worker }
599*890232f2SAndroid Build Coastguard Worker
600*890232f2SAndroid Build Coastguard Worker // Returns the function name that is able to read a value of the given type.
GenGetter(const Type & type)601*890232f2SAndroid Build Coastguard Worker std::string GenGetter(const Type &type) {
602*890232f2SAndroid Build Coastguard Worker switch (type.base_type) {
603*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRING: return std::string(SelfData) + ":String(";
604*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UNION: return std::string(SelfData) + ":Union(";
605*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
606*890232f2SAndroid Build Coastguard Worker default:
607*890232f2SAndroid Build Coastguard Worker return std::string(SelfData) + ":Get(flatbuffers.N." +
608*890232f2SAndroid Build Coastguard Worker ConvertCase(GenTypeGet(type), Case::kUpperCamel) + ", ";
609*890232f2SAndroid Build Coastguard Worker }
610*890232f2SAndroid Build Coastguard Worker }
611*890232f2SAndroid Build Coastguard Worker
612*890232f2SAndroid Build Coastguard Worker // Returns the method name for use with add/put calls.
GenMethod(const FieldDef & field)613*890232f2SAndroid Build Coastguard Worker std::string GenMethod(const FieldDef &field) {
614*890232f2SAndroid Build Coastguard Worker return IsScalar(field.value.type.base_type)
615*890232f2SAndroid Build Coastguard Worker ? ConvertCase(GenTypeBasic(field.value.type), Case::kUpperCamel)
616*890232f2SAndroid Build Coastguard Worker : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
617*890232f2SAndroid Build Coastguard Worker }
618*890232f2SAndroid Build Coastguard Worker
GenTypeBasic(const Type & type)619*890232f2SAndroid Build Coastguard Worker std::string GenTypeBasic(const Type &type) {
620*890232f2SAndroid Build Coastguard Worker // clang-format off
621*890232f2SAndroid Build Coastguard Worker static const char *ctypename[] = {
622*890232f2SAndroid Build Coastguard Worker #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
623*890232f2SAndroid Build Coastguard Worker CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
624*890232f2SAndroid Build Coastguard Worker #PTYPE,
625*890232f2SAndroid Build Coastguard Worker FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
626*890232f2SAndroid Build Coastguard Worker #undef FLATBUFFERS_TD
627*890232f2SAndroid Build Coastguard Worker };
628*890232f2SAndroid Build Coastguard Worker // clang-format on
629*890232f2SAndroid Build Coastguard Worker return ctypename[type.base_type];
630*890232f2SAndroid Build Coastguard Worker }
631*890232f2SAndroid Build Coastguard Worker
GenTypePointer(const Type & type)632*890232f2SAndroid Build Coastguard Worker std::string GenTypePointer(const Type &type) {
633*890232f2SAndroid Build Coastguard Worker switch (type.base_type) {
634*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRING: return "string";
635*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
636*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRUCT: return type.struct_def->name;
637*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UNION:
638*890232f2SAndroid Build Coastguard Worker // fall through
639*890232f2SAndroid Build Coastguard Worker default: return "*flatbuffers.Table";
640*890232f2SAndroid Build Coastguard Worker }
641*890232f2SAndroid Build Coastguard Worker }
642*890232f2SAndroid Build Coastguard Worker
GenTypeGet(const Type & type)643*890232f2SAndroid Build Coastguard Worker std::string GenTypeGet(const Type &type) {
644*890232f2SAndroid Build Coastguard Worker return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
645*890232f2SAndroid Build Coastguard Worker }
646*890232f2SAndroid Build Coastguard Worker
GetNamespace(const Type & type)647*890232f2SAndroid Build Coastguard Worker std::string GetNamespace(const Type &type) {
648*890232f2SAndroid Build Coastguard Worker return type.struct_def->defined_namespace->GetFullyQualifiedName(
649*890232f2SAndroid Build Coastguard Worker type.struct_def->name);
650*890232f2SAndroid Build Coastguard Worker }
651*890232f2SAndroid Build Coastguard Worker
TypeName(const FieldDef & field)652*890232f2SAndroid Build Coastguard Worker std::string TypeName(const FieldDef &field) {
653*890232f2SAndroid Build Coastguard Worker return GenTypeGet(field.value.type);
654*890232f2SAndroid Build Coastguard Worker }
655*890232f2SAndroid Build Coastguard Worker
TypeNameWithNamespace(const FieldDef & field)656*890232f2SAndroid Build Coastguard Worker std::string TypeNameWithNamespace(const FieldDef &field) {
657*890232f2SAndroid Build Coastguard Worker return GetNamespace(field.value.type);
658*890232f2SAndroid Build Coastguard Worker }
659*890232f2SAndroid Build Coastguard Worker
660*890232f2SAndroid Build Coastguard Worker // Create a struct with a builder and the struct's arguments.
GenStructBuilder(const StructDef & struct_def,std::string * code_ptr)661*890232f2SAndroid Build Coastguard Worker void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
662*890232f2SAndroid Build Coastguard Worker BeginBuilderArgs(struct_def, code_ptr);
663*890232f2SAndroid Build Coastguard Worker StructBuilderArgs(struct_def, "", code_ptr);
664*890232f2SAndroid Build Coastguard Worker EndBuilderArgs(code_ptr);
665*890232f2SAndroid Build Coastguard Worker
666*890232f2SAndroid Build Coastguard Worker StructBuilderBody(struct_def, "", code_ptr);
667*890232f2SAndroid Build Coastguard Worker EndBuilderBody(code_ptr);
668*890232f2SAndroid Build Coastguard Worker }
669*890232f2SAndroid Build Coastguard Worker
generate()670*890232f2SAndroid Build Coastguard Worker bool generate() {
671*890232f2SAndroid Build Coastguard Worker if (!generateEnums()) return false;
672*890232f2SAndroid Build Coastguard Worker if (!generateStructs()) return false;
673*890232f2SAndroid Build Coastguard Worker return true;
674*890232f2SAndroid Build Coastguard Worker }
675*890232f2SAndroid Build Coastguard Worker
676*890232f2SAndroid Build Coastguard Worker private:
generateEnums()677*890232f2SAndroid Build Coastguard Worker bool generateEnums() {
678*890232f2SAndroid Build Coastguard Worker for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
679*890232f2SAndroid Build Coastguard Worker ++it) {
680*890232f2SAndroid Build Coastguard Worker auto &enum_def = **it;
681*890232f2SAndroid Build Coastguard Worker std::string enumcode;
682*890232f2SAndroid Build Coastguard Worker GenEnum(enum_def, &enumcode);
683*890232f2SAndroid Build Coastguard Worker if (!SaveType(enum_def, enumcode, false)) return false;
684*890232f2SAndroid Build Coastguard Worker }
685*890232f2SAndroid Build Coastguard Worker return true;
686*890232f2SAndroid Build Coastguard Worker }
687*890232f2SAndroid Build Coastguard Worker
generateStructs()688*890232f2SAndroid Build Coastguard Worker bool generateStructs() {
689*890232f2SAndroid Build Coastguard Worker for (auto it = parser_.structs_.vec.begin();
690*890232f2SAndroid Build Coastguard Worker it != parser_.structs_.vec.end(); ++it) {
691*890232f2SAndroid Build Coastguard Worker auto &struct_def = **it;
692*890232f2SAndroid Build Coastguard Worker std::string declcode;
693*890232f2SAndroid Build Coastguard Worker GenStruct(struct_def, &declcode);
694*890232f2SAndroid Build Coastguard Worker if (!SaveType(struct_def, declcode, true)) return false;
695*890232f2SAndroid Build Coastguard Worker }
696*890232f2SAndroid Build Coastguard Worker return true;
697*890232f2SAndroid Build Coastguard Worker }
698*890232f2SAndroid Build Coastguard Worker
699*890232f2SAndroid Build Coastguard Worker // Begin by declaring namespace and imports.
BeginFile(const std::string & name_space_name,const bool needs_imports,std::string * code_ptr)700*890232f2SAndroid Build Coastguard Worker void BeginFile(const std::string &name_space_name, const bool needs_imports,
701*890232f2SAndroid Build Coastguard Worker std::string *code_ptr) {
702*890232f2SAndroid Build Coastguard Worker std::string &code = *code_ptr;
703*890232f2SAndroid Build Coastguard Worker code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n";
704*890232f2SAndroid Build Coastguard Worker code += std::string(Comment) + "namespace: " + name_space_name + "\n\n";
705*890232f2SAndroid Build Coastguard Worker if (needs_imports) {
706*890232f2SAndroid Build Coastguard Worker code += "local flatbuffers = require('flatbuffers')\n\n";
707*890232f2SAndroid Build Coastguard Worker }
708*890232f2SAndroid Build Coastguard Worker }
709*890232f2SAndroid Build Coastguard Worker
710*890232f2SAndroid Build Coastguard Worker // Save out the generated code for a Lua Table type.
SaveType(const Definition & def,const std::string & classcode,bool needs_imports)711*890232f2SAndroid Build Coastguard Worker bool SaveType(const Definition &def, const std::string &classcode,
712*890232f2SAndroid Build Coastguard Worker bool needs_imports) {
713*890232f2SAndroid Build Coastguard Worker if (!classcode.length()) return true;
714*890232f2SAndroid Build Coastguard Worker
715*890232f2SAndroid Build Coastguard Worker std::string namespace_dir = path_;
716*890232f2SAndroid Build Coastguard Worker auto &namespaces = def.defined_namespace->components;
717*890232f2SAndroid Build Coastguard Worker for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
718*890232f2SAndroid Build Coastguard Worker if (it != namespaces.begin()) namespace_dir += kPathSeparator;
719*890232f2SAndroid Build Coastguard Worker namespace_dir += *it;
720*890232f2SAndroid Build Coastguard Worker // std::string init_py_filename = namespace_dir + "/__init__.py";
721*890232f2SAndroid Build Coastguard Worker // SaveFile(init_py_filename.c_str(), "", false);
722*890232f2SAndroid Build Coastguard Worker }
723*890232f2SAndroid Build Coastguard Worker
724*890232f2SAndroid Build Coastguard Worker std::string code = "";
725*890232f2SAndroid Build Coastguard Worker BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
726*890232f2SAndroid Build Coastguard Worker code += classcode;
727*890232f2SAndroid Build Coastguard Worker code += "\n";
728*890232f2SAndroid Build Coastguard Worker code +=
729*890232f2SAndroid Build Coastguard Worker "return " + NormalizedName(def) + " " + Comment + "return the module";
730*890232f2SAndroid Build Coastguard Worker std::string filename =
731*890232f2SAndroid Build Coastguard Worker NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua";
732*890232f2SAndroid Build Coastguard Worker return SaveFile(filename.c_str(), code, false);
733*890232f2SAndroid Build Coastguard Worker }
734*890232f2SAndroid Build Coastguard Worker
735*890232f2SAndroid Build Coastguard Worker private:
736*890232f2SAndroid Build Coastguard Worker std::unordered_set<std::string> keywords_;
737*890232f2SAndroid Build Coastguard Worker };
738*890232f2SAndroid Build Coastguard Worker
739*890232f2SAndroid Build Coastguard Worker } // namespace lua
740*890232f2SAndroid Build Coastguard Worker
GenerateLua(const Parser & parser,const std::string & path,const std::string & file_name)741*890232f2SAndroid Build Coastguard Worker bool GenerateLua(const Parser &parser, const std::string &path,
742*890232f2SAndroid Build Coastguard Worker const std::string &file_name) {
743*890232f2SAndroid Build Coastguard Worker lua::LuaGenerator generator(parser, path, file_name);
744*890232f2SAndroid Build Coastguard Worker return generator.generate();
745*890232f2SAndroid Build Coastguard Worker }
746*890232f2SAndroid Build Coastguard Worker
747*890232f2SAndroid Build Coastguard Worker } // namespace flatbuffers
748