diff --git a/doc/changelog.dox b/doc/changelog.dox index b018316e4..c1a560c72 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -746,6 +746,7 @@ See also: @ref MeshTools::concatenate(const Containers::Iterable&, InterleaveFlags) optionally take a @ref MeshTools::InterleaveFlags parameter affecting the output, in particular whether to preserve the original interleaved layout. +- @ref MeshTools::interleaveInto() now returns the actually filled size - @ref MeshTools::concatenate() now allows concatenating an array attribute into an array attribute with more elements. The remaining elements are zero-filled, similarly to how missing attributes are handled. To avoid diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 8426910b9..3d293ad0a 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -171,6 +171,7 @@ template void interleaveInto(Containers::ArrayView buffer, const T& first, const U&... next) { +template std::size_t interleaveInto(Containers::ArrayView buffer, const T& first, const U&... next) { /* Verify expected buffer size */ - #ifndef CORRADE_NO_ASSERT const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); - #endif const std::size_t stride = Implementation::Stride{}(first, next...); - CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), ); + CORRADE_ASSERT(attributeCount*stride <= buffer.size(), + "MeshTools::interleaveInto(): expected a buffer of at least" << attributeCount*stride << "bytes but got" << buffer.size(), {}); /* Write data */ Implementation::writeInterleaved(stride, buffer.begin(), first, next...); + + return attributeCount*stride; } /** diff --git a/src/Magnum/MeshTools/Test/InterleaveTest.cpp b/src/Magnum/MeshTools/Test/InterleaveTest.cpp index a35b92c0c..948fa9d7b 100644 --- a/src/Magnum/MeshTools/Test/InterleaveTest.cpp +++ b/src/Magnum/MeshTools/Test/InterleaveTest.cpp @@ -56,6 +56,8 @@ struct InterleaveTest: Corrade::TestSuite::Tester { void interleaveEmpty(); void interleaveInto(); + void interleaveIntoLarger(); + void interleaveIntoInvalid(); void interleavedData(); void interleavedDataUnordered(); @@ -142,6 +144,8 @@ InterleaveTest::InterleaveTest() { &InterleaveTest::interleaveEmpty, &InterleaveTest::interleaveInto, + &InterleaveTest::interleaveIntoLarger, + &InterleaveTest::interleaveIntoInvalid, &InterleaveTest::interleavedData, &InterleaveTest::interleavedDataUnordered, @@ -293,7 +297,8 @@ void InterleaveTest::interleaveInto() { 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77}}; - MeshTools::interleaveInto(data, 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3); + CORRADE_COMPARE(data.size(), 48); + CORRADE_COMPARE(MeshTools::interleaveInto(data, 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3), 48); if(!Utility::Endianness::isBigEndian()) { /* _______gap, int___________________, _gap, short_____, _____________gap */ @@ -314,6 +319,50 @@ void InterleaveTest::interleaveInto() { } } +void InterleaveTest::interleaveIntoLarger() { + /* Same as interleaveInto(), just with the data buffer being larger */ + + Containers::Array data{InPlaceInit, { + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11}}; + + CORRADE_COMPARE(data.size(), 49); + CORRADE_COMPARE(MeshTools::interleaveInto(data, 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3), 48); + + if(!Utility::Endianness::isBigEndian()) { + /* _______gap, int___________________, _gap, short_____, _____________gap */ + CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ + 0x11, 0x33, 0x04, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x05, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x06, 0x00, 0x00, 0x00, 0x55, 0x02, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x07, 0x00, 0x00, 0x00, 0x55, 0x03, 0x00, 0x33, 0x55, 0x77, + 0x11 + })); + } else { + /* _______gap, ___________________int, _gap, _____short, _____________gap */ + CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ + 0x11, 0x33, 0x00, 0x00, 0x00, 0x04, 0x55, 0x00, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x05, 0x55, 0x00, 0x01, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x06, 0x55, 0x00, 0x02, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x07, 0x55, 0x00, 0x03, 0x33, 0x55, 0x77, + 0x11 + })); + } +} + +void InterleaveTest::interleaveIntoInvalid() { + CORRADE_SKIP_IF_NO_ASSERT(); + + Containers::Array data{NoInit, 23}; + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::interleaveInto(data, 2, Containers::arrayView({1, 2, 3, 4})); + CORRADE_COMPARE(out.str(), "MeshTools::interleaveInto(): expected a buffer of at least 24 bytes but got 23\n"); +} + void InterleaveTest::interleavedData() { Containers::Array vertexData{100 + 3*20}; Containers::StridedArrayView1D positions{vertexData,