1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker * Copyright 2021 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 #include "bfbs_gen_lua.h"
18*890232f2SAndroid Build Coastguard Worker
19*890232f2SAndroid Build Coastguard Worker #include <cstdint>
20*890232f2SAndroid Build Coastguard Worker #include <map>
21*890232f2SAndroid Build Coastguard Worker #include <memory>
22*890232f2SAndroid Build Coastguard Worker #include <string>
23*890232f2SAndroid Build Coastguard Worker #include <unordered_set>
24*890232f2SAndroid Build Coastguard Worker #include <vector>
25*890232f2SAndroid Build Coastguard Worker
26*890232f2SAndroid Build Coastguard Worker // Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK.
27*890232f2SAndroid Build Coastguard Worker #include "bfbs_gen.h"
28*890232f2SAndroid Build Coastguard Worker #include "bfbs_namer.h"
29*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/bfbs_generator.h"
30*890232f2SAndroid Build Coastguard Worker
31*890232f2SAndroid Build Coastguard Worker // The intermediate representation schema.
32*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/reflection.h"
33*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/reflection_generated.h"
34*890232f2SAndroid Build Coastguard Worker
35*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
36*890232f2SAndroid Build Coastguard Worker namespace {
37*890232f2SAndroid Build Coastguard Worker
38*890232f2SAndroid Build Coastguard Worker // To reduce typing
39*890232f2SAndroid Build Coastguard Worker namespace r = ::reflection;
40*890232f2SAndroid Build Coastguard Worker
LuaKeywords()41*890232f2SAndroid Build Coastguard Worker std::set<std::string> LuaKeywords() {
42*890232f2SAndroid Build Coastguard Worker return { "and", "break", "do", "else", "elseif", "end",
43*890232f2SAndroid Build Coastguard Worker "false", "for", "function", "goto", "if", "in",
44*890232f2SAndroid Build Coastguard Worker "local", "nil", "not", "or", "repeat", "return",
45*890232f2SAndroid Build Coastguard Worker "then", "true", "until", "while" };
46*890232f2SAndroid Build Coastguard Worker }
47*890232f2SAndroid Build Coastguard Worker
LuaDefaultConfig()48*890232f2SAndroid Build Coastguard Worker Namer::Config LuaDefaultConfig() {
49*890232f2SAndroid Build Coastguard Worker return { /*types=*/Case::kUpperCamel,
50*890232f2SAndroid Build Coastguard Worker /*constants=*/Case::kUnknown,
51*890232f2SAndroid Build Coastguard Worker /*methods=*/Case::kUpperCamel,
52*890232f2SAndroid Build Coastguard Worker /*functions=*/Case::kUpperCamel,
53*890232f2SAndroid Build Coastguard Worker /*fields=*/Case::kUpperCamel,
54*890232f2SAndroid Build Coastguard Worker /*variables=*/Case::kLowerCamel,
55*890232f2SAndroid Build Coastguard Worker /*variants=*/Case::kKeep,
56*890232f2SAndroid Build Coastguard Worker /*enum_variant_seperator=*/"",
57*890232f2SAndroid Build Coastguard Worker /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
58*890232f2SAndroid Build Coastguard Worker /*namespaces=*/Case::kKeep,
59*890232f2SAndroid Build Coastguard Worker /*namespace_seperator=*/"__",
60*890232f2SAndroid Build Coastguard Worker /*object_prefix=*/"",
61*890232f2SAndroid Build Coastguard Worker /*object_suffix=*/"",
62*890232f2SAndroid Build Coastguard Worker /*keyword_prefix=*/"",
63*890232f2SAndroid Build Coastguard Worker /*keyword_suffix=*/"_",
64*890232f2SAndroid Build Coastguard Worker /*filenames=*/Case::kKeep,
65*890232f2SAndroid Build Coastguard Worker /*directories=*/Case::kKeep,
66*890232f2SAndroid Build Coastguard Worker /*output_path=*/"",
67*890232f2SAndroid Build Coastguard Worker /*filename_suffix=*/"",
68*890232f2SAndroid Build Coastguard Worker /*filename_extension=*/".lua" };
69*890232f2SAndroid Build Coastguard Worker }
70*890232f2SAndroid Build Coastguard Worker
71*890232f2SAndroid Build Coastguard Worker class LuaBfbsGenerator : public BaseBfbsGenerator {
72*890232f2SAndroid Build Coastguard Worker public:
LuaBfbsGenerator(const std::string & flatc_version)73*890232f2SAndroid Build Coastguard Worker explicit LuaBfbsGenerator(const std::string &flatc_version)
74*890232f2SAndroid Build Coastguard Worker : BaseBfbsGenerator(),
75*890232f2SAndroid Build Coastguard Worker keywords_(),
76*890232f2SAndroid Build Coastguard Worker requires_(),
77*890232f2SAndroid Build Coastguard Worker current_obj_(nullptr),
78*890232f2SAndroid Build Coastguard Worker current_enum_(nullptr),
79*890232f2SAndroid Build Coastguard Worker flatc_version_(flatc_version),
80*890232f2SAndroid Build Coastguard Worker namer_(LuaDefaultConfig(), LuaKeywords()) {}
81*890232f2SAndroid Build Coastguard Worker
GenerateFromSchema(const r::Schema * schema)82*890232f2SAndroid Build Coastguard Worker GeneratorStatus GenerateFromSchema(const r::Schema *schema)
83*890232f2SAndroid Build Coastguard Worker FLATBUFFERS_OVERRIDE {
84*890232f2SAndroid Build Coastguard Worker if (!GenerateEnums(schema->enums())) { return FAILED; }
85*890232f2SAndroid Build Coastguard Worker if (!GenerateObjects(schema->objects(), schema->root_table())) {
86*890232f2SAndroid Build Coastguard Worker return FAILED;
87*890232f2SAndroid Build Coastguard Worker }
88*890232f2SAndroid Build Coastguard Worker return OK;
89*890232f2SAndroid Build Coastguard Worker }
90*890232f2SAndroid Build Coastguard Worker
SupportedAdvancedFeatures() const91*890232f2SAndroid Build Coastguard Worker uint64_t SupportedAdvancedFeatures() const FLATBUFFERS_OVERRIDE {
92*890232f2SAndroid Build Coastguard Worker return 0xF;
93*890232f2SAndroid Build Coastguard Worker }
94*890232f2SAndroid Build Coastguard Worker
95*890232f2SAndroid Build Coastguard Worker protected:
GenerateEnums(const flatbuffers::Vector<flatbuffers::Offset<r::Enum>> * enums)96*890232f2SAndroid Build Coastguard Worker bool GenerateEnums(
97*890232f2SAndroid Build Coastguard Worker const flatbuffers::Vector<flatbuffers::Offset<r::Enum>> *enums) {
98*890232f2SAndroid Build Coastguard Worker ForAllEnums(enums, [&](const r::Enum *enum_def) {
99*890232f2SAndroid Build Coastguard Worker std::string code;
100*890232f2SAndroid Build Coastguard Worker
101*890232f2SAndroid Build Coastguard Worker StartCodeBlock(enum_def);
102*890232f2SAndroid Build Coastguard Worker
103*890232f2SAndroid Build Coastguard Worker std::string ns;
104*890232f2SAndroid Build Coastguard Worker const std::string enum_name =
105*890232f2SAndroid Build Coastguard Worker namer_.Type(namer_.Denamespace(enum_def, ns));
106*890232f2SAndroid Build Coastguard Worker
107*890232f2SAndroid Build Coastguard Worker GenerateDocumentation(enum_def->documentation(), "", code);
108*890232f2SAndroid Build Coastguard Worker code += "local " + enum_name + " = {\n";
109*890232f2SAndroid Build Coastguard Worker
110*890232f2SAndroid Build Coastguard Worker ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) {
111*890232f2SAndroid Build Coastguard Worker GenerateDocumentation(enum_val->documentation(), " ", code);
112*890232f2SAndroid Build Coastguard Worker code += " " + namer_.Variant(enum_val->name()->str()) + " = " +
113*890232f2SAndroid Build Coastguard Worker NumToString(enum_val->value()) + ",\n";
114*890232f2SAndroid Build Coastguard Worker });
115*890232f2SAndroid Build Coastguard Worker code += "}\n";
116*890232f2SAndroid Build Coastguard Worker code += "\n";
117*890232f2SAndroid Build Coastguard Worker
118*890232f2SAndroid Build Coastguard Worker EmitCodeBlock(code, enum_name, ns, enum_def->declaration_file()->str());
119*890232f2SAndroid Build Coastguard Worker });
120*890232f2SAndroid Build Coastguard Worker return true;
121*890232f2SAndroid Build Coastguard Worker }
122*890232f2SAndroid Build Coastguard Worker
GenerateObjects(const flatbuffers::Vector<flatbuffers::Offset<r::Object>> * objects,const r::Object * root_object)123*890232f2SAndroid Build Coastguard Worker bool GenerateObjects(
124*890232f2SAndroid Build Coastguard Worker const flatbuffers::Vector<flatbuffers::Offset<r::Object>> *objects,
125*890232f2SAndroid Build Coastguard Worker const r::Object *root_object) {
126*890232f2SAndroid Build Coastguard Worker ForAllObjects(objects, [&](const r::Object *object) {
127*890232f2SAndroid Build Coastguard Worker std::string code;
128*890232f2SAndroid Build Coastguard Worker
129*890232f2SAndroid Build Coastguard Worker StartCodeBlock(object);
130*890232f2SAndroid Build Coastguard Worker
131*890232f2SAndroid Build Coastguard Worker // Register the main flatbuffers module.
132*890232f2SAndroid Build Coastguard Worker RegisterRequires("flatbuffers", "flatbuffers");
133*890232f2SAndroid Build Coastguard Worker
134*890232f2SAndroid Build Coastguard Worker std::string ns;
135*890232f2SAndroid Build Coastguard Worker const std::string object_name =
136*890232f2SAndroid Build Coastguard Worker namer_.Type(namer_.Denamespace(object, ns));
137*890232f2SAndroid Build Coastguard Worker
138*890232f2SAndroid Build Coastguard Worker GenerateDocumentation(object->documentation(), "", code);
139*890232f2SAndroid Build Coastguard Worker
140*890232f2SAndroid Build Coastguard Worker code += "local " + object_name + " = {}\n";
141*890232f2SAndroid Build Coastguard Worker code += "local mt = {}\n";
142*890232f2SAndroid Build Coastguard Worker code += "\n";
143*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".New()\n";
144*890232f2SAndroid Build Coastguard Worker code += " local o = {}\n";
145*890232f2SAndroid Build Coastguard Worker code += " setmetatable(o, {__index = mt})\n";
146*890232f2SAndroid Build Coastguard Worker code += " return o\n";
147*890232f2SAndroid Build Coastguard Worker code += "end\n";
148*890232f2SAndroid Build Coastguard Worker code += "\n";
149*890232f2SAndroid Build Coastguard Worker
150*890232f2SAndroid Build Coastguard Worker if (object == root_object) {
151*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".GetRootAs" + object_name +
152*890232f2SAndroid Build Coastguard Worker "(buf, offset)\n";
153*890232f2SAndroid Build Coastguard Worker code += " if type(buf) == \"string\" then\n";
154*890232f2SAndroid Build Coastguard Worker code += " buf = flatbuffers.binaryArray.New(buf)\n";
155*890232f2SAndroid Build Coastguard Worker code += " end\n";
156*890232f2SAndroid Build Coastguard Worker code += "\n";
157*890232f2SAndroid Build Coastguard Worker code += " local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
158*890232f2SAndroid Build Coastguard Worker code += " local o = " + object_name + ".New()\n";
159*890232f2SAndroid Build Coastguard Worker code += " o:Init(buf, n + offset)\n";
160*890232f2SAndroid Build Coastguard Worker code += " return o\n";
161*890232f2SAndroid Build Coastguard Worker code += "end\n";
162*890232f2SAndroid Build Coastguard Worker code += "\n";
163*890232f2SAndroid Build Coastguard Worker }
164*890232f2SAndroid Build Coastguard Worker
165*890232f2SAndroid Build Coastguard Worker // Generates a init method that receives a pre-existing accessor object,
166*890232f2SAndroid Build Coastguard Worker // so that objects can be reused.
167*890232f2SAndroid Build Coastguard Worker
168*890232f2SAndroid Build Coastguard Worker code += "function mt:Init(buf, pos)\n";
169*890232f2SAndroid Build Coastguard Worker code += " self.view = flatbuffers.view.New(buf, pos)\n";
170*890232f2SAndroid Build Coastguard Worker code += "end\n";
171*890232f2SAndroid Build Coastguard Worker code += "\n";
172*890232f2SAndroid Build Coastguard Worker
173*890232f2SAndroid Build Coastguard Worker // Create all the field accessors.
174*890232f2SAndroid Build Coastguard Worker ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
175*890232f2SAndroid Build Coastguard Worker // Skip writing deprecated fields altogether.
176*890232f2SAndroid Build Coastguard Worker if (field->deprecated()) { return; }
177*890232f2SAndroid Build Coastguard Worker
178*890232f2SAndroid Build Coastguard Worker const std::string field_name = namer_.Field(field->name()->str());
179*890232f2SAndroid Build Coastguard Worker const r::BaseType base_type = field->type()->base_type();
180*890232f2SAndroid Build Coastguard Worker
181*890232f2SAndroid Build Coastguard Worker // Generate some fixed strings so we don't repeat outselves later.
182*890232f2SAndroid Build Coastguard Worker const std::string getter_signature =
183*890232f2SAndroid Build Coastguard Worker "function mt:" + field_name + "()\n";
184*890232f2SAndroid Build Coastguard Worker const std::string offset_prefix = "local o = self.view:Offset(" +
185*890232f2SAndroid Build Coastguard Worker NumToString(field->offset()) + ")\n";
186*890232f2SAndroid Build Coastguard Worker const std::string offset_prefix_2 = "if o ~= 0 then\n";
187*890232f2SAndroid Build Coastguard Worker
188*890232f2SAndroid Build Coastguard Worker GenerateDocumentation(field->documentation(), "", code);
189*890232f2SAndroid Build Coastguard Worker
190*890232f2SAndroid Build Coastguard Worker if (IsScalar(base_type)) {
191*890232f2SAndroid Build Coastguard Worker code += getter_signature;
192*890232f2SAndroid Build Coastguard Worker
193*890232f2SAndroid Build Coastguard Worker if (object->is_struct()) {
194*890232f2SAndroid Build Coastguard Worker // TODO(derekbailey): it would be nice to modify the view:Get to
195*890232f2SAndroid Build Coastguard Worker // just pass in the offset and not have to add it its own
196*890232f2SAndroid Build Coastguard Worker // self.view.pos.
197*890232f2SAndroid Build Coastguard Worker code += " return " + GenerateGetter(field->type()) +
198*890232f2SAndroid Build Coastguard Worker "self.view.pos + " + NumToString(field->offset()) + ")\n";
199*890232f2SAndroid Build Coastguard Worker } else {
200*890232f2SAndroid Build Coastguard Worker // Table accessors
201*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix;
202*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix_2;
203*890232f2SAndroid Build Coastguard Worker
204*890232f2SAndroid Build Coastguard Worker std::string getter =
205*890232f2SAndroid Build Coastguard Worker GenerateGetter(field->type()) + "self.view.pos + o)";
206*890232f2SAndroid Build Coastguard Worker if (IsBool(base_type)) { getter = "(" + getter + " ~=0)"; }
207*890232f2SAndroid Build Coastguard Worker code += " return " + getter + "\n";
208*890232f2SAndroid Build Coastguard Worker code += " end\n";
209*890232f2SAndroid Build Coastguard Worker code += " return " + DefaultValue(field) + "\n";
210*890232f2SAndroid Build Coastguard Worker }
211*890232f2SAndroid Build Coastguard Worker code += "end\n";
212*890232f2SAndroid Build Coastguard Worker code += "\n";
213*890232f2SAndroid Build Coastguard Worker } else {
214*890232f2SAndroid Build Coastguard Worker switch (base_type) {
215*890232f2SAndroid Build Coastguard Worker case r::String: {
216*890232f2SAndroid Build Coastguard Worker code += getter_signature;
217*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix;
218*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix_2;
219*890232f2SAndroid Build Coastguard Worker code += " return " + GenerateGetter(field->type()) +
220*890232f2SAndroid Build Coastguard Worker "self.view.pos + o)\n";
221*890232f2SAndroid Build Coastguard Worker code += " end\n";
222*890232f2SAndroid Build Coastguard Worker code += "end\n";
223*890232f2SAndroid Build Coastguard Worker code += "\n";
224*890232f2SAndroid Build Coastguard Worker break;
225*890232f2SAndroid Build Coastguard Worker }
226*890232f2SAndroid Build Coastguard Worker case r::Obj: {
227*890232f2SAndroid Build Coastguard Worker if (object->is_struct()) {
228*890232f2SAndroid Build Coastguard Worker code += "function mt:" + field_name + "(obj)\n";
229*890232f2SAndroid Build Coastguard Worker code += " obj:Init(self.view.bytes, self.view.pos + " +
230*890232f2SAndroid Build Coastguard Worker NumToString(field->offset()) + ")\n";
231*890232f2SAndroid Build Coastguard Worker code += " return obj\n";
232*890232f2SAndroid Build Coastguard Worker code += "end\n";
233*890232f2SAndroid Build Coastguard Worker code += "\n";
234*890232f2SAndroid Build Coastguard Worker } else {
235*890232f2SAndroid Build Coastguard Worker code += getter_signature;
236*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix;
237*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix_2;
238*890232f2SAndroid Build Coastguard Worker
239*890232f2SAndroid Build Coastguard Worker const r::Object *field_object = GetObject(field->type());
240*890232f2SAndroid Build Coastguard Worker if (!field_object) {
241*890232f2SAndroid Build Coastguard Worker // TODO(derekbailey): this is an error condition. we
242*890232f2SAndroid Build Coastguard Worker // should report it better.
243*890232f2SAndroid Build Coastguard Worker return;
244*890232f2SAndroid Build Coastguard Worker }
245*890232f2SAndroid Build Coastguard Worker code += " local x = " +
246*890232f2SAndroid Build Coastguard Worker std::string(
247*890232f2SAndroid Build Coastguard Worker field_object->is_struct()
248*890232f2SAndroid Build Coastguard Worker ? "self.view.pos + o\n"
249*890232f2SAndroid Build Coastguard Worker : "self.view:Indirect(self.view.pos + o)\n");
250*890232f2SAndroid Build Coastguard Worker const std::string require_name = RegisterRequires(field);
251*890232f2SAndroid Build Coastguard Worker code += " local obj = " + require_name + ".New()\n";
252*890232f2SAndroid Build Coastguard Worker code += " obj:Init(self.view.bytes, x)\n";
253*890232f2SAndroid Build Coastguard Worker code += " return obj\n";
254*890232f2SAndroid Build Coastguard Worker code += " end\n";
255*890232f2SAndroid Build Coastguard Worker code += "end\n";
256*890232f2SAndroid Build Coastguard Worker code += "\n";
257*890232f2SAndroid Build Coastguard Worker }
258*890232f2SAndroid Build Coastguard Worker break;
259*890232f2SAndroid Build Coastguard Worker }
260*890232f2SAndroid Build Coastguard Worker case r::Union: {
261*890232f2SAndroid Build Coastguard Worker code += getter_signature;
262*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix;
263*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix_2;
264*890232f2SAndroid Build Coastguard Worker code +=
265*890232f2SAndroid Build Coastguard Worker " local obj = "
266*890232f2SAndroid Build Coastguard Worker "flatbuffers.view.New(flatbuffers.binaryArray.New("
267*890232f2SAndroid Build Coastguard Worker "0), 0)\n";
268*890232f2SAndroid Build Coastguard Worker code += " " + GenerateGetter(field->type()) + "obj, o)\n";
269*890232f2SAndroid Build Coastguard Worker code += " return obj\n";
270*890232f2SAndroid Build Coastguard Worker code += " end\n";
271*890232f2SAndroid Build Coastguard Worker code += "end\n";
272*890232f2SAndroid Build Coastguard Worker code += "\n";
273*890232f2SAndroid Build Coastguard Worker break;
274*890232f2SAndroid Build Coastguard Worker }
275*890232f2SAndroid Build Coastguard Worker case r::Array:
276*890232f2SAndroid Build Coastguard Worker case r::Vector: {
277*890232f2SAndroid Build Coastguard Worker const r::BaseType vector_base_type = field->type()->element();
278*890232f2SAndroid Build Coastguard Worker int32_t element_size = field->type()->element_size();
279*890232f2SAndroid Build Coastguard Worker code += "function mt:" + field_name + "(j)\n";
280*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix;
281*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix_2;
282*890232f2SAndroid Build Coastguard Worker
283*890232f2SAndroid Build Coastguard Worker if (IsStructOrTable(vector_base_type)) {
284*890232f2SAndroid Build Coastguard Worker code += " local x = self.view:Vector(o)\n";
285*890232f2SAndroid Build Coastguard Worker code +=
286*890232f2SAndroid Build Coastguard Worker " x = x + ((j-1) * " + NumToString(element_size) + ")\n";
287*890232f2SAndroid Build Coastguard Worker if (IsTable(field->type(), /*use_element=*/true)) {
288*890232f2SAndroid Build Coastguard Worker code += " x = self.view:Indirect(x)\n";
289*890232f2SAndroid Build Coastguard Worker } else {
290*890232f2SAndroid Build Coastguard Worker // Vector of structs are inline, so we need to query the
291*890232f2SAndroid Build Coastguard Worker // size of the struct.
292*890232f2SAndroid Build Coastguard Worker const reflection::Object *obj =
293*890232f2SAndroid Build Coastguard Worker GetObjectByIndex(field->type()->index());
294*890232f2SAndroid Build Coastguard Worker element_size = obj->bytesize();
295*890232f2SAndroid Build Coastguard Worker }
296*890232f2SAndroid Build Coastguard Worker
297*890232f2SAndroid Build Coastguard Worker // Include the referenced type, thus we need to make sure
298*890232f2SAndroid Build Coastguard Worker // we set `use_element` to true.
299*890232f2SAndroid Build Coastguard Worker const std::string require_name =
300*890232f2SAndroid Build Coastguard Worker RegisterRequires(field, /*use_element=*/true);
301*890232f2SAndroid Build Coastguard Worker code += " local obj = " + require_name + ".New()\n";
302*890232f2SAndroid Build Coastguard Worker code += " obj:Init(self.view.bytes, x)\n";
303*890232f2SAndroid Build Coastguard Worker code += " return obj\n";
304*890232f2SAndroid Build Coastguard Worker } else {
305*890232f2SAndroid Build Coastguard Worker code += " local a = self.view:Vector(o)\n";
306*890232f2SAndroid Build Coastguard Worker code += " return " + GenerateGetter(field->type()) +
307*890232f2SAndroid Build Coastguard Worker "a + ((j-1) * " + NumToString(element_size) + "))\n";
308*890232f2SAndroid Build Coastguard Worker }
309*890232f2SAndroid Build Coastguard Worker code += " end\n";
310*890232f2SAndroid Build Coastguard Worker // Only generate a default value for those types that are
311*890232f2SAndroid Build Coastguard Worker // supported.
312*890232f2SAndroid Build Coastguard Worker if (!IsStructOrTable(vector_base_type)) {
313*890232f2SAndroid Build Coastguard Worker code +=
314*890232f2SAndroid Build Coastguard Worker " return " +
315*890232f2SAndroid Build Coastguard Worker std::string(vector_base_type == r::String ? "''\n" : "0\n");
316*890232f2SAndroid Build Coastguard Worker }
317*890232f2SAndroid Build Coastguard Worker code += "end\n";
318*890232f2SAndroid Build Coastguard Worker code += "\n";
319*890232f2SAndroid Build Coastguard Worker
320*890232f2SAndroid Build Coastguard Worker // If the vector is composed of single byte values, we
321*890232f2SAndroid Build Coastguard Worker // generate a helper function to get it as a byte string in
322*890232f2SAndroid Build Coastguard Worker // Lua.
323*890232f2SAndroid Build Coastguard Worker if (IsSingleByte(vector_base_type)) {
324*890232f2SAndroid Build Coastguard Worker code += "function mt:" + field_name + "AsString(start, stop)\n";
325*890232f2SAndroid Build Coastguard Worker code += " return self.view:VectorAsString(" +
326*890232f2SAndroid Build Coastguard Worker NumToString(field->offset()) + ", start, stop)\n";
327*890232f2SAndroid Build Coastguard Worker code += "end\n";
328*890232f2SAndroid Build Coastguard Worker code += "\n";
329*890232f2SAndroid Build Coastguard Worker }
330*890232f2SAndroid Build Coastguard Worker
331*890232f2SAndroid Build Coastguard Worker // We also make a new accessor to query just the length of the
332*890232f2SAndroid Build Coastguard Worker // vector.
333*890232f2SAndroid Build Coastguard Worker code += "function mt:" + field_name + "Length()\n";
334*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix;
335*890232f2SAndroid Build Coastguard Worker code += " " + offset_prefix_2;
336*890232f2SAndroid Build Coastguard Worker code += " return self.view:VectorLen(o)\n";
337*890232f2SAndroid Build Coastguard Worker code += " end\n";
338*890232f2SAndroid Build Coastguard Worker code += " return 0\n";
339*890232f2SAndroid Build Coastguard Worker code += "end\n";
340*890232f2SAndroid Build Coastguard Worker code += "\n";
341*890232f2SAndroid Build Coastguard Worker break;
342*890232f2SAndroid Build Coastguard Worker }
343*890232f2SAndroid Build Coastguard Worker default: {
344*890232f2SAndroid Build Coastguard Worker return;
345*890232f2SAndroid Build Coastguard Worker }
346*890232f2SAndroid Build Coastguard Worker }
347*890232f2SAndroid Build Coastguard Worker }
348*890232f2SAndroid Build Coastguard Worker return;
349*890232f2SAndroid Build Coastguard Worker });
350*890232f2SAndroid Build Coastguard Worker
351*890232f2SAndroid Build Coastguard Worker // Create all the builders
352*890232f2SAndroid Build Coastguard Worker if (object->is_struct()) {
353*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".Create" + object_name +
354*890232f2SAndroid Build Coastguard Worker "(builder" + GenerateStructBuilderArgs(object) + ")\n";
355*890232f2SAndroid Build Coastguard Worker code += AppendStructBuilderBody(object);
356*890232f2SAndroid Build Coastguard Worker code += " return builder:Offset()\n";
357*890232f2SAndroid Build Coastguard Worker code += "end\n";
358*890232f2SAndroid Build Coastguard Worker code += "\n";
359*890232f2SAndroid Build Coastguard Worker } else {
360*890232f2SAndroid Build Coastguard Worker // Table builders
361*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".Start(builder)\n";
362*890232f2SAndroid Build Coastguard Worker code += " builder:StartObject(" +
363*890232f2SAndroid Build Coastguard Worker NumToString(object->fields()->size()) + ")\n";
364*890232f2SAndroid Build Coastguard Worker code += "end\n";
365*890232f2SAndroid Build Coastguard Worker code += "\n";
366*890232f2SAndroid Build Coastguard Worker
367*890232f2SAndroid Build Coastguard Worker ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
368*890232f2SAndroid Build Coastguard Worker if (field->deprecated()) { return; }
369*890232f2SAndroid Build Coastguard Worker
370*890232f2SAndroid Build Coastguard Worker const std::string field_name = namer_.Field(field->name()->str());
371*890232f2SAndroid Build Coastguard Worker const std::string variable_name =
372*890232f2SAndroid Build Coastguard Worker namer_.Variable(field->name()->str());
373*890232f2SAndroid Build Coastguard Worker
374*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".Add" + field_name +
375*890232f2SAndroid Build Coastguard Worker "(builder, " + variable_name + ")\n";
376*890232f2SAndroid Build Coastguard Worker code += " builder:Prepend" + GenerateMethod(field) + "Slot(" +
377*890232f2SAndroid Build Coastguard Worker NumToString(field->id()) + ", " + variable_name + ", " +
378*890232f2SAndroid Build Coastguard Worker DefaultValue(field) + ")\n";
379*890232f2SAndroid Build Coastguard Worker code += "end\n";
380*890232f2SAndroid Build Coastguard Worker code += "\n";
381*890232f2SAndroid Build Coastguard Worker
382*890232f2SAndroid Build Coastguard Worker if (IsVector(field->type()->base_type())) {
383*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".Start" + field_name +
384*890232f2SAndroid Build Coastguard Worker "Vector(builder, numElems)\n";
385*890232f2SAndroid Build Coastguard Worker
386*890232f2SAndroid Build Coastguard Worker const int32_t element_size = field->type()->element_size();
387*890232f2SAndroid Build Coastguard Worker int32_t alignment = 0;
388*890232f2SAndroid Build Coastguard Worker if (IsStruct(field->type(), /*use_element=*/true)) {
389*890232f2SAndroid Build Coastguard Worker alignment = GetObjectByIndex(field->type()->index())->minalign();
390*890232f2SAndroid Build Coastguard Worker } else {
391*890232f2SAndroid Build Coastguard Worker alignment = element_size;
392*890232f2SAndroid Build Coastguard Worker }
393*890232f2SAndroid Build Coastguard Worker
394*890232f2SAndroid Build Coastguard Worker code += " return builder:StartVector(" +
395*890232f2SAndroid Build Coastguard Worker NumToString(element_size) + ", numElems, " +
396*890232f2SAndroid Build Coastguard Worker NumToString(alignment) + ")\n";
397*890232f2SAndroid Build Coastguard Worker code += "end\n";
398*890232f2SAndroid Build Coastguard Worker code += "\n";
399*890232f2SAndroid Build Coastguard Worker }
400*890232f2SAndroid Build Coastguard Worker });
401*890232f2SAndroid Build Coastguard Worker
402*890232f2SAndroid Build Coastguard Worker code += "function " + object_name + ".End(builder)\n";
403*890232f2SAndroid Build Coastguard Worker code += " return builder:EndObject()\n";
404*890232f2SAndroid Build Coastguard Worker code += "end\n";
405*890232f2SAndroid Build Coastguard Worker code += "\n";
406*890232f2SAndroid Build Coastguard Worker }
407*890232f2SAndroid Build Coastguard Worker
408*890232f2SAndroid Build Coastguard Worker EmitCodeBlock(code, object_name, ns, object->declaration_file()->str());
409*890232f2SAndroid Build Coastguard Worker });
410*890232f2SAndroid Build Coastguard Worker return true;
411*890232f2SAndroid Build Coastguard Worker }
412*890232f2SAndroid Build Coastguard Worker
413*890232f2SAndroid Build Coastguard Worker private:
GenerateDocumentation(const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> * documentation,std::string indent,std::string & code) const414*890232f2SAndroid Build Coastguard Worker void GenerateDocumentation(
415*890232f2SAndroid Build Coastguard Worker const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
416*890232f2SAndroid Build Coastguard Worker *documentation,
417*890232f2SAndroid Build Coastguard Worker std::string indent, std::string &code) const {
418*890232f2SAndroid Build Coastguard Worker flatbuffers::ForAllDocumentation(
419*890232f2SAndroid Build Coastguard Worker documentation, [&](const flatbuffers::String *str) {
420*890232f2SAndroid Build Coastguard Worker code += indent + "--" + str->str() + "\n";
421*890232f2SAndroid Build Coastguard Worker });
422*890232f2SAndroid Build Coastguard Worker }
423*890232f2SAndroid Build Coastguard Worker
GenerateStructBuilderArgs(const r::Object * object,std::string prefix="") const424*890232f2SAndroid Build Coastguard Worker std::string GenerateStructBuilderArgs(const r::Object *object,
425*890232f2SAndroid Build Coastguard Worker std::string prefix = "") const {
426*890232f2SAndroid Build Coastguard Worker std::string signature;
427*890232f2SAndroid Build Coastguard Worker ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
428*890232f2SAndroid Build Coastguard Worker if (IsStructOrTable(field->type()->base_type())) {
429*890232f2SAndroid Build Coastguard Worker const r::Object *field_object = GetObject(field->type());
430*890232f2SAndroid Build Coastguard Worker signature += GenerateStructBuilderArgs(
431*890232f2SAndroid Build Coastguard Worker field_object, prefix + namer_.Variable(field->name()->str()) + "_");
432*890232f2SAndroid Build Coastguard Worker } else {
433*890232f2SAndroid Build Coastguard Worker signature += ", " + prefix + namer_.Variable(field->name()->str());
434*890232f2SAndroid Build Coastguard Worker }
435*890232f2SAndroid Build Coastguard Worker });
436*890232f2SAndroid Build Coastguard Worker return signature;
437*890232f2SAndroid Build Coastguard Worker }
438*890232f2SAndroid Build Coastguard Worker
AppendStructBuilderBody(const r::Object * object,std::string prefix="") const439*890232f2SAndroid Build Coastguard Worker std::string AppendStructBuilderBody(const r::Object *object,
440*890232f2SAndroid Build Coastguard Worker std::string prefix = "") const {
441*890232f2SAndroid Build Coastguard Worker std::string code;
442*890232f2SAndroid Build Coastguard Worker code += " builder:Prep(" + NumToString(object->minalign()) + ", " +
443*890232f2SAndroid Build Coastguard Worker NumToString(object->bytesize()) + ")\n";
444*890232f2SAndroid Build Coastguard Worker
445*890232f2SAndroid Build Coastguard Worker // We need to reverse the order we iterate over, since we build the
446*890232f2SAndroid Build Coastguard Worker // buffer backwards.
447*890232f2SAndroid Build Coastguard Worker ForAllFields(object, /*reverse=*/true, [&](const r::Field *field) {
448*890232f2SAndroid Build Coastguard Worker const int32_t num_padding_bytes = field->padding();
449*890232f2SAndroid Build Coastguard Worker if (num_padding_bytes) {
450*890232f2SAndroid Build Coastguard Worker code += " builder:Pad(" + NumToString(num_padding_bytes) + ")\n";
451*890232f2SAndroid Build Coastguard Worker }
452*890232f2SAndroid Build Coastguard Worker if (IsStructOrTable(field->type()->base_type())) {
453*890232f2SAndroid Build Coastguard Worker const r::Object *field_object = GetObject(field->type());
454*890232f2SAndroid Build Coastguard Worker code += AppendStructBuilderBody(
455*890232f2SAndroid Build Coastguard Worker field_object, prefix + namer_.Variable(field->name()->str()) + "_");
456*890232f2SAndroid Build Coastguard Worker } else {
457*890232f2SAndroid Build Coastguard Worker code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix +
458*890232f2SAndroid Build Coastguard Worker namer_.Variable(field->name()->str()) + ")\n";
459*890232f2SAndroid Build Coastguard Worker }
460*890232f2SAndroid Build Coastguard Worker });
461*890232f2SAndroid Build Coastguard Worker
462*890232f2SAndroid Build Coastguard Worker return code;
463*890232f2SAndroid Build Coastguard Worker }
464*890232f2SAndroid Build Coastguard Worker
GenerateMethod(const r::Field * field) const465*890232f2SAndroid Build Coastguard Worker std::string GenerateMethod(const r::Field *field) const {
466*890232f2SAndroid Build Coastguard Worker const r::BaseType base_type = field->type()->base_type();
467*890232f2SAndroid Build Coastguard Worker if (IsScalar(base_type)) { return namer_.Type(GenerateType(base_type)); }
468*890232f2SAndroid Build Coastguard Worker if (IsStructOrTable(base_type)) { return "Struct"; }
469*890232f2SAndroid Build Coastguard Worker return "UOffsetTRelative";
470*890232f2SAndroid Build Coastguard Worker }
471*890232f2SAndroid Build Coastguard Worker
GenerateGetter(const r::Type * type,bool element_type=false) const472*890232f2SAndroid Build Coastguard Worker std::string GenerateGetter(const r::Type *type,
473*890232f2SAndroid Build Coastguard Worker bool element_type = false) const {
474*890232f2SAndroid Build Coastguard Worker switch (element_type ? type->element() : type->base_type()) {
475*890232f2SAndroid Build Coastguard Worker case r::String: return "self.view:String(";
476*890232f2SAndroid Build Coastguard Worker case r::Union: return "self.view:Union(";
477*890232f2SAndroid Build Coastguard Worker case r::Vector: return GenerateGetter(type, true);
478*890232f2SAndroid Build Coastguard Worker default:
479*890232f2SAndroid Build Coastguard Worker return "self.view:Get(flatbuffers.N." +
480*890232f2SAndroid Build Coastguard Worker namer_.Type(GenerateType(type, element_type)) + ", ";
481*890232f2SAndroid Build Coastguard Worker }
482*890232f2SAndroid Build Coastguard Worker }
483*890232f2SAndroid Build Coastguard Worker
GenerateType(const r::Type * type,bool element_type=false) const484*890232f2SAndroid Build Coastguard Worker std::string GenerateType(const r::Type *type,
485*890232f2SAndroid Build Coastguard Worker bool element_type = false) const {
486*890232f2SAndroid Build Coastguard Worker const r::BaseType base_type =
487*890232f2SAndroid Build Coastguard Worker element_type ? type->element() : type->base_type();
488*890232f2SAndroid Build Coastguard Worker if (IsScalar(base_type)) { return GenerateType(base_type); }
489*890232f2SAndroid Build Coastguard Worker switch (base_type) {
490*890232f2SAndroid Build Coastguard Worker case r::String: return "string";
491*890232f2SAndroid Build Coastguard Worker case r::Vector: return GenerateGetter(type, true);
492*890232f2SAndroid Build Coastguard Worker case r::Obj: return namer_.Type(namer_.Denamespace(GetObject(type)));
493*890232f2SAndroid Build Coastguard Worker
494*890232f2SAndroid Build Coastguard Worker default: return "*flatbuffers.Table";
495*890232f2SAndroid Build Coastguard Worker }
496*890232f2SAndroid Build Coastguard Worker }
497*890232f2SAndroid Build Coastguard Worker
GenerateType(const r::BaseType base_type) const498*890232f2SAndroid Build Coastguard Worker std::string GenerateType(const r::BaseType base_type) const {
499*890232f2SAndroid Build Coastguard Worker // Need to override the default naming to match the Lua runtime libraries.
500*890232f2SAndroid Build Coastguard Worker // TODO(derekbailey): make overloads in the runtime libraries to avoid this.
501*890232f2SAndroid Build Coastguard Worker switch (base_type) {
502*890232f2SAndroid Build Coastguard Worker case r::None: return "uint8";
503*890232f2SAndroid Build Coastguard Worker case r::UType: return "uint8";
504*890232f2SAndroid Build Coastguard Worker case r::Byte: return "int8";
505*890232f2SAndroid Build Coastguard Worker case r::UByte: return "uint8";
506*890232f2SAndroid Build Coastguard Worker case r::Short: return "int16";
507*890232f2SAndroid Build Coastguard Worker case r::UShort: return "uint16";
508*890232f2SAndroid Build Coastguard Worker case r::Int: return "int32";
509*890232f2SAndroid Build Coastguard Worker case r::UInt: return "uint32";
510*890232f2SAndroid Build Coastguard Worker case r::Long: return "int64";
511*890232f2SAndroid Build Coastguard Worker case r::ULong: return "uint64";
512*890232f2SAndroid Build Coastguard Worker case r::Float: return "Float32";
513*890232f2SAndroid Build Coastguard Worker case r::Double: return "Float64";
514*890232f2SAndroid Build Coastguard Worker default: return r::EnumNameBaseType(base_type);
515*890232f2SAndroid Build Coastguard Worker }
516*890232f2SAndroid Build Coastguard Worker }
517*890232f2SAndroid Build Coastguard Worker
DefaultValue(const r::Field * field) const518*890232f2SAndroid Build Coastguard Worker std::string DefaultValue(const r::Field *field) const {
519*890232f2SAndroid Build Coastguard Worker const r::BaseType base_type = field->type()->base_type();
520*890232f2SAndroid Build Coastguard Worker if (IsFloatingPoint(base_type)) {
521*890232f2SAndroid Build Coastguard Worker return NumToString(field->default_real());
522*890232f2SAndroid Build Coastguard Worker }
523*890232f2SAndroid Build Coastguard Worker if (IsBool(base_type)) {
524*890232f2SAndroid Build Coastguard Worker return field->default_integer() ? "true" : "false";
525*890232f2SAndroid Build Coastguard Worker }
526*890232f2SAndroid Build Coastguard Worker if (IsScalar(base_type)) { return NumToString((field->default_integer())); }
527*890232f2SAndroid Build Coastguard Worker // represents offsets
528*890232f2SAndroid Build Coastguard Worker return "0";
529*890232f2SAndroid Build Coastguard Worker }
530*890232f2SAndroid Build Coastguard Worker
StartCodeBlock(const reflection::Enum * enum_def)531*890232f2SAndroid Build Coastguard Worker void StartCodeBlock(const reflection::Enum *enum_def) {
532*890232f2SAndroid Build Coastguard Worker current_enum_ = enum_def;
533*890232f2SAndroid Build Coastguard Worker current_obj_ = nullptr;
534*890232f2SAndroid Build Coastguard Worker requires_.clear();
535*890232f2SAndroid Build Coastguard Worker }
536*890232f2SAndroid Build Coastguard Worker
StartCodeBlock(const reflection::Object * object)537*890232f2SAndroid Build Coastguard Worker void StartCodeBlock(const reflection::Object *object) {
538*890232f2SAndroid Build Coastguard Worker current_obj_ = object;
539*890232f2SAndroid Build Coastguard Worker current_enum_ = nullptr;
540*890232f2SAndroid Build Coastguard Worker requires_.clear();
541*890232f2SAndroid Build Coastguard Worker }
542*890232f2SAndroid Build Coastguard Worker
RegisterRequires(const r::Field * field,bool use_element=false)543*890232f2SAndroid Build Coastguard Worker std::string RegisterRequires(const r::Field *field,
544*890232f2SAndroid Build Coastguard Worker bool use_element = false) {
545*890232f2SAndroid Build Coastguard Worker std::string type_name;
546*890232f2SAndroid Build Coastguard Worker
547*890232f2SAndroid Build Coastguard Worker const r::BaseType type =
548*890232f2SAndroid Build Coastguard Worker use_element ? field->type()->element() : field->type()->base_type();
549*890232f2SAndroid Build Coastguard Worker
550*890232f2SAndroid Build Coastguard Worker if (IsStructOrTable(type)) {
551*890232f2SAndroid Build Coastguard Worker const r::Object *object = GetObjectByIndex(field->type()->index());
552*890232f2SAndroid Build Coastguard Worker if (object == current_obj_) { return namer_.Denamespace(object); }
553*890232f2SAndroid Build Coastguard Worker type_name = object->name()->str();
554*890232f2SAndroid Build Coastguard Worker } else {
555*890232f2SAndroid Build Coastguard Worker const r::Enum *enum_def = GetEnumByIndex(field->type()->index());
556*890232f2SAndroid Build Coastguard Worker if (enum_def == current_enum_) { return namer_.Denamespace(enum_def); }
557*890232f2SAndroid Build Coastguard Worker type_name = enum_def->name()->str();
558*890232f2SAndroid Build Coastguard Worker }
559*890232f2SAndroid Build Coastguard Worker
560*890232f2SAndroid Build Coastguard Worker // Prefix with double __ to avoid name clashing, since these are defined
561*890232f2SAndroid Build Coastguard Worker // at the top of the file and have lexical scoping. Replace '.' with '_'
562*890232f2SAndroid Build Coastguard Worker // so it can be a legal identifier.
563*890232f2SAndroid Build Coastguard Worker std::string name = "__" + type_name;
564*890232f2SAndroid Build Coastguard Worker std::replace(name.begin(), name.end(), '.', '_');
565*890232f2SAndroid Build Coastguard Worker
566*890232f2SAndroid Build Coastguard Worker return RegisterRequires(name, type_name);
567*890232f2SAndroid Build Coastguard Worker }
568*890232f2SAndroid Build Coastguard Worker
RegisterRequires(const std::string & local_name,const std::string & requires_name)569*890232f2SAndroid Build Coastguard Worker std::string RegisterRequires(const std::string &local_name,
570*890232f2SAndroid Build Coastguard Worker const std::string &requires_name) {
571*890232f2SAndroid Build Coastguard Worker requires_[local_name] = requires_name;
572*890232f2SAndroid Build Coastguard Worker return local_name;
573*890232f2SAndroid Build Coastguard Worker }
574*890232f2SAndroid Build Coastguard Worker
EmitCodeBlock(const std::string & code_block,const std::string & name,const std::string & ns,const std::string & declaring_file) const575*890232f2SAndroid Build Coastguard Worker void EmitCodeBlock(const std::string &code_block, const std::string &name,
576*890232f2SAndroid Build Coastguard Worker const std::string &ns,
577*890232f2SAndroid Build Coastguard Worker const std::string &declaring_file) const {
578*890232f2SAndroid Build Coastguard Worker const std::string root_type = schema_->root_table()->name()->str();
579*890232f2SAndroid Build Coastguard Worker const std::string root_file =
580*890232f2SAndroid Build Coastguard Worker schema_->root_table()->declaration_file()->str();
581*890232f2SAndroid Build Coastguard Worker const std::string full_qualified_name = ns.empty() ? name : ns + "." + name;
582*890232f2SAndroid Build Coastguard Worker
583*890232f2SAndroid Build Coastguard Worker std::string code = "--[[ " + full_qualified_name + "\n\n";
584*890232f2SAndroid Build Coastguard Worker code +=
585*890232f2SAndroid Build Coastguard Worker " Automatically generated by the FlatBuffers compiler, do not "
586*890232f2SAndroid Build Coastguard Worker "modify.\n";
587*890232f2SAndroid Build Coastguard Worker code += " Or modify. I'm a message, not a cop.\n";
588*890232f2SAndroid Build Coastguard Worker code += "\n";
589*890232f2SAndroid Build Coastguard Worker code += " flatc version: " + flatc_version_ + "\n";
590*890232f2SAndroid Build Coastguard Worker code += "\n";
591*890232f2SAndroid Build Coastguard Worker code += " Declared by : " + declaring_file + "\n";
592*890232f2SAndroid Build Coastguard Worker code += " Rooting type : " + root_type + " (" + root_file + ")\n";
593*890232f2SAndroid Build Coastguard Worker code += "\n--]]\n\n";
594*890232f2SAndroid Build Coastguard Worker
595*890232f2SAndroid Build Coastguard Worker if (!requires_.empty()) {
596*890232f2SAndroid Build Coastguard Worker for (auto it = requires_.cbegin(); it != requires_.cend(); ++it) {
597*890232f2SAndroid Build Coastguard Worker code += "local " + it->first + " = require('" + it->second + "')\n";
598*890232f2SAndroid Build Coastguard Worker }
599*890232f2SAndroid Build Coastguard Worker code += "\n";
600*890232f2SAndroid Build Coastguard Worker }
601*890232f2SAndroid Build Coastguard Worker
602*890232f2SAndroid Build Coastguard Worker code += code_block;
603*890232f2SAndroid Build Coastguard Worker code += "return " + name;
604*890232f2SAndroid Build Coastguard Worker
605*890232f2SAndroid Build Coastguard Worker // Namespaces are '.' deliminted, so replace it with the path separator.
606*890232f2SAndroid Build Coastguard Worker std::string path = ns;
607*890232f2SAndroid Build Coastguard Worker
608*890232f2SAndroid Build Coastguard Worker if (ns.empty()) {
609*890232f2SAndroid Build Coastguard Worker path = ".";
610*890232f2SAndroid Build Coastguard Worker } else {
611*890232f2SAndroid Build Coastguard Worker std::replace(path.begin(), path.end(), '.', '/');
612*890232f2SAndroid Build Coastguard Worker }
613*890232f2SAndroid Build Coastguard Worker
614*890232f2SAndroid Build Coastguard Worker // TODO(derekbailey): figure out a save file without depending on util.h
615*890232f2SAndroid Build Coastguard Worker EnsureDirExists(path);
616*890232f2SAndroid Build Coastguard Worker const std::string file_name = path + "/" + namer_.File(name);
617*890232f2SAndroid Build Coastguard Worker SaveFile(file_name.c_str(), code, false);
618*890232f2SAndroid Build Coastguard Worker }
619*890232f2SAndroid Build Coastguard Worker
620*890232f2SAndroid Build Coastguard Worker std::unordered_set<std::string> keywords_;
621*890232f2SAndroid Build Coastguard Worker std::map<std::string, std::string> requires_;
622*890232f2SAndroid Build Coastguard Worker const r::Object *current_obj_;
623*890232f2SAndroid Build Coastguard Worker const r::Enum *current_enum_;
624*890232f2SAndroid Build Coastguard Worker const std::string flatc_version_;
625*890232f2SAndroid Build Coastguard Worker const BfbsNamer namer_;
626*890232f2SAndroid Build Coastguard Worker };
627*890232f2SAndroid Build Coastguard Worker } // namespace
628*890232f2SAndroid Build Coastguard Worker
NewLuaBfbsGenerator(const std::string & flatc_version)629*890232f2SAndroid Build Coastguard Worker std::unique_ptr<BfbsGenerator> NewLuaBfbsGenerator(
630*890232f2SAndroid Build Coastguard Worker const std::string &flatc_version) {
631*890232f2SAndroid Build Coastguard Worker return std::unique_ptr<LuaBfbsGenerator>(new LuaBfbsGenerator(flatc_version));
632*890232f2SAndroid Build Coastguard Worker }
633*890232f2SAndroid Build Coastguard Worker
634*890232f2SAndroid Build Coastguard Worker } // namespace flatbuffers