mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-11 15:37:27 +00:00
Add support for fixed-size arrays (#5313)
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
0d2cebccfe
commit
e635141d5b
@@ -697,6 +697,13 @@ class CppGenerator : public BaseGenerator {
|
||||
bool user_facing_type) {
|
||||
if (IsScalar(type.base_type)) {
|
||||
return GenTypeBasic(type, user_facing_type) + afterbasic;
|
||||
} else if (IsArray(type)) {
|
||||
auto element_type = type.VectorType();
|
||||
return beforeptr +
|
||||
(IsScalar(element_type.base_type)
|
||||
? GenTypeBasic(element_type, user_facing_type)
|
||||
: GenTypePointer(element_type)) +
|
||||
afterptr;
|
||||
} else {
|
||||
return beforeptr + GenTypePointer(type) + afterptr;
|
||||
}
|
||||
@@ -2689,7 +2696,8 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
|
||||
(void)bits;
|
||||
*code_ptr += ",\n padding" + NumToString((*id)++) + "__(0)";
|
||||
if (*code_ptr != "") *code_ptr += ",\n ";
|
||||
*code_ptr += "padding" + NumToString((*id)++) + "__(0)";
|
||||
}
|
||||
|
||||
static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
|
||||
@@ -2717,10 +2725,14 @@ class CppGenerator : public BaseGenerator {
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
code_.SetValue("FIELD_TYPE",
|
||||
GenTypeGet(field.value.type, " ", "", " ", false));
|
||||
const auto &field_type = field.value.type;
|
||||
code_.SetValue("FIELD_TYPE", GenTypeGet(field_type, " ", "", " ", false));
|
||||
code_.SetValue("FIELD_NAME", Name(field));
|
||||
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;";
|
||||
code_.SetValue("ARRAY",
|
||||
IsArray(field_type)
|
||||
? "[" + NumToString(field_type.fixed_length) + "]"
|
||||
: "");
|
||||
code_ += (" {{FIELD_TYPE}}{{FIELD_NAME}}_{{ARRAY}};");
|
||||
|
||||
if (field.padding) {
|
||||
std::string padding;
|
||||
@@ -2745,33 +2757,40 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
// Generate a default constructor.
|
||||
code_ += " {{STRUCT_NAME}}() {";
|
||||
code_ += " memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
|
||||
code_ +=
|
||||
" memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
|
||||
code_ += " }";
|
||||
|
||||
// Generate a constructor that takes all fields as arguments.
|
||||
// Generate a constructor that takes all fields as arguments,
|
||||
// excluding arrays
|
||||
std::string arg_list;
|
||||
std::string init_list;
|
||||
padding_id = 0;
|
||||
auto first = struct_def.fields.vec.begin();
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
if (IsArray(field.value.type)) {
|
||||
first++;
|
||||
continue;
|
||||
}
|
||||
const auto member_name = Name(field) + "_";
|
||||
const auto arg_name = "_" + Name(field);
|
||||
const auto arg_type =
|
||||
GenTypeGet(field.value.type, " ", "const ", " &", true);
|
||||
|
||||
if (it != struct_def.fields.vec.begin()) {
|
||||
arg_list += ", ";
|
||||
init_list += ",\n ";
|
||||
}
|
||||
if (it != first) { arg_list += ", "; }
|
||||
arg_list += arg_type;
|
||||
arg_list += arg_name;
|
||||
init_list += member_name;
|
||||
if (IsScalar(field.value.type.base_type)) {
|
||||
auto type = GenUnderlyingCast(field, false, arg_name);
|
||||
init_list += "(flatbuffers::EndianScalar(" + type + "))";
|
||||
} else {
|
||||
init_list += "(" + arg_name + ")";
|
||||
if (!IsArray(field.value.type)) {
|
||||
if (it != first && init_list != "") { init_list += ",\n "; }
|
||||
init_list += member_name;
|
||||
if (IsScalar(field.value.type.base_type)) {
|
||||
auto type = GenUnderlyingCast(field, false, arg_name);
|
||||
init_list += "(flatbuffers::EndianScalar(" + type + "))";
|
||||
} else {
|
||||
init_list += "(" + arg_name + ")";
|
||||
}
|
||||
}
|
||||
if (field.padding) {
|
||||
GenPadding(field, &init_list, &padding_id, PaddingInitializer);
|
||||
@@ -2781,12 +2800,21 @@ class CppGenerator : public BaseGenerator {
|
||||
if (!arg_list.empty()) {
|
||||
code_.SetValue("ARG_LIST", arg_list);
|
||||
code_.SetValue("INIT_LIST", init_list);
|
||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
|
||||
code_ += " : {{INIT_LIST}} {";
|
||||
if (!init_list.empty()) {
|
||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
|
||||
code_ += " : {{INIT_LIST}} {";
|
||||
} else {
|
||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}}) {";
|
||||
}
|
||||
padding_id = 0;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
if (IsArray(field.value.type)) {
|
||||
const auto &member = Name(field) + "_";
|
||||
code_ +=
|
||||
" std::memset(" + member + ", 0, sizeof(" + member + "));";
|
||||
}
|
||||
if (field.padding) {
|
||||
std::string padding;
|
||||
GenPadding(field, &padding, &padding_id, PaddingNoop);
|
||||
@@ -2802,7 +2830,9 @@ class CppGenerator : public BaseGenerator {
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
|
||||
auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true);
|
||||
auto field_type = GenTypeGet(field.value.type, " ",
|
||||
IsArray(field.value.type) ? "" : "const ",
|
||||
IsArray(field.value.type) ? "" : " &", true);
|
||||
auto is_scalar = IsScalar(field.value.type.base_type);
|
||||
auto member = Name(field) + "_";
|
||||
auto value =
|
||||
@@ -2813,12 +2843,29 @@ class CppGenerator : public BaseGenerator {
|
||||
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
|
||||
|
||||
GenComment(field.doc_comment, " ");
|
||||
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
|
||||
code_ += " return {{FIELD_VALUE}};";
|
||||
code_ += " }";
|
||||
|
||||
// Generate a const accessor function.
|
||||
if (IsArray(field.value.type)) {
|
||||
auto underlying = GenTypeGet(field.value.type, "", "", "", false);
|
||||
code_ += " const flatbuffers::Array<" + field_type + ", " +
|
||||
NumToString(field.value.type.fixed_length) + "> *" +
|
||||
"{{FIELD_NAME}}() const {";
|
||||
code_ += " return reinterpret_cast<const flatbuffers::Array<" +
|
||||
field_type + ", " +
|
||||
NumToString(field.value.type.fixed_length) +
|
||||
"> *>({{FIELD_VALUE}});";
|
||||
code_ += " }";
|
||||
} else {
|
||||
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
|
||||
code_ += " return {{FIELD_VALUE}};";
|
||||
code_ += " }";
|
||||
}
|
||||
|
||||
// Generate a mutable accessor function.
|
||||
if (parser_.opts.mutable_buffer) {
|
||||
auto mut_field_type = GenTypeGet(field.value.type, " ", "", " &", true);
|
||||
auto mut_field_type =
|
||||
GenTypeGet(field.value.type, " ", "",
|
||||
IsArray(field.value.type) ? "" : " &", true);
|
||||
code_.SetValue("FIELD_TYPE", mut_field_type);
|
||||
if (is_scalar) {
|
||||
code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
|
||||
@@ -2830,9 +2877,19 @@ class CppGenerator : public BaseGenerator {
|
||||
" flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
|
||||
"{{FIELD_VALUE}});";
|
||||
code_ += " }";
|
||||
} else if (IsArray(field.value.type)) {
|
||||
auto underlying = GenTypeGet(field.value.type, "", "", "", false);
|
||||
code_ += " flatbuffers::Array<" + mut_field_type + ", " +
|
||||
NumToString(field.value.type.fixed_length) +
|
||||
"> *" + "mutable_{{FIELD_NAME}}() {";
|
||||
code_ += " return reinterpret_cast<flatbuffers::Array<" +
|
||||
mut_field_type + ", " +
|
||||
NumToString(field.value.type.fixed_length) +
|
||||
"> *>({{FIELD_VALUE}});";
|
||||
code_ += " }";
|
||||
} else {
|
||||
code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
|
||||
code_ += " return {{FIELD_NAME}}_;";
|
||||
code_ += " return {{FIELD_VALUE}};";
|
||||
code_ += " }";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,10 +254,6 @@ class GeneralGenerator : public BaseGenerator {
|
||||
: "";
|
||||
}
|
||||
|
||||
static bool IsEnum(const Type &type) {
|
||||
return type.enum_def != nullptr && IsInteger(type.base_type);
|
||||
}
|
||||
|
||||
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const {
|
||||
// clang-format off
|
||||
static const char * const java_typename[] = {
|
||||
@@ -312,7 +308,10 @@ class GeneralGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
std::string GenTypeGet(const Type &type) const {
|
||||
return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
|
||||
return IsScalar(type.base_type)
|
||||
? GenTypeBasic(type)
|
||||
: (IsArray(type) ? GenTypeGet(type.VectorType())
|
||||
: GenTypePointer(type));
|
||||
}
|
||||
|
||||
// Find the destination type the user wants to receive the value in (e.g.
|
||||
@@ -325,6 +324,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
|
||||
case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
|
||||
case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
|
||||
case BASE_TYPE_ARRAY:
|
||||
case BASE_TYPE_VECTOR:
|
||||
if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
|
||||
FLATBUFFERS_FALLTHROUGH(); // else fall thru
|
||||
@@ -378,7 +378,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
|
||||
// Casts necessary to correctly read serialized data
|
||||
std::string DestinationCast(const Type &type) const {
|
||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
||||
if (IsSeries(type)) {
|
||||
return DestinationCast(type.VectorType());
|
||||
} else {
|
||||
switch (lang_.language) {
|
||||
@@ -405,7 +405,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
// directly cast an Enum to its underlying type, which is essential before
|
||||
// putting it onto the buffer.
|
||||
std::string SourceCast(const Type &type, bool castFromDest) const {
|
||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
||||
if (IsSeries(type)) {
|
||||
return SourceCast(type.VectorType(), castFromDest);
|
||||
} else {
|
||||
switch (lang_.language) {
|
||||
@@ -602,6 +602,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct";
|
||||
case BASE_TYPE_UNION: return lang_.accessor_prefix + "__union";
|
||||
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
|
||||
case BASE_TYPE_ARRAY: return GenGetter(type.VectorType());
|
||||
default: {
|
||||
std::string getter =
|
||||
lang_.accessor_prefix + "bb." + FunctionStart('G') + "et";
|
||||
@@ -656,20 +657,36 @@ class GeneralGenerator : public BaseGenerator {
|
||||
// Recursively generate arguments for a constructor, to deal with nested
|
||||
// structs.
|
||||
void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
|
||||
const char *nameprefix) const {
|
||||
const char *nameprefix, size_t array_count = 0) const {
|
||||
std::string &code = *code_ptr;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (IsStruct(field.value.type)) {
|
||||
const auto &field_type = field.value.type;
|
||||
const auto array_field = IsArray(field_type);
|
||||
const auto &type = array_field ? field_type.VectorType()
|
||||
: DestinationType(field_type, false);
|
||||
const auto array_cnt = array_field ? (array_count + 1) : array_count;
|
||||
if (IsStruct(type)) {
|
||||
// Generate arguments for a struct inside a struct. To ensure names
|
||||
// don't clash, and to make it obvious these arguments are constructing
|
||||
// a nested struct, prefix the name with the field name.
|
||||
GenStructArgs(*field.value.type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str());
|
||||
GenStructArgs(*field_type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str(), array_cnt);
|
||||
} else {
|
||||
code += ", ";
|
||||
code += GenTypeBasic(DestinationType(field.value.type, false));
|
||||
code += GenTypeBasic(type);
|
||||
if (lang_.language == IDLOptions::kJava) {
|
||||
for (size_t i = 0; i < array_cnt; i++) code += "[]";
|
||||
} else if (lang_.language == IDLOptions::kCSharp) {
|
||||
if (array_cnt > 0) {
|
||||
code += "[";
|
||||
for (size_t i = 1; i < array_cnt; i++) code += ",";
|
||||
code += "]";
|
||||
}
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(0);
|
||||
}
|
||||
code += " ";
|
||||
code += nameprefix;
|
||||
code += MakeCamel(field.name, lang_.first_camel_upper);
|
||||
@@ -681,29 +698,67 @@ class GeneralGenerator : public BaseGenerator {
|
||||
// builder.putType(name);
|
||||
// and insert manual padding.
|
||||
void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
|
||||
const char *nameprefix) const {
|
||||
const char *nameprefix, size_t index = 0,
|
||||
bool in_array = false) const {
|
||||
std::string &code = *code_ptr;
|
||||
code += " builder." + FunctionStart('P') + "rep(";
|
||||
std::string indent((index + 1) * 2, ' ');
|
||||
code += indent + " builder." + FunctionStart('P') + "rep(";
|
||||
code += NumToString(struct_def.minalign) + ", ";
|
||||
code += NumToString(struct_def.bytesize) + ");\n";
|
||||
for (auto it = struct_def.fields.vec.rbegin();
|
||||
it != struct_def.fields.vec.rend(); ++it) {
|
||||
auto &field = **it;
|
||||
const auto &field_type = field.value.type;
|
||||
if (field.padding) {
|
||||
code += " builder." + FunctionStart('P') + "ad(";
|
||||
code += indent + " builder." + FunctionStart('P') + "ad(";
|
||||
code += NumToString(field.padding) + ");\n";
|
||||
}
|
||||
if (IsStruct(field.value.type)) {
|
||||
GenStructBody(*field.value.type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str());
|
||||
if (IsStruct(field_type)) {
|
||||
GenStructBody(*field_type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str(), index,
|
||||
in_array);
|
||||
} else {
|
||||
code += " builder." + FunctionStart('P') + "ut";
|
||||
code += GenMethod(field.value.type) + "(";
|
||||
code += SourceCast(field.value.type);
|
||||
auto argname =
|
||||
nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
|
||||
code += argname;
|
||||
code += ");\n";
|
||||
const auto &type =
|
||||
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||
const auto index_var = "_idx" + NumToString(index);
|
||||
if (IsArray(field_type)) {
|
||||
code += indent + " for (int " + index_var + " = ";
|
||||
code += NumToString(field_type.fixed_length);
|
||||
code += "; " + index_var + " > 0; " + index_var + "--) {\n";
|
||||
in_array = true;
|
||||
}
|
||||
if (IsStruct(type)) {
|
||||
GenStructBody(*field_type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str(), index + 1,
|
||||
in_array);
|
||||
} else {
|
||||
code += IsArray(field_type) ? " " : "";
|
||||
code += indent + " builder." + FunctionStart('P') + "ut";
|
||||
code += GenMethod(type) + "(";
|
||||
code += SourceCast(type);
|
||||
auto argname =
|
||||
nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
|
||||
code += argname;
|
||||
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
|
||||
if (lang_.language == IDLOptions::kJava) {
|
||||
for (size_t i = 0; in_array && i < array_cnt; i++) {
|
||||
code += "[_idx" + NumToString(i) + "-1]";
|
||||
}
|
||||
} else if (lang_.language == IDLOptions::kCSharp) {
|
||||
if (array_cnt > 0) {
|
||||
code += "[";
|
||||
for (size_t i = 0; in_array && i < array_cnt; i++) {
|
||||
code += "_idx" + NumToString(i) + "-1";
|
||||
if (i != (array_cnt - 1)) code += ",";
|
||||
}
|
||||
code += "]";
|
||||
}
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(0);
|
||||
}
|
||||
code += ");\n";
|
||||
}
|
||||
if (IsArray(field_type)) { code += indent + " }\n"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -924,9 +979,11 @@ class GeneralGenerator : public BaseGenerator {
|
||||
|
||||
// Most field accessors need to retrieve and test the field offset first,
|
||||
// this is the prefix code for that:
|
||||
auto offset_prefix = " { int o = " + lang_.accessor_prefix + "__offset(" +
|
||||
NumToString(field.value.offset) +
|
||||
"); return o != 0 ? ";
|
||||
auto offset_prefix =
|
||||
IsArray(field.value.type)
|
||||
? " { return "
|
||||
: (" { int o = " + lang_.accessor_prefix + "__offset(" +
|
||||
NumToString(field.value.offset) + "); return o != 0 ? ");
|
||||
// Generate the accessors that don't do object reuse.
|
||||
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
|
||||
// Calls the accessor that takes an accessor object with a new object.
|
||||
@@ -1017,6 +1074,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
code += offset_prefix + getter + "(o + " + lang_.accessor_prefix;
|
||||
code += "bb_pos) : null";
|
||||
break;
|
||||
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BASE_TYPE_VECTOR: {
|
||||
auto vectortype = field.value.type.VectorType();
|
||||
if (vectortype.base_type == BASE_TYPE_UNION &&
|
||||
@@ -1043,8 +1101,13 @@ class GeneralGenerator : public BaseGenerator {
|
||||
} else {
|
||||
code += body;
|
||||
}
|
||||
auto index = lang_.accessor_prefix + "__vector(o) + j * " +
|
||||
NumToString(InlineSize(vectortype));
|
||||
auto index = lang_.accessor_prefix;
|
||||
if (IsArray(field.value.type)) {
|
||||
index += "bb_pos + " + NumToString(field.value.offset) + " + ";
|
||||
} else {
|
||||
index += "__vector(o) + ";
|
||||
}
|
||||
index += "j * " + NumToString(InlineSize(vectortype));
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += vectortype.struct_def->fixed
|
||||
? index
|
||||
@@ -1055,13 +1118,16 @@ class GeneralGenerator : public BaseGenerator {
|
||||
} else {
|
||||
code += index;
|
||||
}
|
||||
code += ")" + dest_mask + " : ";
|
||||
code += ")" + dest_mask;
|
||||
if (!IsArray(field.value.type)) {
|
||||
code += " : ";
|
||||
code +=
|
||||
field.value.type.element == BASE_TYPE_BOOL
|
||||
? "false"
|
||||
: (IsScalar(field.value.type.element) ? default_cast + "0"
|
||||
: "null");
|
||||
}
|
||||
|
||||
code +=
|
||||
field.value.type.element == BASE_TYPE_BOOL
|
||||
? "false"
|
||||
: (IsScalar(field.value.type.element) ? default_cast + "0"
|
||||
: "null");
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
@@ -1215,9 +1281,9 @@ class GeneralGenerator : public BaseGenerator {
|
||||
}
|
||||
// Generate mutators for scalar fields or vectors of scalars.
|
||||
if (parser_.opts.mutable_buffer) {
|
||||
auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
|
||||
? field.value.type.VectorType()
|
||||
: field.value.type;
|
||||
auto is_series = (IsSeries(field.value.type));
|
||||
const auto &underlying_type =
|
||||
is_series ? field.value.type.VectorType() : field.value.type;
|
||||
// Boolean parameters have to be explicitly converted to byte
|
||||
// representation.
|
||||
auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
|
||||
@@ -1226,21 +1292,21 @@ class GeneralGenerator : public BaseGenerator {
|
||||
auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper);
|
||||
// A vector mutator also needs the index of the vector element it should
|
||||
// mutate.
|
||||
auto mutator_params =
|
||||
(field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, "
|
||||
: "(") +
|
||||
GenTypeNameDest(underlying_type) + " " + field.name + ") { ";
|
||||
auto mutator_params = (is_series ? "(int j, " : "(") +
|
||||
GenTypeNameDest(underlying_type) + " " +
|
||||
field.name + ") { ";
|
||||
auto setter_index =
|
||||
field.value.type.base_type == BASE_TYPE_VECTOR
|
||||
? lang_.accessor_prefix + "__vector(o) + j * " +
|
||||
NumToString(InlineSize(underlying_type))
|
||||
is_series
|
||||
? lang_.accessor_prefix +
|
||||
(IsArray(field.value.type)
|
||||
? "bb_pos + " + NumToString(field.value.offset)
|
||||
: "__vector(o)") +
|
||||
+" + j * " + NumToString(InlineSize(underlying_type))
|
||||
: (struct_def.fixed
|
||||
? lang_.accessor_prefix + "bb_pos + " +
|
||||
NumToString(field.value.offset)
|
||||
: "o + " + lang_.accessor_prefix + "bb_pos");
|
||||
if (IsScalar(field.value.type.base_type) ||
|
||||
(field.value.type.base_type == BASE_TYPE_VECTOR &&
|
||||
IsScalar(field.value.type.VectorType().base_type))) {
|
||||
if (IsScalar(underlying_type.base_type)) {
|
||||
code += " public ";
|
||||
code += struct_def.fixed ? "void " : lang_.bool_type;
|
||||
code += mutator_prefix + MakeCamel(field.name, true);
|
||||
|
||||
@@ -42,6 +42,7 @@ std::string GenNativeType(BaseType type) {
|
||||
case BASE_TYPE_FLOAT:
|
||||
case BASE_TYPE_DOUBLE: return "number";
|
||||
case BASE_TYPE_STRING: return "string";
|
||||
case BASE_TYPE_ARRAY: return "array";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
@@ -70,6 +71,7 @@ std::string GenType(const Type &type) {
|
||||
return GenTypeRef(type.enum_def);
|
||||
}
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BASE_TYPE_VECTOR: {
|
||||
std::string typeline;
|
||||
typeline.append("\"type\" : \"array\", \"items\" : { ");
|
||||
@@ -156,8 +158,16 @@ class JsonSchemaGenerator : public BaseGenerator {
|
||||
const auto &properties = structure->fields.vec;
|
||||
for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
|
||||
const auto &property = *prop;
|
||||
std::string typeLine(" \"" + property->name + "\" : { " +
|
||||
GenType(property->value.type) + " }");
|
||||
std::string arrayInfo = "";
|
||||
if (IsArray(property->value.type)) {
|
||||
arrayInfo = ",\n \"minItems\": " +
|
||||
NumToString(property->value.type.fixed_length) +
|
||||
",\n \"maxItems\": " +
|
||||
NumToString(property->value.type.fixed_length);
|
||||
}
|
||||
std::string typeLine =
|
||||
" \"" + property->name + "\" : {\n" + " " +
|
||||
GenType(property->value.type) + arrayInfo + "\n }";
|
||||
if (property != properties.back()) { typeLine.append(","); }
|
||||
code_ += typeLine;
|
||||
}
|
||||
|
||||
@@ -224,6 +224,30 @@ class PythonGenerator : public BaseGenerator {
|
||||
code += "\n" + Indent + Indent + "return obj\n\n";
|
||||
}
|
||||
|
||||
// Get the value of a fixed size array.
|
||||
void GetArrayOfStruct(const StructDef &struct_def, const FieldDef &field,
|
||||
std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
const auto vec_type = field.value.type.VectorType();
|
||||
GenReceiver(struct_def, code_ptr);
|
||||
code += MakeCamel(NormalizedName(field));
|
||||
if (IsStruct(vec_type)) {
|
||||
code += "(self, obj, i):\n";
|
||||
code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
|
||||
code += NumToString(field.value.offset) + " + i * ";
|
||||
code += NumToString(InlineSize(vec_type));
|
||||
code += ")\n" + Indent + Indent + "return obj\n\n";
|
||||
} else {
|
||||
auto getter = GenGetter(vec_type);
|
||||
code += "(self): return [" + getter;
|
||||
code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
|
||||
code += NumToString(field.value.offset) + " + i * ";
|
||||
code += NumToString(InlineSize(vec_type));
|
||||
code += ")) for i in range(";
|
||||
code += NumToString(field.value.type.fixed_length) + ")]\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Get a struct by initializing an existing struct.
|
||||
// Specific to Table.
|
||||
void GetStructFieldOfTable(const StructDef &struct_def,
|
||||
@@ -380,12 +404,16 @@ class PythonGenerator : public BaseGenerator {
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (IsStruct(field.value.type)) {
|
||||
const auto &field_type = field.value.type;
|
||||
const auto &type =
|
||||
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||
if (IsStruct(type)) {
|
||||
// Generate arguments for a struct inside a struct. To ensure names
|
||||
// don't clash, and to make it obvious these arguments are constructing
|
||||
// a nested struct, prefix the name with the field name.
|
||||
StructBuilderArgs(*field.value.type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
|
||||
StructBuilderArgs(*field_type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(),
|
||||
code_ptr);
|
||||
} else {
|
||||
std::string &code = *code_ptr;
|
||||
code += std::string(", ") + nameprefix;
|
||||
@@ -402,22 +430,50 @@ class PythonGenerator : public BaseGenerator {
|
||||
|
||||
// Recursively generate struct construction statements and instert manual
|
||||
// padding.
|
||||
void StructBuilderBody(const StructDef &struct_def,
|
||||
const char *nameprefix, std::string *code_ptr) {
|
||||
void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
|
||||
std::string *code_ptr, size_t index = 0,
|
||||
bool in_array = false) {
|
||||
std::string &code = *code_ptr;
|
||||
code += " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
|
||||
std::string indent(index * 4, ' ');
|
||||
code +=
|
||||
indent + " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
|
||||
code += NumToString(struct_def.bytesize) + ")\n";
|
||||
for (auto it = struct_def.fields.vec.rbegin();
|
||||
it != struct_def.fields.vec.rend(); ++it) {
|
||||
auto &field = **it;
|
||||
const auto &field_type = field.value.type;
|
||||
const auto &type =
|
||||
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||
if (field.padding)
|
||||
code += " builder.Pad(" + NumToString(field.padding) + ")\n";
|
||||
if (IsStruct(field.value.type)) {
|
||||
StructBuilderBody(*field.value.type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
|
||||
code +=
|
||||
indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
|
||||
if (IsStruct(field_type)) {
|
||||
StructBuilderBody(*field_type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(),
|
||||
code_ptr, index, in_array);
|
||||
} else {
|
||||
code += " builder.Prepend" + GenMethod(field) + "(";
|
||||
code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
|
||||
const auto index_var = "_idx" + NumToString(index);
|
||||
if (IsArray(field_type)) {
|
||||
code += indent + " for " + index_var + " in range(";
|
||||
code += NumToString(field_type.fixed_length);
|
||||
code += " , 0, -1):\n";
|
||||
in_array = true;
|
||||
}
|
||||
if (IsStruct(type)) {
|
||||
StructBuilderBody(
|
||||
*field_type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr,
|
||||
index + 1, in_array);
|
||||
} else {
|
||||
code += IsArray(field_type) ? " " : "";
|
||||
code += indent + " builder.Prepend" + GenMethod(field) + "(";
|
||||
code += nameprefix + MakeCamel(NormalizedName(field), false);
|
||||
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
|
||||
for (size_t i = 0; in_array && i < array_cnt; i++) {
|
||||
code += "[_idx" + NumToString(i) + "-1]";
|
||||
}
|
||||
code += ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -505,6 +561,8 @@ class PythonGenerator : public BaseGenerator {
|
||||
} else {
|
||||
GetScalarFieldOfTable(struct_def, field, code_ptr);
|
||||
}
|
||||
} else if (IsArray(field.value.type)) {
|
||||
GetArrayOfStruct(struct_def, field, code_ptr);
|
||||
} else {
|
||||
switch (field.value.type.base_type) {
|
||||
case BASE_TYPE_STRUCT:
|
||||
@@ -613,9 +671,9 @@ class PythonGenerator : public BaseGenerator {
|
||||
|
||||
// Returns the method name for use with add/put calls.
|
||||
std::string GenMethod(const FieldDef &field) {
|
||||
return IsScalar(field.value.type.base_type)
|
||||
? MakeCamel(GenTypeBasic(field.value.type))
|
||||
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
|
||||
return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
|
||||
? MakeCamel(GenTypeBasic(field.value.type))
|
||||
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
|
||||
}
|
||||
|
||||
std::string GenTypeBasic(const Type &type) {
|
||||
@@ -628,7 +686,8 @@ class PythonGenerator : public BaseGenerator {
|
||||
#undef FLATBUFFERS_TD
|
||||
// clang-format on
|
||||
};
|
||||
return ctypename[type.base_type];
|
||||
return ctypename[IsArray(type) ? type.VectorType().base_type
|
||||
: type.base_type];
|
||||
}
|
||||
|
||||
std::string GenTypePointer(const Type &type) {
|
||||
|
||||
@@ -69,26 +69,27 @@ bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
|
||||
template<typename T>
|
||||
bool PrintVector(const Vector<T> &v, Type type, int indent,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
// Print a vector or an array of JSON values, comma seperated, wrapped in "[]".
|
||||
template<typename T, typename Container>
|
||||
bool PrintContainer(const Container &c, size_t size, Type type, int indent,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
std::string &text = *_text;
|
||||
text += "[";
|
||||
text += NewLine(opts);
|
||||
for (uoffset_t i = 0; i < v.size(); i++) {
|
||||
for (uoffset_t i = 0; i < size; i++) {
|
||||
if (i) {
|
||||
if (!opts.protobuf_ascii_alike) text += ",";
|
||||
text += NewLine(opts);
|
||||
}
|
||||
text.append(indent + Indent(opts), ' ');
|
||||
if (IsStruct(type)) {
|
||||
if (!Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
|
||||
indent + Indent(opts), nullptr, opts, _text)) {
|
||||
if (!Print(reinterpret_cast<const void *>(c.Data() +
|
||||
i * type.struct_def->bytesize),
|
||||
type, indent + Indent(opts), nullptr, opts, _text)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!Print(v[i], type, indent + Indent(opts), nullptr, opts, _text)) {
|
||||
if (!Print(c[i], type, indent + Indent(opts), nullptr, opts, _text)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -99,6 +100,20 @@ bool PrintVector(const Vector<T> &v, Type type, int indent,
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool PrintVector(const Vector<T> &v, Type type, int indent,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
return PrintContainer<T, Vector<T>>(v, v.size(), type, indent, opts, _text);
|
||||
}
|
||||
|
||||
// Print an array a sequence of JSON values, comma separated, wrapped in "[]".
|
||||
template<typename T>
|
||||
bool PrintArray(const Array<T, 0xFFFF> &a, size_t size, Type type, int indent,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
return PrintContainer<T, Array<T, 0xFFFF>>(a, size, type, indent, opts,
|
||||
_text);
|
||||
}
|
||||
|
||||
// Specialization of Print above for pointer types.
|
||||
template<>
|
||||
bool Print<const void *>(const void *val, Type type, int indent,
|
||||
@@ -125,25 +140,49 @@ bool Print<const void *>(const void *val, Type type, int indent,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_VECTOR:
|
||||
type = type.VectorType();
|
||||
case BASE_TYPE_VECTOR: {
|
||||
const auto vec_type = type.VectorType();
|
||||
// Call PrintVector above specifically for each element type:
|
||||
switch (type.base_type) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
switch (vec_type.base_type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
if (!PrintVector<CTYPE>( \
|
||||
*reinterpret_cast<const Vector<CTYPE> *>(val), \
|
||||
type, indent, opts, _text)) { \
|
||||
vec_type, indent, opts, _text)) { \
|
||||
return false; \
|
||||
} \
|
||||
break;
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
// clang-format on
|
||||
}
|
||||
// clang-format on
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_ARRAY: {
|
||||
const auto vec_type = type.VectorType();
|
||||
// Call PrintArray above specifically for each element type:
|
||||
// clang-format off
|
||||
switch (vec_type.base_type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
if (!PrintArray<CTYPE>( \
|
||||
*reinterpret_cast<const Array<CTYPE, 0xFFFF> *>(val), \
|
||||
type.fixed_length, \
|
||||
vec_type, indent, opts, _text)) { \
|
||||
return false; \
|
||||
} \
|
||||
break;
|
||||
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
case BASE_TYPE_ARRAY: FLATBUFFERS_ASSERT(0);
|
||||
}
|
||||
// clang-format on
|
||||
break;
|
||||
}
|
||||
default: FLATBUFFERS_ASSERT(0);
|
||||
}
|
||||
return true;
|
||||
@@ -177,8 +216,8 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
|
||||
std::string *_text) {
|
||||
const void *val = nullptr;
|
||||
if (fixed) {
|
||||
// The only non-scalar fields in structs are structs.
|
||||
FLATBUFFERS_ASSERT(IsStruct(fd.value.type));
|
||||
// The only non-scalar fields in structs are structs or arrays.
|
||||
FLATBUFFERS_ASSERT(IsStruct(fd.value.type) || IsArray(fd.value.type));
|
||||
val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
|
||||
fd.value.offset);
|
||||
} else if (fd.flexbuffer) {
|
||||
@@ -241,6 +280,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM:
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||
FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
|
||||
union_type, opts, _text)) {
|
||||
|
||||
@@ -601,12 +601,35 @@ CheckedError Parser::ParseType(Type &type) {
|
||||
NEXT();
|
||||
Type subtype;
|
||||
ECHECK(Recurse([&]() { return ParseType(subtype); }));
|
||||
if (subtype.base_type == BASE_TYPE_VECTOR) {
|
||||
if (IsSeries(subtype)) {
|
||||
// We could support this, but it will complicate things, and it's
|
||||
// easier to work around with a struct around the inner vector.
|
||||
return Error("nested vector types not supported (wrap in table first).");
|
||||
return Error("nested vector types not supported (wrap in table first)");
|
||||
}
|
||||
if (token_ == ':') {
|
||||
NEXT();
|
||||
if (token_ != kTokenIntegerConstant) {
|
||||
return Error("length of fixed-length array must be an integer value");
|
||||
}
|
||||
uint16_t fixed_length = 0;
|
||||
bool check = StringToNumber(attribute_.c_str(), &fixed_length);
|
||||
if (!check || fixed_length < 1) {
|
||||
return Error(
|
||||
"length of fixed-length array must be positive and fit to "
|
||||
"uint16_t type");
|
||||
}
|
||||
// Check if enum arrays are used in C++ without specifying --scoped-enums
|
||||
if ((opts.lang_to_generate & IDLOptions::kCpp) && !opts.scoped_enums &&
|
||||
IsEnum(subtype)) {
|
||||
return Error(
|
||||
"--scoped-enums must be enabled to use enum arrays in C++\n");
|
||||
}
|
||||
type = Type(BASE_TYPE_ARRAY, subtype.struct_def, subtype.enum_def,
|
||||
fixed_length);
|
||||
NEXT();
|
||||
} else {
|
||||
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
|
||||
}
|
||||
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
|
||||
type.element = subtype.base_type;
|
||||
EXPECT(']');
|
||||
} else {
|
||||
@@ -651,9 +674,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
Type type;
|
||||
ECHECK(ParseType(type));
|
||||
|
||||
if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type))
|
||||
if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type) &&
|
||||
!IsArray(type))
|
||||
return Error("structs_ may contain only scalar or struct fields");
|
||||
|
||||
if (!struct_def.fixed && IsArray(type))
|
||||
return Error("fixed-length array in table must be wrapped in struct");
|
||||
|
||||
if (IsArray(type) && !SupportsAdvancedArrayFeatures()) {
|
||||
return Error(
|
||||
"Arrays are not yet supported in all "
|
||||
"the specified programming languages.");
|
||||
}
|
||||
|
||||
FieldDef *typefield = nullptr;
|
||||
if (type.base_type == BASE_TYPE_UNION) {
|
||||
// For union fields, add a second auto-generated field to hold the type,
|
||||
@@ -703,12 +736,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
}
|
||||
}
|
||||
if (type.enum_def) {
|
||||
// The type.base_type can only be scalar, union or vector.
|
||||
// The type.base_type can only be scalar, union, array or vector.
|
||||
// Table, struct or string can't have enum_def.
|
||||
// Default value of union and vector in NONE, NULL translated to "0".
|
||||
FLATBUFFERS_ASSERT(IsInteger(type.base_type) ||
|
||||
(type.base_type == BASE_TYPE_UNION) ||
|
||||
(type.base_type == BASE_TYPE_VECTOR));
|
||||
(type.base_type == BASE_TYPE_VECTOR) ||
|
||||
(type.base_type == BASE_TYPE_ARRAY));
|
||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
||||
// Vector can't use initialization list.
|
||||
FLATBUFFERS_ASSERT(field->value.constant == "0");
|
||||
@@ -963,6 +997,10 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
val.constant = NumToString(off);
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_ARRAY: {
|
||||
ECHECK(ParseArray(val));
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_INT:
|
||||
case BASE_TYPE_UINT:
|
||||
case BASE_TYPE_LONG:
|
||||
@@ -983,11 +1021,16 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
}
|
||||
|
||||
void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) {
|
||||
SerializeStruct(builder_, struct_def, val);
|
||||
}
|
||||
|
||||
void Parser::SerializeStruct(FlatBufferBuilder &builder,
|
||||
const StructDef &struct_def, const Value &val) {
|
||||
FLATBUFFERS_ASSERT(val.constant.length() == struct_def.bytesize);
|
||||
builder_.Align(struct_def.minalign);
|
||||
builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
|
||||
struct_def.bytesize);
|
||||
builder_.AddStructOffset(val.offset, builder_.GetSize());
|
||||
builder.Align(struct_def.minalign);
|
||||
builder.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
|
||||
struct_def.bytesize);
|
||||
builder.AddStructOffset(val.offset, builder.GetSize());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
@@ -1161,7 +1204,13 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
||||
break;
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD);
|
||||
#undef FLATBUFFERS_TD
|
||||
// clang-format on
|
||||
case BASE_TYPE_ARRAY:
|
||||
builder_.Pad(field->padding);
|
||||
builder_.PushBytes(
|
||||
reinterpret_cast<const uint8_t*>(field_value.constant.c_str()),
|
||||
InlineSize(field_value.type));
|
||||
break;
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1244,6 +1293,54 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseArray(Value &array) {
|
||||
std::vector<Value> stack;
|
||||
FlatBufferBuilder builder;
|
||||
const auto &type = array.type.VectorType();
|
||||
auto length = array.type.fixed_length;
|
||||
uoffset_t count = 0;
|
||||
auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
|
||||
vector_emplace_back(&stack, Value());
|
||||
auto &val = stack.back();
|
||||
val.type = type;
|
||||
if (IsStruct(type)) {
|
||||
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
|
||||
} else {
|
||||
ECHECK(ParseSingleValue(nullptr, val, false));
|
||||
}
|
||||
return NoError();
|
||||
});
|
||||
ECHECK(err);
|
||||
if (length != count) return Error("Fixed-length array size is incorrect.");
|
||||
|
||||
for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
|
||||
auto &val = *it;
|
||||
// clang-format off
|
||||
switch (val.type.base_type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
if (IsStruct(val.type)) { \
|
||||
SerializeStruct(builder, *val.type.struct_def, val); \
|
||||
} else { \
|
||||
CTYPE elem; \
|
||||
ECHECK(atot(val.constant.c_str(), *this, &elem)); \
|
||||
builder.PushElement(elem); \
|
||||
} \
|
||||
break;
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
default: FLATBUFFERS_ASSERT(0);
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
array.constant.assign(
|
||||
reinterpret_cast<const char *>(builder.GetCurrentBufferPointer()),
|
||||
InlineSize(array.type));
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def) {
|
||||
@@ -1989,6 +2086,13 @@ bool Parser::SupportsAdvancedUnionFeatures() const {
|
||||
IDLOptions::kBinary)) == 0;
|
||||
}
|
||||
|
||||
bool Parser::SupportsAdvancedArrayFeatures() const {
|
||||
return (opts.lang_to_generate &
|
||||
~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava |
|
||||
IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson |
|
||||
IDLOptions::kBinary)) == 0;
|
||||
}
|
||||
|
||||
Namespace *Parser::UniqueNamespace(Namespace *ns) {
|
||||
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
|
||||
if (ns->components == (*it)->components) {
|
||||
@@ -3171,19 +3275,22 @@ bool EnumVal::Deserialize(const Parser &parser,
|
||||
|
||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||
return reflection::CreateType(
|
||||
*builder,
|
||||
static_cast<reflection::BaseType>(base_type),
|
||||
*builder, static_cast<reflection::BaseType>(base_type),
|
||||
static_cast<reflection::BaseType>(element),
|
||||
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1));
|
||||
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1),
|
||||
fixed_length);
|
||||
}
|
||||
|
||||
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
|
||||
if (type == nullptr) return true;
|
||||
base_type = static_cast<BaseType>(type->base_type());
|
||||
element = static_cast<BaseType>(type->element());
|
||||
fixed_length = type->fixed_length();
|
||||
if (type->index() >= 0) {
|
||||
bool is_series = type->base_type() == reflection::Vector ||
|
||||
type->base_type() == reflection::Array;
|
||||
if (type->base_type() == reflection::Obj ||
|
||||
(type->base_type() == reflection::Vector &&
|
||||
(is_series &&
|
||||
type->element() == reflection::Obj)) {
|
||||
if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
|
||||
struct_def = parser.structs_.vec[type->index()];
|
||||
|
||||
Reference in New Issue
Block a user