From ad7ec1e5266e410da43b80d28fbdfefcc9743365 Mon Sep 17 00:00:00 2001 From: ZXShady <153229951+ZXShady@users.noreply.github.com> Date: Fri, 12 Sep 2025 00:52:11 +0300 Subject: [PATCH 1/3] Outline catch_strnlen's definition into catch_tostring.cpp --- src/catch2/catch_tostring.cpp | 6 ++++++ src/catch2/catch_tostring.hpp | 8 +------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/catch2/catch_tostring.cpp b/src/catch2/catch_tostring.cpp index cc6865674b..20b0a62986 100644 --- a/src/catch2/catch_tostring.cpp +++ b/src/catch2/catch_tostring.cpp @@ -57,6 +57,12 @@ namespace Detail { } } // end unnamed namespace + std::size_t catch_strnlen( const char* str, std::size_t n ) { + auto ret = std::char_traits::find( str, n, '\0' ); + if ( ret != nullptr ) { return static_cast( ret - str ); } + return n; + } + std::string convertIntoString(StringRef string, bool escapeInvisibles) { std::string ret; // This is enough for the "don't escape invisibles" case, and a good diff --git a/src/catch2/catch_tostring.hpp b/src/catch2/catch_tostring.hpp index 41f89413c4..aca1f7e02f 100644 --- a/src/catch2/catch_tostring.hpp +++ b/src/catch2/catch_tostring.hpp @@ -40,13 +40,7 @@ namespace Catch { namespace Detail { - inline std::size_t catch_strnlen(const char *str, std::size_t n) { - auto ret = std::char_traits::find(str, n, '\0'); - if (ret != nullptr) { - return static_cast(ret - str); - } - return n; - } + std::size_t catch_strnlen(const char *str, std::size_t n); constexpr StringRef unprintableString = "{?}"_sr; From a04b7720630704b8b3d6a676773377a4dc5c9b5a Mon Sep 17 00:00:00 2001 From: ZXShady <153229951+ZXShady@users.noreply.github.com> Date: Fri, 12 Sep 2025 00:52:11 +0300 Subject: [PATCH 2/3] Outline part of formatting system_clock's time_point into cpp file --- src/catch2/catch_tostring.cpp | 24 ++++++++++++++++++++++++ src/catch2/catch_tostring.hpp | 27 ++++----------------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/catch2/catch_tostring.cpp b/src/catch2/catch_tostring.cpp index 20b0a62986..dad6241071 100644 --- a/src/catch2/catch_tostring.cpp +++ b/src/catch2/catch_tostring.cpp @@ -63,6 +63,30 @@ namespace Detail { return n; } + std::string formatTimeT(std::time_t time) { +#ifdef _MSC_VER + std::tm timeInfo = {}; + const auto err = gmtime_s( &timeInfo, &time ); + if ( err ) { + return "gmtime from provided timepoint has failed. This " + "happens e.g. with pre-1970 dates using Microsoft libc"; + } +#else + std::tm* timeInfo = std::gmtime( &time ); +#endif + + auto const timeStampSize = sizeof( "2017-01-16T17:06:45Z" ); + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime( timeStamp, timeStampSize, fmt, &timeInfo ); +#else + std::strftime( timeStamp, timeStampSize, fmt, timeInfo ); +#endif + return std::string( timeStamp, timeStampSize - 1 ); + } + std::string convertIntoString(StringRef string, bool escapeInvisibles) { std::string ret; // This is enough for the "don't escape invisibles" case, and a good diff --git a/src/catch2/catch_tostring.hpp b/src/catch2/catch_tostring.hpp index aca1f7e02f..db0338df6d 100644 --- a/src/catch2/catch_tostring.hpp +++ b/src/catch2/catch_tostring.hpp @@ -8,7 +8,7 @@ #ifndef CATCH_TOSTRING_HPP_INCLUDED #define CATCH_TOSTRING_HPP_INCLUDED - +#include #include #include #include @@ -42,6 +42,8 @@ namespace Catch { std::size_t catch_strnlen(const char *str, std::size_t n); + std::string formatTimeT( std::time_t time ); + constexpr StringRef unprintableString = "{?}"_sr; //! Encases `string in quotes, and optionally escapes invisibles @@ -629,28 +631,7 @@ struct ratio_string { const auto systemish = std::chrono::time_point_cast< std::chrono::system_clock::duration>( time_point ); const auto as_time_t = std::chrono::system_clock::to_time_t( systemish ); - -#ifdef _MSC_VER - std::tm timeInfo = {}; - const auto err = gmtime_s( &timeInfo, &as_time_t ); - if ( err ) { - return "gmtime from provided timepoint has failed. This " - "happens e.g. with pre-1970 dates using Microsoft libc"; - } -#else - std::tm* timeInfo = std::gmtime( &as_time_t ); -#endif - - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp, timeStampSize - 1); + return ::Catch::Detail::formatTimeT( as_time_t ); } }; } From 2718aec2a203b88c1f649aadde82f50aa1014908 Mon Sep 17 00:00:00 2001 From: ZXShady <153229951+ZXShady@users.noreply.github.com> Date: Fri, 12 Sep 2025 00:52:11 +0300 Subject: [PATCH 3/3] Remove recursion when stringifying std::tuple --- src/catch2/catch_tostring.hpp | 48 +++++++++++++++-------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/catch2/catch_tostring.hpp b/src/catch2/catch_tostring.hpp index db0338df6d..b005212f83 100644 --- a/src/catch2/catch_tostring.hpp +++ b/src/catch2/catch_tostring.hpp @@ -407,44 +407,38 @@ namespace Catch { // Separate std::tuple specialization #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) -#include +# include +# include namespace Catch { namespace Detail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct TupleElementPrinter { - static void print(const Tuple& tuple, std::ostream& os) { - os << (N ? ", " : " ") - << ::Catch::Detail::stringify(std::get(tuple)); - TupleElementPrinter::print(tuple, os); - } - }; - - template< - typename Tuple, - std::size_t N - > - struct TupleElementPrinter { - static void print(const Tuple&, std::ostream&) {} - }; - - } + template + void PrintTuple( const Tuple& tuple, + std::ostream& os, + std::index_sequence ) { + // 1 + Account for when the tuple is empty + char a[1 + sizeof...( Is )] = { + ( ( os << ( Is ? ", " : " " ) + << ::Catch::Detail::stringify( std::get( tuple ) ) ), + '\0' )... }; + (void)a; + } + } // namespace Detail - template + template struct StringMaker> { - static std::string convert(const std::tuple& tuple) { + static std::string convert( const std::tuple& tuple ) { ReusableStringStream rss; rss << '{'; - Detail::TupleElementPrinter>::print(tuple, rss.get()); + Detail::PrintTuple( + tuple, + rss.get(), + std::make_index_sequence{} ); rss << " }"; return rss.str(); } }; -} +} // namespace Catch #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)