summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnass Al <dev@anassinator.com>2020-04-06 09:27:13 -0700
committerGitHub <noreply@github.com>2020-04-06 09:27:13 -0700
commitfb96fadc20a78da264b1878ff95f12838c3b22c8 (patch)
treea38786659ba6eab03c07c521bcb63f878d8fead0
parent408f11fbdd42bedc86e6a69aecdc77c98b39167a (diff)
downloadflatbuffers-fb96fadc20a78da264b1878ff95f12838c3b22c8.tar.gz
flatbuffers-fb96fadc20a78da264b1878ff95f12838c3b22c8.tar.bz2
flatbuffers-fb96fadc20a78da264b1878ff95f12838c3b22c8.zip
[C#] Fix nested structs and arrays in Object API (#5765)
* [C#] Fix nested structs and arrays in Object API The adds support for nested structs and fixed size arrays in the C# Object API codegen which previously generated invalid code that wouldn't compile. - Nested structs would originally generate syntax errors due to adding an additional `.` to separate fields. - Fixed size arrays of nested structs would originally generate code for the first field in the top most struct, and would lead to a compiler error due to referencing undefined variables. * [C#] fix nested structs and arrays of structs. * fix nested structs + arrays * add table support * Cleanup code Co-authored-by: mugisoba <mugisoba+github@icloud.com>
-rw-r--r--src/idl_gen_csharp.cpp168
-rw-r--r--tests/MyGame/Example/Vec3.cs6
2 files changed, 96 insertions, 78 deletions
diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp
index 0bcd132c..96a5da80 100644
--- a/src/idl_gen_csharp.cpp
+++ b/src/idl_gen_csharp.cpp
@@ -38,6 +38,11 @@ static CommentConfig comment_config = {
namespace csharp {
class CSharpGenerator : public BaseGenerator {
+ struct FieldArrayLength {
+ std::string name;
+ int length;
+ };
+
public:
CSharpGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
@@ -1540,6 +1545,15 @@ class CSharpGenerator : public BaseGenerator {
GenOffsetType(*field.value.type.struct_def) +
") : " + GenTypeGet(field.value.type) +
".Pack(builder, _o." + camel_name + ");\n";
+ } else if (struct_def.fixed && struct_has_create) {
+ std::vector<FieldArrayLength> array_lengths;
+ FieldArrayLength tmp_array_length = {
+ field.name,
+ field.value.type.fixed_length,
+ };
+ array_lengths.push_back(tmp_array_length);
+ GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
+ array_lengths);
}
break;
}
@@ -1620,12 +1634,14 @@ class CSharpGenerator : public BaseGenerator {
}
case BASE_TYPE_ARRAY: {
if (field.value.type.struct_def != nullptr) {
- std::vector<std::string> name_vec;
- name_vec.push_back(field.name);
- std::vector<int> array_length_vec;
- array_length_vec.push_back(field.value.type.fixed_length);
- GenArrayPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
- name_vec, array_length_vec);
+ std::vector<FieldArrayLength> array_lengths;
+ FieldArrayLength tmp_array_length = {
+ field.name,
+ field.value.type.fixed_length,
+ };
+ array_lengths.push_back(tmp_array_length);
+ GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
+ array_lengths);
} else {
code += " var _" + field.name + " = _o." + camel_name + ";\n";
}
@@ -1656,8 +1672,9 @@ class CSharpGenerator : public BaseGenerator {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (struct_def.fixed) {
- GenStructArgs_ObjectAPI(*field.value.type.struct_def, code_ptr,
- " _o." + camel_name + ".");
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
+ code_ptr,
+ " _" + field.name + "_");
} else {
code += ",\n";
if (field.value.type.struct_def->fixed) {
@@ -1674,8 +1691,9 @@ class CSharpGenerator : public BaseGenerator {
}
case BASE_TYPE_ARRAY: {
if (field.value.type.struct_def != nullptr) {
- GenArrayPackCall_ObjectAPI(*field.value.type.struct_def, code_ptr,
- " _" + field.name + "_");
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
+ code_ptr,
+ " _" + field.name + "_");
} else {
code += ",\n";
code += " _" + field.name;
@@ -1745,28 +1763,9 @@ class CSharpGenerator : public BaseGenerator {
code += " }\n";
}
- void GenStructArgs_ObjectAPI(const StructDef &struct_def,
- std::string *code_ptr,
- std::string prefix) const {
- auto &code = *code_ptr;
- for (auto it = struct_def.fields.vec.begin();
- it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
- const auto &field_type = field.value.type;
- if (IsStruct(field_type)) {
- GenStructArgs_ObjectAPI(*field_type.struct_def, code_ptr,
- prefix + "." + MakeCamel(field.name) + ".");
- } else {
- code += ",\n";
- code += prefix + MakeCamel(field.name);
- }
- }
- }
-
- void GenArrayPackDecl_ObjectAPI(const StructDef &struct_def,
- std::string *code_ptr,
- std::vector<std::string> name_vec,
- std::vector<int> array_length_vec) const {
+ void GenStructPackDecl_ObjectAPI(
+ const StructDef &struct_def, std::string *code_ptr,
+ std::vector<FieldArrayLength> &array_lengths) const {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
@@ -1774,64 +1773,81 @@ class CSharpGenerator : public BaseGenerator {
auto is_array = IsArray(field.value.type);
const auto &field_type =
is_array ? field.value.type.VectorType() : field.value.type;
- if (!IsStruct(field_type)) {
- auto tmp_name_vec = name_vec;
- tmp_name_vec.push_back(field.name);
- auto tmp_array_length_vec = array_length_vec;
- if (is_array) {
- tmp_array_length_vec.push_back(field_type.fixed_length);
+ FieldArrayLength tmp_array_length = {
+ field.name,
+ field_type.fixed_length,
+ };
+ array_lengths.push_back(tmp_array_length);
+ if (field_type.struct_def != nullptr) {
+ GenStructPackDecl_ObjectAPI(*field_type.struct_def, code_ptr,
+ array_lengths);
+ } else {
+ std::vector<FieldArrayLength> array_only_lengths;
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ if (array_lengths[i].length > 0) {
+ array_only_lengths.push_back(array_lengths[i]);
+ }
}
std::string name;
- for (size_t tmp_name_index = 0; tmp_name_index < tmp_name_vec.size();
- ++tmp_name_index) {
- name += "_" + tmp_name_vec[tmp_name_index];
- }
- code += " var " + name + " = new " + GenTypeBasic(field_type) + "[";
- code += NumToString(tmp_array_length_vec[0]);
- for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) {
- auto array_length = tmp_array_length_vec[i];
- code += "," + NumToString(array_length);
- }
- code += "];\n";
- code += " ";
- // initialize array
- for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
- auto array_length = tmp_array_length_vec[i];
- auto idx = "idx" + NumToString(i);
- code += "for (var " + idx + " = 0; " + idx + " < " +
- NumToString(array_length) + "; ++" + idx + ") {";
- }
- code += name + "[idx0";
- for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) {
- auto idx = "idx" + NumToString(i);
- code += "," + idx;
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ name += "_" + array_lengths[i].name;
}
- code += "] = _o";
- for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
- auto idx = "idx" + NumToString(i);
- code += "." + MakeCamel(tmp_name_vec[i]) + "[" + idx + "]";
- }
- if (!is_array) { code += "." + MakeCamel(field.name); }
- code += ";";
- for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
- code += "}";
+ code += " var " + name + " = ";
+ if (array_only_lengths.size() > 0) {
+ code += "new " + GenTypeBasic(field_type) + "[";
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ if (i != 0) { code += ","; }
+ code += NumToString(array_only_lengths[i].length);
+ }
+ code += "];\n";
+ code += " ";
+ // initialize array
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ auto idx = "idx" + NumToString(i);
+ code += "for (var " + idx + " = 0; " + idx + " < " +
+ NumToString(array_only_lengths[i].length) + "; ++" + idx +
+ ") {";
+ }
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ auto idx = "idx" + NumToString(i);
+ if (i == 0) {
+ code += name + "[" + idx;
+ } else {
+ code += "," + idx;
+ }
+ }
+ code += "] = _o";
+ for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) {
+ code += "." + MakeCamel(array_lengths[i].name);
+ if (array_lengths[i].length <= 0) continue;
+ code += "[idx" + NumToString(j++) + "]";
+ }
+ code += ";";
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) { code += "}"; }
+ } else {
+ code += "_o";
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ code += "." + MakeCamel(array_lengths[i].name);
+ }
+ code += ";";
}
code += "\n";
}
+ array_lengths.pop_back();
}
}
- void GenArrayPackCall_ObjectAPI(const StructDef &struct_def,
- std::string *code_ptr,
- std::string prefix) const {
+ void GenStructPackCall_ObjectAPI(const StructDef &struct_def,
+ std::string *code_ptr,
+ std::string prefix) const {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
const auto &field_type = field.value.type;
- if (IsStruct(field_type)) {
- GenArrayPackCall_ObjectAPI(*field_type.struct_def, code_ptr,
- prefix + field.name + "_");
+ if (field_type.struct_def != nullptr) {
+ GenStructPackCall_ObjectAPI(*field_type.struct_def, code_ptr,
+ prefix + field.name + "_");
} else {
code += ",\n";
code += prefix + field.name;
diff --git a/tests/MyGame/Example/Vec3.cs b/tests/MyGame/Example/Vec3.cs
index 4a9bf0d1..54fc8f99 100644
--- a/tests/MyGame/Example/Vec3.cs
+++ b/tests/MyGame/Example/Vec3.cs
@@ -59,6 +59,8 @@ public struct Vec3 : IFlatbufferObject
}
public static Offset<MyGame.Example.Vec3> Pack(FlatBufferBuilder builder, Vec3T _o) {
if (_o == null) return default(Offset<MyGame.Example.Vec3>);
+ var _test3_a = _o.Test3.A;
+ var _test3_b = _o.Test3.B;
return CreateVec3(
builder,
_o.X,
@@ -66,8 +68,8 @@ public struct Vec3 : IFlatbufferObject
_o.Z,
_o.Test1,
_o.Test2,
- _o.Test3.A,
- _o.Test3.B);
+ _test3_a,
+ _test3_b);
}
};