From 1ce936cfc217a458aa9a656a822f5c23691d5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 19 Feb 2022 21:55:43 +0100 Subject: [PATCH] Utility: support C++17 std::string_view in format(). --- doc/corrade-changelog.dox | 2 + src/Corrade/Utility/CMakeLists.txt | 1 + src/Corrade/Utility/Format.h | 1 + src/Corrade/Utility/FormatStl.h | 3 +- src/Corrade/Utility/FormatStlStringView.h | 60 ++++++++++++++++++ src/Corrade/Utility/Test/CMakeLists.txt | 10 ++- .../Utility/Test/FormatStlStringViewTest.cpp | 62 +++++++++++++++++++ 7 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 src/Corrade/Utility/FormatStlStringView.h create mode 100644 src/Corrade/Utility/Test/FormatStlStringViewTest.cpp diff --git a/doc/corrade-changelog.dox b/doc/corrade-changelog.dox index 96bbf1575..6d2a64325 100644 --- a/doc/corrade-changelog.dox +++ b/doc/corrade-changelog.dox @@ -203,6 +203,8 @@ namespace Corrade { sense from a portability point of view. - @ref Utility::format() now supports printing integers as characters using the @cpp "{:c}" @ce modifier +- @ref Utility::format() now accepts also a C++17 @ref std::string_view if + you include @ref Corrade/Utility/FormatStlStringView.h - @ref Utility::String::split() and @ref Utility::String::splitWithoutEmptyParts() now have @ref Containers::StringView overloads that allocate much less diff --git a/src/Corrade/Utility/CMakeLists.txt b/src/Corrade/Utility/CMakeLists.txt index d3a4d892b..24ad4a329 100644 --- a/src/Corrade/Utility/CMakeLists.txt +++ b/src/Corrade/Utility/CMakeLists.txt @@ -62,6 +62,7 @@ if(WITH_UTILITY) EndiannessBatch.h Format.h FormatStl.h + FormatStlStringView.h Macros.h Memory.h Move.h diff --git a/src/Corrade/Utility/Format.h b/src/Corrade/Utility/Format.h index e03ba6d90..49f8a318c 100644 --- a/src/Corrade/Utility/Format.h +++ b/src/Corrade/Utility/Format.h @@ -88,6 +88,7 @@ In order to write a literal curly brace to the output, simply double it: | @ref Containers::StringView, \n @ref Containers::MutableStringView "MutableStringView", @ref Containers::String "String" | Written as a sequence of @ref Containers::StringView::size() characters | @ref Containers::ArrayView "Containers::ArrayView" @m_class{m-label m-danger} **deprecated** | Written as a sequence of @ref Containers::ArrayView::size() characters. \n Deprecated, use @ref Containers::StringView instead. | @ref std::string | Written as a sequence of @ref std::string::size() characters \n (@cpp #include @ce @ref Corrade/Utility/FormatStl.h in addition) +| @ref std::string_view | Written as a sequence of @ref std::string_view::size() characters \n (@cpp #include @ce @ref Corrade/Utility/FormatStlStringView.h in addition) # Advanced formatting options diff --git a/src/Corrade/Utility/FormatStl.h b/src/Corrade/Utility/FormatStl.h index 4448b2fe8..004a2fd84 100644 --- a/src/Corrade/Utility/FormatStl.h +++ b/src/Corrade/Utility/FormatStl.h @@ -31,7 +31,8 @@ @m_since{2019,10} Including this header also allows you to use @ref std::string in arguments to -@ref Utility::format(). +@ref Utility::format(). A separate @ref Corrade/Utility/FormatStlStringView.h +header provides compatibility with @ref std::string_view from C++17. @experimental */ diff --git a/src/Corrade/Utility/FormatStlStringView.h b/src/Corrade/Utility/FormatStlStringView.h new file mode 100644 index 000000000..3c600a050 --- /dev/null +++ b/src/Corrade/Utility/FormatStlStringView.h @@ -0,0 +1,60 @@ +#ifndef Corrade_Utility_FormatStlStringView_h +#define Corrade_Utility_FormatStlStringView_h +/* + This file is part of Corrade. + + Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, + 2017, 2018, 2019, 2020, 2021, 2022 + 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. +*/ + +/** @file +STL @ref std::string_view compatibility for @ref Utility::format() +@m_since_latest + +Including this header allows you to use a C++17 @ref std::string_view in +arguments to @ref Utility::format(). A separate @ref Corrade/Utility/FormatStl.h +header provides compatibility with @ref std::string. +@experimental +*/ + +#include + +#include "Corrade/Containers/StringView.h" +#include "Corrade/Utility/Format.h" + +/* Listing these namespaces doesn't add anything to the docs, so don't */ +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Corrade { namespace Utility { namespace Implementation { + +template<> struct Formatter { + static std::size_t format(const Containers::MutableStringView& buffer, std::string_view value, int precision, FormatType type) { + return Formatter::format(buffer, {value.data(), value.size()}, precision, type); + } + static void format(std::FILE* file, std::string_view value, int precision, FormatType type) { + return Formatter::format(file, {value.data(), value.size()}, precision, type); + } +}; + +}}} +#endif + +#endif diff --git a/src/Corrade/Utility/Test/CMakeLists.txt b/src/Corrade/Utility/Test/CMakeLists.txt index 9af801ff9..4c49c08d1 100644 --- a/src/Corrade/Utility/Test/CMakeLists.txt +++ b/src/Corrade/Utility/Test/CMakeLists.txt @@ -171,10 +171,14 @@ if(NOT CMAKE_CXX_FLAGS MATCHES "-std=") (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.3") OR (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.10")) + corrade_add_test(UtilityFormatStlStringViewTest FormatStlStringViewTest.cpp) corrade_add_test(UtilityMacrosCpp17Test MacrosCpp17Test.cpp) - set_target_properties(UtilityMacrosCpp17Test PROPERTIES - CORRADE_CXX_STANDARD 17 - FOLDER "Corrade/Utility/Test") + set_target_properties( + UtilityFormatStlStringViewTest + UtilityMacrosCpp17Test + PROPERTIES + CORRADE_CXX_STANDARD 17 + FOLDER "Corrade/Utility/Test") endif() # Copied verbatim from src/Corrade/Test/CMakeLists.txt, please keep in sync diff --git a/src/Corrade/Utility/Test/FormatStlStringViewTest.cpp b/src/Corrade/Utility/Test/FormatStlStringViewTest.cpp new file mode 100644 index 000000000..b3fe4dcae --- /dev/null +++ b/src/Corrade/Utility/Test/FormatStlStringViewTest.cpp @@ -0,0 +1,62 @@ +/* + This file is part of Corrade. + + Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, + 2017, 2018, 2019, 2020, 2021, 2022 + 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. +*/ + +#include "Corrade/Containers/String.h" +#include "Corrade/TestSuite/Tester.h" +#include "Corrade/Utility/FormatStlStringView.h" + +namespace Corrade { namespace Utility { namespace Test { namespace { + +struct FormatStlStringViewTest: TestSuite::Tester { + explicit FormatStlStringViewTest(); + + void test(); + void testEmpty(); +}; + +FormatStlStringViewTest::FormatStlStringViewTest() { + addTests({&FormatStlStringViewTest::test, + &FormatStlStringViewTest::testEmpty}); +} + +using namespace Containers::Literals; +using namespace std::string_view_literals; + +void FormatStlStringViewTest::test() { + CORRADE_COMPARE(format("hello {}", std::string_view{"worlds", 5}), + "hello world"); + CORRADE_COMPARE(format("hello {}", "world\0, i guess?"sv), + "hello world\0, i guess?"_s); +} + +void FormatStlStringViewTest::testEmpty() { + /* Empty string view should not cause any issues with data access */ + CORRADE_COMPARE(format("hello{}!", std::string_view{}), "hello!"); +} + +}}}} + +CORRADE_TEST_MAIN(Corrade::Utility::Test::FormatStlStringViewTest)