forked from BigfootDev/flatbuffers
[C++] Generate code for vector force_align attribute. (#5796)
* [Flatbuffer] Generate code for force_align with CreateXDirect and Pack functions. * Fixed Visual Studio 10.0 compile error for std::to_string. * Fixed Visual Studio 10.0 compile error for std::to_string.
This commit is contained in:
@@ -345,6 +345,9 @@ Current understood attributes:
|
|||||||
Note: currently not guaranteed to have an effect when used with
|
Note: currently not guaranteed to have an effect when used with
|
||||||
`--object-api`, since that may allocate objects at alignments less than
|
`--object-api`, since that may allocate objects at alignments less than
|
||||||
what you specify with `force_align`.
|
what you specify with `force_align`.
|
||||||
|
- `force_align: size` (on a vector): force the alignment of this vector to be
|
||||||
|
something different than what the element size would normally dictate.
|
||||||
|
Note: Now only work for generated C++ code.
|
||||||
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
||||||
meaning that any unsigned value N specified in the schema will end up
|
meaning that any unsigned value N specified in the schema will end up
|
||||||
representing 1<<N, or if you don't specify values at all, you'll get
|
representing 1<<N, or if you don't specify values at all, you'll get
|
||||||
|
|||||||
@@ -2152,6 +2152,25 @@ class CppGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate code to force vector alignment. Return empty string for vector
|
||||||
|
// that doesn't need alignment code.
|
||||||
|
std::string GenVectorForceAlign(const FieldDef &field,
|
||||||
|
const std::string &field_size) {
|
||||||
|
FLATBUFFERS_ASSERT(field.value.type.base_type == BASE_TYPE_VECTOR);
|
||||||
|
// Get the value of the force_align attribute.
|
||||||
|
const auto *force_align = field.attributes.Lookup("force_align");
|
||||||
|
const int align = force_align ? atoi(force_align->constant.c_str()) : 1;
|
||||||
|
// Generate code to do force_align for the vector.
|
||||||
|
if (align > 1) {
|
||||||
|
const auto vtype = field.value.type.VectorType();
|
||||||
|
const auto type = IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
|
||||||
|
: GenTypeWire(vtype, "", false);
|
||||||
|
return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type +
|
||||||
|
"), " + std::to_string(static_cast<long long>(align)) + ");";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void GenBuilders(const StructDef &struct_def) {
|
void GenBuilders(const StructDef &struct_def) {
|
||||||
code_.SetValue("STRUCT_NAME", Name(struct_def));
|
code_.SetValue("STRUCT_NAME", Name(struct_def));
|
||||||
|
|
||||||
@@ -2307,6 +2326,11 @@ class CppGenerator : public BaseGenerator {
|
|||||||
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
|
" auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
|
||||||
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
|
"_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
|
||||||
} else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
} else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||||
|
const std::string force_align_code =
|
||||||
|
GenVectorForceAlign(field, Name(field) + "->size()");
|
||||||
|
if (!force_align_code.empty()) {
|
||||||
|
code_ += " if ({{FIELD_NAME}}) { " + force_align_code + " }";
|
||||||
|
}
|
||||||
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
|
code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
|
||||||
const auto vtype = field.value.type.VectorType();
|
const auto vtype = field.value.type.VectorType();
|
||||||
const auto has_key = TypeHasKey(vtype);
|
const auto has_key = TypeHasKey(vtype);
|
||||||
@@ -2766,6 +2790,11 @@ class CppGenerator : public BaseGenerator {
|
|||||||
it != struct_def.fields.vec.end(); ++it) {
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
if (field.deprecated) { continue; }
|
if (field.deprecated) { continue; }
|
||||||
|
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||||
|
const std::string force_align_code =
|
||||||
|
GenVectorForceAlign(field, "_o->" + Name(field) + ".size()");
|
||||||
|
if (!force_align_code.empty()) { code_ += " " + force_align_code; }
|
||||||
|
}
|
||||||
code_ += " auto _" + Name(field) + " = " + GenCreateParam(field) + ";";
|
code_ += " auto _" + Name(field) + " = " + GenCreateParam(field) + ";";
|
||||||
}
|
}
|
||||||
// Need to call "Create" with the struct namespace.
|
// Need to call "Create" with the struct namespace.
|
||||||
|
|||||||
@@ -1293,8 +1293,15 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
|
|||||||
});
|
});
|
||||||
ECHECK(err);
|
ECHECK(err);
|
||||||
|
|
||||||
builder_.StartVector(count * InlineSize(type) / InlineAlignment(type),
|
const auto *force_align = field->attributes.Lookup("force_align");
|
||||||
InlineAlignment(type));
|
const size_t align =
|
||||||
|
force_align ? static_cast<size_t>(atoi(force_align->constant.c_str()))
|
||||||
|
: 1;
|
||||||
|
const size_t len = count * InlineSize(type) / InlineAlignment(type);
|
||||||
|
const size_t elemsize = InlineAlignment(type);
|
||||||
|
if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
|
||||||
|
|
||||||
|
builder_.StartVector(len, elemsize);
|
||||||
for (uoffset_t i = 0; i < count; i++) {
|
for (uoffset_t i = 0; i < count; i++) {
|
||||||
// start at the back, since we're building the data backwards.
|
// start at the back, since we're building the data backwards.
|
||||||
auto &val = field_stack_.back().first;
|
auto &val = field_stack_.back().first;
|
||||||
|
|||||||
Reference in New Issue
Block a user