mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-30 02:22:00 +00:00
[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>
This commit is contained in:
@@ -38,6 +38,11 @@ static CommentConfig comment_config = {
|
|||||||
|
|
||||||
namespace csharp {
|
namespace csharp {
|
||||||
class CSharpGenerator : public BaseGenerator {
|
class CSharpGenerator : public BaseGenerator {
|
||||||
|
struct FieldArrayLength {
|
||||||
|
std::string name;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSharpGenerator(const Parser &parser, const std::string &path,
|
CSharpGenerator(const Parser &parser, const std::string &path,
|
||||||
const std::string &file_name)
|
const std::string &file_name)
|
||||||
@@ -1540,6 +1545,15 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
GenOffsetType(*field.value.type.struct_def) +
|
GenOffsetType(*field.value.type.struct_def) +
|
||||||
") : " + GenTypeGet(field.value.type) +
|
") : " + GenTypeGet(field.value.type) +
|
||||||
".Pack(builder, _o." + camel_name + ");\n";
|
".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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1620,12 +1634,14 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
case BASE_TYPE_ARRAY: {
|
case BASE_TYPE_ARRAY: {
|
||||||
if (field.value.type.struct_def != nullptr) {
|
if (field.value.type.struct_def != nullptr) {
|
||||||
std::vector<std::string> name_vec;
|
std::vector<FieldArrayLength> array_lengths;
|
||||||
name_vec.push_back(field.name);
|
FieldArrayLength tmp_array_length = {
|
||||||
std::vector<int> array_length_vec;
|
field.name,
|
||||||
array_length_vec.push_back(field.value.type.fixed_length);
|
field.value.type.fixed_length,
|
||||||
GenArrayPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
|
};
|
||||||
name_vec, array_length_vec);
|
array_lengths.push_back(tmp_array_length);
|
||||||
|
GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
|
||||||
|
array_lengths);
|
||||||
} else {
|
} else {
|
||||||
code += " var _" + field.name + " = _o." + camel_name + ";\n";
|
code += " var _" + field.name + " = _o." + camel_name + ";\n";
|
||||||
}
|
}
|
||||||
@@ -1656,8 +1672,9 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
switch (field.value.type.base_type) {
|
switch (field.value.type.base_type) {
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
if (struct_def.fixed) {
|
if (struct_def.fixed) {
|
||||||
GenStructArgs_ObjectAPI(*field.value.type.struct_def, code_ptr,
|
GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
|
||||||
" _o." + camel_name + ".");
|
code_ptr,
|
||||||
|
" _" + field.name + "_");
|
||||||
} else {
|
} else {
|
||||||
code += ",\n";
|
code += ",\n";
|
||||||
if (field.value.type.struct_def->fixed) {
|
if (field.value.type.struct_def->fixed) {
|
||||||
@@ -1674,8 +1691,9 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
case BASE_TYPE_ARRAY: {
|
case BASE_TYPE_ARRAY: {
|
||||||
if (field.value.type.struct_def != nullptr) {
|
if (field.value.type.struct_def != nullptr) {
|
||||||
GenArrayPackCall_ObjectAPI(*field.value.type.struct_def, code_ptr,
|
GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
|
||||||
" _" + field.name + "_");
|
code_ptr,
|
||||||
|
" _" + field.name + "_");
|
||||||
} else {
|
} else {
|
||||||
code += ",\n";
|
code += ",\n";
|
||||||
code += " _" + field.name;
|
code += " _" + field.name;
|
||||||
@@ -1745,28 +1763,9 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
code += " }\n";
|
code += " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenStructArgs_ObjectAPI(const StructDef &struct_def,
|
void GenStructPackDecl_ObjectAPI(
|
||||||
std::string *code_ptr,
|
const StructDef &struct_def, std::string *code_ptr,
|
||||||
std::string prefix) const {
|
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) {
|
|
||||||
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 {
|
|
||||||
auto &code = *code_ptr;
|
auto &code = *code_ptr;
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
@@ -1774,64 +1773,81 @@ class CSharpGenerator : public BaseGenerator {
|
|||||||
auto is_array = IsArray(field.value.type);
|
auto is_array = IsArray(field.value.type);
|
||||||
const auto &field_type =
|
const auto &field_type =
|
||||||
is_array ? field.value.type.VectorType() : field.value.type;
|
is_array ? field.value.type.VectorType() : field.value.type;
|
||||||
if (!IsStruct(field_type)) {
|
FieldArrayLength tmp_array_length = {
|
||||||
auto tmp_name_vec = name_vec;
|
field.name,
|
||||||
tmp_name_vec.push_back(field.name);
|
field_type.fixed_length,
|
||||||
auto tmp_array_length_vec = array_length_vec;
|
};
|
||||||
if (is_array) {
|
array_lengths.push_back(tmp_array_length);
|
||||||
tmp_array_length_vec.push_back(field_type.fixed_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;
|
std::string name;
|
||||||
for (size_t tmp_name_index = 0; tmp_name_index < tmp_name_vec.size();
|
for (size_t i = 0; i < array_lengths.size(); ++i) {
|
||||||
++tmp_name_index) {
|
name += "_" + array_lengths[i].name;
|
||||||
name += "_" + tmp_name_vec[tmp_name_index];
|
|
||||||
}
|
}
|
||||||
code += " var " + name + " = new " + GenTypeBasic(field_type) + "[";
|
code += " var " + name + " = ";
|
||||||
code += NumToString(tmp_array_length_vec[0]);
|
if (array_only_lengths.size() > 0) {
|
||||||
for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) {
|
code += "new " + GenTypeBasic(field_type) + "[";
|
||||||
auto array_length = tmp_array_length_vec[i];
|
for (size_t i = 0; i < array_only_lengths.size(); ++i) {
|
||||||
code += "," + NumToString(array_length);
|
if (i != 0) { code += ","; }
|
||||||
}
|
code += NumToString(array_only_lengths[i].length);
|
||||||
code += "];\n";
|
}
|
||||||
code += " ";
|
code += "];\n";
|
||||||
// initialize array
|
code += " ";
|
||||||
for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
|
// initialize array
|
||||||
auto array_length = tmp_array_length_vec[i];
|
for (size_t i = 0; i < array_only_lengths.size(); ++i) {
|
||||||
auto idx = "idx" + NumToString(i);
|
auto idx = "idx" + NumToString(i);
|
||||||
code += "for (var " + idx + " = 0; " + idx + " < " +
|
code += "for (var " + idx + " = 0; " + idx + " < " +
|
||||||
NumToString(array_length) + "; ++" + idx + ") {";
|
NumToString(array_only_lengths[i].length) + "; ++" + idx +
|
||||||
}
|
") {";
|
||||||
code += name + "[idx0";
|
}
|
||||||
for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) {
|
for (size_t i = 0; i < array_only_lengths.size(); ++i) {
|
||||||
auto idx = "idx" + NumToString(i);
|
auto idx = "idx" + NumToString(i);
|
||||||
code += "," + idx;
|
if (i == 0) {
|
||||||
}
|
code += name + "[" + idx;
|
||||||
code += "] = _o";
|
} else {
|
||||||
for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
|
code += "," + idx;
|
||||||
auto idx = "idx" + NumToString(i);
|
}
|
||||||
code += "." + MakeCamel(tmp_name_vec[i]) + "[" + idx + "]";
|
}
|
||||||
}
|
code += "] = _o";
|
||||||
if (!is_array) { code += "." + MakeCamel(field.name); }
|
for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) {
|
||||||
code += ";";
|
code += "." + MakeCamel(array_lengths[i].name);
|
||||||
for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
|
if (array_lengths[i].length <= 0) continue;
|
||||||
code += "}";
|
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";
|
code += "\n";
|
||||||
}
|
}
|
||||||
|
array_lengths.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenArrayPackCall_ObjectAPI(const StructDef &struct_def,
|
void GenStructPackCall_ObjectAPI(const StructDef &struct_def,
|
||||||
std::string *code_ptr,
|
std::string *code_ptr,
|
||||||
std::string prefix) const {
|
std::string prefix) const {
|
||||||
auto &code = *code_ptr;
|
auto &code = *code_ptr;
|
||||||
for (auto it = struct_def.fields.vec.begin();
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
it != struct_def.fields.vec.end(); ++it) {
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
const auto &field_type = field.value.type;
|
const auto &field_type = field.value.type;
|
||||||
if (IsStruct(field_type)) {
|
if (field_type.struct_def != nullptr) {
|
||||||
GenArrayPackCall_ObjectAPI(*field_type.struct_def, code_ptr,
|
GenStructPackCall_ObjectAPI(*field_type.struct_def, code_ptr,
|
||||||
prefix + field.name + "_");
|
prefix + field.name + "_");
|
||||||
} else {
|
} else {
|
||||||
code += ",\n";
|
code += ",\n";
|
||||||
code += prefix + field.name;
|
code += prefix + field.name;
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public struct Vec3 : IFlatbufferObject
|
|||||||
}
|
}
|
||||||
public static Offset<MyGame.Example.Vec3> Pack(FlatBufferBuilder builder, Vec3T _o) {
|
public static Offset<MyGame.Example.Vec3> Pack(FlatBufferBuilder builder, Vec3T _o) {
|
||||||
if (_o == null) return default(Offset<MyGame.Example.Vec3>);
|
if (_o == null) return default(Offset<MyGame.Example.Vec3>);
|
||||||
|
var _test3_a = _o.Test3.A;
|
||||||
|
var _test3_b = _o.Test3.B;
|
||||||
return CreateVec3(
|
return CreateVec3(
|
||||||
builder,
|
builder,
|
||||||
_o.X,
|
_o.X,
|
||||||
@@ -66,8 +68,8 @@ public struct Vec3 : IFlatbufferObject
|
|||||||
_o.Z,
|
_o.Z,
|
||||||
_o.Test1,
|
_o.Test1,
|
||||||
_o.Test2,
|
_o.Test2,
|
||||||
_o.Test3.A,
|
_test3_a,
|
||||||
_o.Test3.B);
|
_test3_b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user