diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 00fd8c3bd..b0ff71ed5 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -64,7 +64,11 @@ set(Magnum_HEADERS visibility.h) set(Magnum_PRIVATE_HEADERS - Implementation/ImageProperties.h) + Implementation/ImageProperties.h + + Implementation/meshIndexTypeMapping.hpp + Implementation/meshPrimitiveMapping.hpp + Implementation/compressedPixelFormatMapping.hpp) # Functionality specific to static Windows builds if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT AND MAGNUM_BUILD_STATIC) diff --git a/src/Magnum/Implementation/meshIndexTypeMapping.hpp b/src/Magnum/Implementation/meshIndexTypeMapping.hpp new file mode 100644 index 000000000..df4b022f8 --- /dev/null +++ b/src/Magnum/Implementation/meshIndexTypeMapping.hpp @@ -0,0 +1,31 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Each entry is just the name, for debug output and configuration to string */ +#ifdef _c +_c(UnsignedByte) +_c(UnsignedShort) +_c(UnsignedInt) +#endif diff --git a/src/Magnum/Implementation/meshPrimitiveMapping.hpp b/src/Magnum/Implementation/meshPrimitiveMapping.hpp new file mode 100644 index 000000000..0f503c8a4 --- /dev/null +++ b/src/Magnum/Implementation/meshPrimitiveMapping.hpp @@ -0,0 +1,35 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Each entry is just the name, for debug output and configuration to string */ +#ifdef _c +_c(Points) +_c(Lines) +_c(LineLoop) +_c(LineStrip) +_c(Triangles) +_c(TriangleStrip) +_c(TriangleFan) +#endif diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index b96a24bfc..bcfb0829a 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -25,6 +25,7 @@ #include "Mesh.h" +#include #include #include @@ -41,36 +42,44 @@ UnsignedInt meshIndexTypeSize(MeshIndexType type) { } #ifndef DOXYGEN_GENERATING_OUTPUT -Debug& operator<<(Debug& debug, MeshPrimitive value) { - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case MeshPrimitive::value: return debug << "MeshPrimitive::" #value; - _c(Points) - _c(Lines) - _c(LineLoop) - _c(LineStrip) - _c(Triangles) - _c(TriangleStrip) - _c(TriangleFan) - #undef _c - /* LCOV_EXCL_STOP */ +namespace { + +constexpr const char* MeshPrimitiveNames[] { + #define _c(primitive) #primitive, + #include "Magnum/Implementation/meshPrimitiveMapping.hpp" + #undef _c +}; + +} + +Debug& operator<<(Debug& debug, const MeshPrimitive value) { + debug << "MeshPrimitive" << Debug::nospace; + + if(UnsignedInt(value) < Containers::arraySize(MeshPrimitiveNames)) { + return debug << "::" << Debug::nospace << MeshPrimitiveNames[UnsignedInt(value)]; } - return debug << "MeshPrimitive(" << Debug::nospace << reinterpret_cast(UnsignedInt(value)) << Debug::nospace << ")"; + return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedInt(value)) << Debug::nospace << ")"; +} + +namespace { + +constexpr const char* MeshIndexTypeNames[] { + #define _c(type) #type, + #include "Magnum/Implementation/meshIndexTypeMapping.hpp" + #undef _c +}; + } -Debug& operator<<(Debug& debug, MeshIndexType value) { - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case MeshIndexType::value: return debug << "MeshIndexType::" #value; - _c(UnsignedByte) - _c(UnsignedShort) - _c(UnsignedInt) - #undef _c - /* LCOV_EXCL_STOP */ +Debug& operator<<(Debug& debug, const MeshIndexType value) { + debug << "MeshIndexType" << Debug::nospace; + + if(UnsignedInt(value) < Containers::arraySize(MeshIndexTypeNames)) { + return debug << "::" << Debug::nospace << MeshIndexTypeNames[UnsignedInt(value)]; } - return debug << "MeshIndexType(" << Debug::nospace << reinterpret_cast(UnsignedInt(value)) << Debug::nospace << ")"; + return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedInt(value)) << Debug::nospace << ")"; } #endif @@ -79,60 +88,29 @@ Debug& operator<<(Debug& debug, MeshIndexType value) { namespace Corrade { namespace Utility { std::string ConfigurationValue::toString(Magnum::MeshPrimitive value, ConfigurationValueFlags) { - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case Magnum::MeshPrimitive::value: return #value; - _c(Points) - _c(Lines) - _c(LineLoop) - _c(LineStrip) - _c(Triangles) - _c(TriangleStrip) - _c(TriangleFan) - #undef _c - /* LCOV_EXCL_STOP */ - } + if(Magnum::UnsignedInt(value) < Containers::arraySize(Magnum::MeshPrimitiveNames)) + return Magnum::MeshPrimitiveNames[Magnum::UnsignedInt(value)]; return {}; } Magnum::MeshPrimitive ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { - /* LCOV_EXCL_START */ - #define _c(value) if(stringValue == #value) return Magnum::MeshPrimitive::value; - _c(LineStrip) - _c(LineLoop) - _c(Lines) - _c(Triangles) - _c(TriangleStrip) - _c(TriangleFan) - #undef _c - /* LCOV_EXCL_STOP */ + for(std::size_t i = 0; i != Containers::arraySize(Magnum::MeshPrimitiveNames); ++i) + if(stringValue == Magnum::MeshPrimitiveNames[i]) return Magnum::MeshPrimitive(i); return Magnum::MeshPrimitive::Points; } std::string ConfigurationValue::toString(Magnum::MeshIndexType value, ConfigurationValueFlags) { - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case Magnum::MeshIndexType::value: return #value; - _c(UnsignedByte) - _c(UnsignedShort) - _c(UnsignedInt) - #undef _c - /* LCOV_EXCL_STOP */ - } + if(Magnum::UnsignedInt(value) < Containers::arraySize(Magnum::MeshIndexTypeNames)) + return Magnum::MeshIndexTypeNames[Magnum::UnsignedInt(value)]; return {}; } Magnum::MeshIndexType ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { - /* LCOV_EXCL_START */ - #define _c(value) if(stringValue == #value) return Magnum::MeshIndexType::value; - _c(UnsignedByte) - _c(UnsignedShort) - _c(UnsignedInt) - #undef _c - /* LCOV_EXCL_STOP */ + for(std::size_t i = 0; i != Containers::arraySize(Magnum::MeshIndexTypeNames); ++i) + if(stringValue == Magnum::MeshIndexTypeNames[i]) return Magnum::MeshIndexType(i); return Magnum::MeshIndexType::UnsignedInt; } diff --git a/src/Magnum/Test/MeshTest.cpp b/src/Magnum/Test/MeshTest.cpp index 0b22b6b5b..0dc66dc9f 100644 --- a/src/Magnum/Test/MeshTest.cpp +++ b/src/Magnum/Test/MeshTest.cpp @@ -35,6 +35,9 @@ namespace Magnum { namespace Test { namespace { struct MeshTest: TestSuite::Tester { explicit MeshTest(); + void primitiveMapping(); + void indexTypeMapping(); + void indexTypeSize(); void debugPrimitive(); @@ -44,7 +47,10 @@ struct MeshTest: TestSuite::Tester { }; MeshTest::MeshTest() { - addTests({&MeshTest::indexTypeSize, + addTests({&MeshTest::primitiveMapping, + &MeshTest::indexTypeMapping, + + &MeshTest::indexTypeSize, &MeshTest::debugPrimitive, &MeshTest::debugIndexType, @@ -52,6 +58,80 @@ MeshTest::MeshTest() { &MeshTest::configurationIndexType}); } +void MeshTest::primitiveMapping() { + /* This goes through the first 8 bits, which should be enough. */ + UnsignedInt firstUnhandled = 0xff; + UnsignedInt nextHandled = 0; + for(UnsignedInt i = 0; i <= 0xff; ++i) { + const auto primitive = MeshPrimitive(i); + /* Each case verifies: + - that the cases are ordered by number (so insertion here is done in + proper place) + - that there was no gap (unhandled value inside the range) */ + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(primitive) { + #define _c(primitive) \ + case MeshPrimitive::primitive: \ + CORRADE_COMPARE(nextHandled, i); \ + CORRADE_COMPARE(firstUnhandled, 0xff); \ + ++nextHandled; \ + continue; + #include "Magnum/Implementation/meshPrimitiveMapping.hpp" + #undef _c + } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + + /* Not handled by any value, remember -- we might either be at the end + of the enum range (which is okay) or some value might be unhandled + here */ + firstUnhandled = i; + } + + CORRADE_COMPARE(firstUnhandled, 0xff); +} + +void MeshTest::indexTypeMapping() { + /* This goes through the first 8 bits, which should be enough. */ + UnsignedInt firstUnhandled = 0xff; + UnsignedInt nextHandled = 0; + for(UnsignedInt i = 0; i <= 0xff; ++i) { + const auto type = MeshIndexType(i); + /* Each case verifies: + - that the cases are ordered by number (so insertion here is done in + proper place) + - that there was no gap (unhandled value inside the range) */ + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(type) { + #define _c(type) \ + case MeshIndexType::type: \ + CORRADE_COMPARE(nextHandled, i); \ + CORRADE_COMPARE(firstUnhandled, 0xff); \ + ++nextHandled; \ + continue; + #include "Magnum/Implementation/meshIndexTypeMapping.hpp" + #undef _c + } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + + /* Not handled by any value, remember -- we might either be at the end + of the enum range (which is okay) or some value might be unhandled + here */ + firstUnhandled = i; + } + + CORRADE_COMPARE(firstUnhandled, 0xff); +} + void MeshTest::indexTypeSize() { CORRADE_COMPARE(meshIndexTypeSize(MeshIndexType::UnsignedByte), 1); CORRADE_COMPARE(meshIndexTypeSize(MeshIndexType::UnsignedShort), 2);