diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 531d65fdc..8afde1ef8 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -580,7 +580,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function { auto _e = mana(); _o->mana = _e; } { auto _e = hp(); _o->hp = _e; } { auto _e = name(); if (_e) _o->name = _e->str(); } - { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } } + { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->inventory.begin()); } } { auto _e = color(); _o->color = _e; } { auto _e = weapons(); if (_e) { _o->weapons.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons[_i] = flatbuffers::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = equipped_type(); _o->equipped.type = _e; } diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 404353378..dabc385bb 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -2498,58 +2498,75 @@ class CppGenerator : public BaseGenerator { std::string code; switch (field.value.type.base_type) { case BASE_TYPE_VECTOR: { - auto cpp_type = field.attributes.Lookup("cpp_type"); - std::string indexing; - if (field.value.type.enum_def) { - indexing += "static_cast<" + - WrapInNameSpace(*field.value.type.enum_def) + ">("; - } - indexing += "_e->Get(_i)"; - if (field.value.type.enum_def) { indexing += ")"; } - if (field.value.type.element == BASE_TYPE_BOOL) { indexing += " != 0"; } - - // Generate code that pushes data from _e to _o in the form: - // for (uoffset_t i = 0; i < _e->size(); ++i) { - // _o->field.push_back(_e->Get(_i)); - // } auto name = Name(field); if (field.value.type.element == BASE_TYPE_UTYPE) { name = StripUnionType(Name(field)); } - auto access = - field.value.type.element == BASE_TYPE_UTYPE - ? ".type" - : (field.value.type.element == BASE_TYPE_UNION ? ".value" : ""); code += "{ _o->" + name + ".resize(_e->size()); "; - code += "for (flatbuffers::uoffset_t _i = 0;"; - code += " _i < _e->size(); _i++) { "; - if (cpp_type) { - // Generate code that resolves the cpp pointer type, of the form: - // if (resolver) - // (*resolver)(&_o->field, (hash_value_t)(_e)); - // else - // _o->field = nullptr; - code += "//vector resolver, " + PtrType(&field) + "\n"; - code += "if (_resolver) "; - code += "(*_resolver)"; - code += "(reinterpret_cast(&_o->" + name + "[_i]" + access + - "), "; - code += "static_cast(" + indexing + "));"; - if (PtrType(&field) == "naked") { - code += " else "; - code += "_o->" + name + "[_i]" + access + " = nullptr"; - } else { - // code += " else "; - // code += "_o->" + name + "[_i]" + access + " = " + - // GenTypeNativePtr(cpp_type->constant, &field, true) + "();"; - code += "/* else do nothing */"; - } + if (!field.value.type.enum_def && !IsBool(field.value.type.element) && + IsOneByte(field.value.type.element)) { + // For vectors of bytes, std::copy is used to improve performance. + // This doesn't work for: + // - enum types because they have to be explicitly static_cast. + // - vectors of bool, since they are a template specialization. + // - multiple-byte types due to endianness. + code += + "std::copy(_e->begin(), _e->end(), _o->" + name + ".begin()); }"; } else { - code += "_o->" + name + "[_i]" + access + " = "; - code += GenUnpackVal(field.value.type.VectorType(), indexing, true, - field); + std::string indexing; + if (field.value.type.enum_def) { + indexing += "static_cast<" + + WrapInNameSpace(*field.value.type.enum_def) + ">("; + } + indexing += "_e->Get(_i)"; + if (field.value.type.enum_def) { + indexing += ")"; + } + if (field.value.type.element == BASE_TYPE_BOOL) { + indexing += " != 0"; + } + // Generate code that pushes data from _e to _o in the form: + // for (uoffset_t i = 0; i < _e->size(); ++i) { + // _o->field.push_back(_e->Get(_i)); + // } + auto access = + field.value.type.element == BASE_TYPE_UTYPE + ? ".type" + : (field.value.type.element == BASE_TYPE_UNION ? ".value" + : ""); + + code += "for (flatbuffers::uoffset_t _i = 0;"; + code += " _i < _e->size(); _i++) { "; + auto cpp_type = field.attributes.Lookup("cpp_type"); + if (cpp_type) { + // Generate code that resolves the cpp pointer type, of the form: + // if (resolver) + // (*resolver)(&_o->field, (hash_value_t)(_e)); + // else + // _o->field = nullptr; + code += "//vector resolver, " + PtrType(&field) + "\n"; + code += "if (_resolver) "; + code += "(*_resolver)"; + code += "(reinterpret_cast(&_o->" + name + "[_i]" + + access + "), "; + code += + "static_cast(" + indexing + "));"; + if (PtrType(&field) == "naked") { + code += " else "; + code += "_o->" + name + "[_i]" + access + " = nullptr"; + } else { + // code += " else "; + // code += "_o->" + name + "[_i]" + access + " = " + + // GenTypeNativePtr(cpp_type->constant, &field, true) + "();"; + code += "/* else do nothing */"; + } + } else { + code += "_o->" + name + "[_i]" + access + " = "; + code += GenUnpackVal(field.value.type.VectorType(), indexing, true, + field); + } + code += "; } }"; } - code += "; } }"; break; } case BASE_TYPE_UTYPE: { diff --git a/tests/cpp17/generated_cpp17/monster_test_generated.h b/tests/cpp17/generated_cpp17/monster_test_generated.h index baa3a6e1e..6ec52bf30 100644 --- a/tests/cpp17/generated_cpp17/monster_test_generated.h +++ b/tests/cpp17/generated_cpp17/monster_test_generated.h @@ -2298,7 +2298,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function { auto _e = mana(); _o->mana = _e; } { auto _e = hp(); _o->hp = _e; } { auto _e = name(); if (_e) _o->name = _e->str(); } - { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } } + { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->inventory.begin()); } } { auto _e = color(); _o->color = _e; } { auto _e = test_type(); _o->test.type = _e; } { auto _e = test(); if (_e) _o->test.value = MyGame::Example::AnyUnion::UnPack(_e, test_type(), _resolver); } @@ -2306,7 +2306,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function { auto _e = testarrayofstring(); if (_e) { _o->testarrayofstring.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring[_i] = _e->Get(_i)->str(); } } } { auto _e = testarrayoftables(); if (_e) { _o->testarrayoftables.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = enemy(); if (_e) _o->enemy = std::unique_ptr(_e->UnPack(_resolver)); } - { auto _e = testnestedflatbuffer(); if (_e) { _o->testnestedflatbuffer.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer[_i] = _e->Get(_i); } } } + { auto _e = testnestedflatbuffer(); if (_e) { _o->testnestedflatbuffer.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->testnestedflatbuffer.begin()); } } { auto _e = testempty(); if (_e) _o->testempty = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = testbool(); _o->testbool = _e; } { auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; } @@ -2324,7 +2324,7 @@ if (_resolver) (*_resolver)(reinterpret_cast(&_o->testhashu32_fnv1a), s { auto _e = testf3(); _o->testf3 = _e; } { auto _e = testarrayofstring2(); if (_e) { _o->testarrayofstring2.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring2[_i] = _e->Get(_i)->str(); } } } { auto _e = testarrayofsortedstruct(); if (_e) { _o->testarrayofsortedstruct.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofsortedstruct[_i] = *_e->Get(_i); } } } - { auto _e = flex(); if (_e) { _o->flex.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->flex[_i] = _e->Get(_i); } } } + { auto _e = flex(); if (_e) { _o->flex.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->flex.begin()); } } { auto _e = test5(); if (_e) { _o->test5.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test5[_i] = *_e->Get(_i); } } } { auto _e = vector_of_longs(); if (_e) { _o->vector_of_longs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vector_of_longs[_i] = _e->Get(_i); } } } { auto _e = vector_of_doubles(); if (_e) { _o->vector_of_doubles.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vector_of_doubles[_i] = _e->Get(_i); } } } @@ -2478,7 +2478,7 @@ inline void TypeAliases::UnPackTo(TypeAliasesT *_o, const flatbuffers::resolver_ { auto _e = u64(); _o->u64 = _e; } { auto _e = f32(); _o->f32 = _e; } { auto _e = f64(); _o->f64 = _e; } - { auto _e = v8(); if (_e) { _o->v8.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->v8[_i] = _e->Get(_i); } } } + { auto _e = v8(); if (_e) { _o->v8.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->v8.begin()); } } { auto _e = vf64(); if (_e) { _o->vf64.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vf64[_i] = _e->Get(_i); } } } } diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index b932622bf..98830af15 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -2580,7 +2580,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function { auto _e = mana(); _o->mana = _e; } { auto _e = hp(); _o->hp = _e; } { auto _e = name(); if (_e) _o->name = _e->str(); } - { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } } + { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->inventory.begin()); } } { auto _e = color(); _o->color = _e; } { auto _e = test_type(); _o->test.type = _e; } { auto _e = test(); if (_e) _o->test.value = MyGame::Example::AnyUnion::UnPack(_e, test_type(), _resolver); } @@ -2588,7 +2588,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function { auto _e = testarrayofstring(); if (_e) { _o->testarrayofstring.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring[_i] = _e->Get(_i)->str(); } } } { auto _e = testarrayoftables(); if (_e) { _o->testarrayoftables.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables[_i] = flatbuffers::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = enemy(); if (_e) _o->enemy = flatbuffers::unique_ptr(_e->UnPack(_resolver)); } - { auto _e = testnestedflatbuffer(); if (_e) { _o->testnestedflatbuffer.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer[_i] = _e->Get(_i); } } } + { auto _e = testnestedflatbuffer(); if (_e) { _o->testnestedflatbuffer.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->testnestedflatbuffer.begin()); } } { auto _e = testempty(); if (_e) _o->testempty = flatbuffers::unique_ptr(_e->UnPack(_resolver)); } { auto _e = testbool(); _o->testbool = _e; } { auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; } @@ -2606,7 +2606,7 @@ if (_resolver) (*_resolver)(reinterpret_cast(&_o->testhashu32_fnv1a), s { auto _e = testf3(); _o->testf3 = _e; } { auto _e = testarrayofstring2(); if (_e) { _o->testarrayofstring2.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring2[_i] = _e->Get(_i)->str(); } } } { auto _e = testarrayofsortedstruct(); if (_e) { _o->testarrayofsortedstruct.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofsortedstruct[_i] = *_e->Get(_i); } } } - { auto _e = flex(); if (_e) { _o->flex.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->flex[_i] = _e->Get(_i); } } } + { auto _e = flex(); if (_e) { _o->flex.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->flex.begin()); } } { auto _e = test5(); if (_e) { _o->test5.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test5[_i] = *_e->Get(_i); } } } { auto _e = vector_of_longs(); if (_e) { _o->vector_of_longs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vector_of_longs[_i] = _e->Get(_i); } } } { auto _e = vector_of_doubles(); if (_e) { _o->vector_of_doubles.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vector_of_doubles[_i] = _e->Get(_i); } } } @@ -2760,7 +2760,7 @@ inline void TypeAliases::UnPackTo(TypeAliasesT *_o, const flatbuffers::resolver_ { auto _e = u64(); _o->u64 = _e; } { auto _e = f32(); _o->f32 = _e; } { auto _e = f64(); _o->f64 = _e; } - { auto _e = v8(); if (_e) { _o->v8.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->v8[_i] = _e->Get(_i); } } } + { auto _e = v8(); if (_e) { _o->v8.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->v8.begin()); } } { auto _e = vf64(); if (_e) { _o->vf64.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vf64[_i] = _e->Get(_i); } } } }