mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Introduced ReusableStringStream and removed all uses of std::ostringstream from the main path
ReusableStringStream holds a std::ostringstream internally, but only exposes the ostream interface. It caches a pool of ostringstreams in a vector which is currently global, but will be made thread-local. Altogether this should enable both runtime and compile-time benefits. although more work is needed to realise the compile time opportunities.
This commit is contained in:
		| @@ -36,9 +36,9 @@ namespace Detail { | ||||
|     } | ||||
|  | ||||
|     std::string Approx::toString() const { | ||||
|         std::ostringstream oss; | ||||
|         oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; | ||||
|         return oss.str(); | ||||
|         ReusableStringStream rss; | ||||
|         rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; | ||||
|         return rss.str(); | ||||
|     } | ||||
|  | ||||
|     bool Approx::equalityComparisonImpl(const double other) const { | ||||
|   | ||||
| @@ -8,10 +8,10 @@ | ||||
| #ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_enforce.h" | ||||
| #include "catch_tostring.h" | ||||
|  | ||||
| #include <type_traits> | ||||
| #include <stdexcept> | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Detail { | ||||
| @@ -83,9 +83,12 @@ namespace Detail { | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         Approx& epsilon( T const& newEpsilon ) { | ||||
|             double epsilonAsDouble = static_cast<double>(newEpsilon); | ||||
|             CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0, | ||||
|                           "Invalid Approx::epsilon: " << epsilonAsDouble | ||||
|                           << ", Approx::epsilon has to be between 0 and 1"); | ||||
|             if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) { | ||||
|                 throw std::domain_error | ||||
|                     (   "Invalid Approx::epsilon: " + | ||||
|                         Catch::Detail::stringify( epsilonAsDouble ) + | ||||
|                         ", Approx::epsilon has to be between 0 and 1" ); | ||||
|             } | ||||
|             m_epsilon = epsilonAsDouble; | ||||
|             return *this; | ||||
|         } | ||||
| @@ -93,9 +96,13 @@ namespace Detail { | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         Approx& margin( T const& newMargin ) { | ||||
|             double marginAsDouble = static_cast<double>(newMargin); | ||||
|             CATCH_ENFORCE(marginAsDouble >= 0, | ||||
|                           "Invalid Approx::margin: " << marginAsDouble | ||||
|                           << ", Approx::Margin has to be non-negative."); | ||||
|             if( marginAsDouble < 0 ) { | ||||
|                 throw std::domain_error | ||||
|                     (   "Invalid Approx::margin: " + | ||||
|                          Catch::Detail::stringify( marginAsDouble ) + | ||||
|                          ", Approx::Margin has to be non-negative." ); | ||||
|  | ||||
|             } | ||||
|             m_margin = marginAsDouble; | ||||
|             return *this; | ||||
|         } | ||||
|   | ||||
| @@ -17,10 +17,9 @@ namespace Catch { | ||||
|  | ||||
|         if( reconstructedExpression.empty() ) { | ||||
|             if( lazyExpression ) { | ||||
|                 // !TBD Use stringstream for now, but rework above to pass stream in | ||||
|                 std::ostringstream oss; | ||||
|                 oss << lazyExpression; | ||||
|                 reconstructedExpression = oss.str(); | ||||
|                 ReusableStringStream rss; | ||||
|                 rss << lazyExpression; | ||||
|                 reconstructedExpression = rss.str(); | ||||
|             } | ||||
|         } | ||||
|         return reconstructedExpression; | ||||
|   | ||||
| @@ -23,6 +23,8 @@ | ||||
| #include "catch_debugger.h" | ||||
| #include "catch_windows_h_proxy.h" | ||||
|  | ||||
| #include <sstream> | ||||
|  | ||||
| namespace Catch { | ||||
|     namespace { | ||||
|  | ||||
|   | ||||
| @@ -8,12 +8,13 @@ | ||||
| #define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED | ||||
|  | ||||
| #include "catch_common.h" | ||||
| #include "catch_stream.h" | ||||
|  | ||||
| #include <sstream> | ||||
| #include <stdexcept> | ||||
| #include <iosfwd> | ||||
|  | ||||
| #define CATCH_PREPARE_EXCEPTION( type, msg ) \ | ||||
|     type( static_cast<std::ostringstream&&>( std::ostringstream() << msg ).str() ) | ||||
|     type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() ) | ||||
| #define CATCH_INTERNAL_ERROR( msg ) \ | ||||
|     throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); | ||||
| #define CATCH_ERROR( msg ) \ | ||||
|   | ||||
| @@ -115,13 +115,14 @@ namespace Catch { | ||||
|         } | ||||
|  | ||||
|         for( auto const& tagCount : tagCounts ) { | ||||
|             std::ostringstream oss; | ||||
|             oss << "  " << std::setw(2) << tagCount.second.count << "  "; | ||||
|             ReusableStringStream rss; | ||||
|             rss << "  " << std::setw(2) << tagCount.second.count << "  "; | ||||
|             auto str = rss.str(); | ||||
|             auto wrapper = Column( tagCount.second.all() ) | ||||
|                                                     .initialIndent( 0 ) | ||||
|                                                     .indent( oss.str().size() ) | ||||
|                                                     .indent( str.size() ) | ||||
|                                                     .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); | ||||
|             Catch::cout() << oss.str() << wrapper << '\n'; | ||||
|             Catch::cout() << str << wrapper << '\n'; | ||||
|         } | ||||
|         Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; | ||||
|         return tagCounts.size(); | ||||
|   | ||||
| @@ -9,9 +9,9 @@ | ||||
| #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED | ||||
|  | ||||
| #include <string> | ||||
| #include <sstream> | ||||
| #include "catch_result_type.h" | ||||
| #include "catch_common.h" | ||||
| #include "catch_stream.h" | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| @@ -40,8 +40,7 @@ namespace Catch { | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         // !TBD reuse a global/ thread-local stream | ||||
|         std::ostringstream m_stream; | ||||
|         ReusableStringStream m_stream; | ||||
|     }; | ||||
|  | ||||
|     struct MessageBuilder : MessageStream { | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|  | ||||
| #include <cassert> | ||||
| #include <algorithm> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| @@ -13,7 +14,7 @@ namespace Catch { | ||||
|         : m_stream(stream), | ||||
|         m_prevBuf(stream.rdbuf()), | ||||
|         m_targetString(targetString) { | ||||
|         stream.rdbuf(m_oss.rdbuf()); | ||||
|         stream.rdbuf(m_oss.get().rdbuf()); | ||||
|     } | ||||
|  | ||||
|     StreamRedirect::~StreamRedirect() { | ||||
| @@ -24,8 +25,8 @@ namespace Catch { | ||||
|     StdErrRedirect::StdErrRedirect(std::string & targetString) | ||||
|         :m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()), | ||||
|         m_targetString(targetString) { | ||||
|         cerr().rdbuf(m_oss.rdbuf()); | ||||
|         clog().rdbuf(m_oss.rdbuf()); | ||||
|         cerr().rdbuf(m_oss.get().rdbuf()); | ||||
|         clog().rdbuf(m_oss.get().rdbuf()); | ||||
|     } | ||||
|  | ||||
|     StdErrRedirect::~StdErrRedirect() { | ||||
|   | ||||
| @@ -32,13 +32,12 @@ namespace Catch { | ||||
|  | ||||
|     public: | ||||
|         StreamRedirect(std::ostream& stream, std::string& targetString); | ||||
|  | ||||
|         ~StreamRedirect(); | ||||
|  | ||||
|     private: | ||||
|         std::ostream& m_stream; | ||||
|         std::streambuf* m_prevBuf; | ||||
|         std::ostringstream m_oss; | ||||
|         ReusableStringStream m_oss; | ||||
|         std::string& m_targetString; | ||||
|     }; | ||||
|  | ||||
| @@ -52,7 +51,7 @@ namespace Catch { | ||||
|     private: | ||||
|         std::streambuf* m_cerrBuf; | ||||
|         std::streambuf* m_clogBuf; | ||||
|         std::ostringstream m_oss; | ||||
|         ReusableStringStream m_oss; | ||||
|         std::string& m_targetString; | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -13,10 +13,16 @@ | ||||
| #include "catch_debug_console.h" | ||||
| #include "catch_stringref.h" | ||||
|  | ||||
| #include <stdexcept> | ||||
| #include <cstdio> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| #if defined(__clang__) | ||||
| #    pragma clang diagnostic push | ||||
| #    pragma clang diagnostic ignored "-Wexit-time-destructors" | ||||
| #endif | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| @@ -132,18 +138,64 @@ namespace Catch { | ||||
|             return new detail::FileStream( filename ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // This class encapsulates the idea of a pool of ostringstreams that can be reused. | ||||
|     struct StringStreams { | ||||
|         std::vector<std::unique_ptr<std::ostringstream>> m_streams; | ||||
|         std::vector<std::size_t> m_unused; | ||||
|         std::ostringstream m_referenceStream; // Used for copy state/ flags from | ||||
|  | ||||
|         auto add() -> std::size_t { | ||||
|             if( m_unused.empty() ) { | ||||
|                 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) ); | ||||
|                 return m_streams.size()-1; | ||||
|             } | ||||
|             else { | ||||
|                 auto index = m_unused.back(); | ||||
|                 m_unused.pop_back(); | ||||
|                 return index; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         void release( std::size_t index ) { | ||||
|             m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state | ||||
|             m_unused.push_back(index); | ||||
|         } | ||||
|  | ||||
|         // !TBD: put in TLS | ||||
|         static auto instance() -> StringStreams& { | ||||
|             static StringStreams s_stringStreams; | ||||
|             return s_stringStreams; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     ReusableStringStream::ReusableStringStream() | ||||
|     :   m_index( StringStreams::instance().add() ), | ||||
|         m_oss( StringStreams::instance().m_streams[m_index].get() ) | ||||
|     {} | ||||
|  | ||||
|     ReusableStringStream::~ReusableStringStream() { | ||||
|         static_cast<std::ostringstream*>( m_oss )->str(""); | ||||
|         m_oss->clear(); | ||||
|         StringStreams::instance().release( m_index ); | ||||
|     } | ||||
|  | ||||
|     auto ReusableStringStream::str() const -> std::string { | ||||
|         return static_cast<std::ostringstream*>( m_oss )->str(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|  | ||||
| #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions | ||||
|     std::ostream& cout() { | ||||
|         return std::cout; | ||||
|     } | ||||
|     std::ostream& cerr() { | ||||
|         return std::cerr; | ||||
|     } | ||||
|     std::ostream& clog() { | ||||
|         return std::clog; | ||||
|     } | ||||
|     std::ostream& cout() { return std::cout; } | ||||
|     std::ostream& cerr() { return std::cerr; } | ||||
|     std::ostream& clog() { return std::clog; } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #if defined(__clang__) | ||||
| #    pragma clang diagnostic pop | ||||
| #endif | ||||
|   | ||||
| @@ -10,6 +10,8 @@ | ||||
| #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED | ||||
|  | ||||
| #include <iosfwd> | ||||
| #include <cstddef> | ||||
| #include <ostream> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| @@ -25,6 +27,23 @@ namespace Catch { | ||||
|     }; | ||||
|  | ||||
|     auto makeStream( StringRef const &filename ) -> IStream const*; | ||||
|  | ||||
|     class ReusableStringStream { | ||||
|         std::size_t m_index; | ||||
|         std::ostream* m_oss; | ||||
|     public: | ||||
|         ReusableStringStream(); | ||||
|         ~ReusableStringStream(); | ||||
|  | ||||
|         auto str() const -> std::string; | ||||
|  | ||||
|         template<typename T> | ||||
|         auto operator << ( T const& value ) -> ReusableStringStream& { | ||||
|             *m_oss << value; | ||||
|             return *this; | ||||
|         } | ||||
|         auto get() -> std::ostream& { return *m_oss; } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED | ||||
|   | ||||
| @@ -10,9 +10,10 @@ | ||||
| #include "catch_console_colour.h" | ||||
| #include "catch_enforce.h" | ||||
| #include "catch_interfaces_registry_hub.h" | ||||
| #include "catch_stream.h" | ||||
| #include "catch_string_manip.h" | ||||
|  | ||||
| #include <sstream> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     TagAliasRegistry::~TagAliasRegistry() {} | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include <cctype> | ||||
| #include <exception> | ||||
| #include <algorithm> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|   | ||||
| @@ -66,9 +66,9 @@ namespace Catch { | ||||
|     void TestRegistry::registerTest( TestCase const& testCase ) { | ||||
|         std::string name = testCase.getTestCaseInfo().name; | ||||
|         if( name.empty() ) { | ||||
|             std::ostringstream oss; | ||||
|             oss << "Anonymous test case " << ++m_unnamedCount; | ||||
|             return registerTest( testCase.withName( oss.str() ) ); | ||||
|             ReusableStringStream rss; | ||||
|             rss << "Anonymous test case " << ++m_unnamedCount; | ||||
|             return registerTest( testCase.withName( rss.str() ) ); | ||||
|         } | ||||
|         m_functions.push_back( testCase ); | ||||
|     } | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include <assert.h> | ||||
| #include <stdexcept> | ||||
| #include <memory> | ||||
| #include <sstream> | ||||
|  | ||||
| #if defined(__clang__) | ||||
| #    pragma clang diagnostic push | ||||
|   | ||||
| @@ -52,22 +52,22 @@ namespace Detail { | ||||
|         } | ||||
|  | ||||
|         unsigned char const *bytes = static_cast<unsigned char const *>(object); | ||||
|         std::ostringstream os; | ||||
|         os << "0x" << std::setfill('0') << std::hex; | ||||
|         ReusableStringStream rss; | ||||
|         rss << "0x" << std::setfill('0') << std::hex; | ||||
|         for( ; i != end; i += inc ) | ||||
|              os << std::setw(2) << static_cast<unsigned>(bytes[i]); | ||||
|        return os.str(); | ||||
|              rss << std::setw(2) << static_cast<unsigned>(bytes[i]); | ||||
|        return rss.str(); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| template<typename T> | ||||
| std::string fpToString( T value, int precision ) { | ||||
|     std::ostringstream oss; | ||||
|     oss << std::setprecision( precision ) | ||||
|     ReusableStringStream rss; | ||||
|     rss << std::setprecision( precision ) | ||||
|         << std::fixed | ||||
|         << value; | ||||
|     std::string d = oss.str(); | ||||
|     std::string d = rss.str(); | ||||
|     std::size_t i = d.find_last_not_of( '0' ); | ||||
|     if( i != std::string::npos && i != d.size()-1 ) { | ||||
|         if( d[i] == '.' ) | ||||
| @@ -153,12 +153,12 @@ std::string StringMaker<long>::convert(long value) { | ||||
|     return ::Catch::Detail::stringify(static_cast<long long>(value)); | ||||
| } | ||||
| std::string StringMaker<long long>::convert(long long value) { | ||||
|     std::ostringstream oss; | ||||
|     oss << value; | ||||
|     ReusableStringStream rss; | ||||
|     rss << value; | ||||
|     if (value > Detail::hexThreshold) { | ||||
|         oss << " (0x" << std::hex << value << ')'; | ||||
|         rss << " (0x" << std::hex << value << ')'; | ||||
|     } | ||||
|     return oss.str(); | ||||
|     return rss.str(); | ||||
| } | ||||
|  | ||||
| std::string StringMaker<unsigned int>::convert(unsigned int value) { | ||||
| @@ -168,12 +168,12 @@ std::string StringMaker<unsigned long>::convert(unsigned long value) { | ||||
|     return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); | ||||
| } | ||||
| std::string StringMaker<unsigned long long>::convert(unsigned long long value) { | ||||
|     std::ostringstream oss; | ||||
|     oss << value; | ||||
|     ReusableStringStream rss; | ||||
|     rss << value; | ||||
|     if (value > Detail::hexThreshold) { | ||||
|         oss << " (0x" << std::hex << value << ')'; | ||||
|         rss << " (0x" << std::hex << value << ')'; | ||||
|     } | ||||
|     return oss.str(); | ||||
|     return rss.str(); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -9,11 +9,11 @@ | ||||
| #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED | ||||
|  | ||||
|  | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
| #include <cstddef> | ||||
| #include <type_traits> | ||||
| #include <string> | ||||
| #include "catch_stream.h" | ||||
|  | ||||
| #ifdef __OBJC__ | ||||
| #include "catch_objc_arc.hpp" | ||||
| @@ -66,9 +66,9 @@ namespace Catch { | ||||
|         static | ||||
|         typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type | ||||
|             convert(const Fake& t) { | ||||
|                 std::ostringstream sstr; | ||||
|                 sstr << t; | ||||
|                 return sstr.str(); | ||||
|                 ReusableStringStream rss; | ||||
|                 rss << t; | ||||
|                 return rss.str(); | ||||
|         } | ||||
|  | ||||
|         template <typename Fake = T> | ||||
| @@ -221,15 +221,15 @@ namespace Catch { | ||||
|     namespace Detail { | ||||
|         template<typename InputIterator> | ||||
|         std::string rangeToString(InputIterator first, InputIterator last) { | ||||
|             std::ostringstream oss; | ||||
|             oss << "{ "; | ||||
|             ReusableStringStream rss; | ||||
|             rss << "{ "; | ||||
|             if (first != last) { | ||||
|                 oss << ::Catch::Detail::stringify(*first); | ||||
|                 rss << ::Catch::Detail::stringify(*first); | ||||
|                 for (++first; first != last; ++first) | ||||
|                     oss << ", " << ::Catch::Detail::stringify(*first); | ||||
|                     rss << ", " << ::Catch::Detail::stringify(*first); | ||||
|             } | ||||
|             oss << " }"; | ||||
|             return oss.str(); | ||||
|             rss << " }"; | ||||
|             return rss.str(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -290,13 +290,13 @@ namespace Catch { | ||||
|     template<typename T1, typename T2> | ||||
|     struct StringMaker<std::pair<T1, T2> > { | ||||
|         static std::string convert(const std::pair<T1, T2>& pair) { | ||||
|             std::ostringstream oss; | ||||
|             oss << "{ " | ||||
|             ReusableStringStream rss; | ||||
|             rss << "{ " | ||||
|                 << ::Catch::Detail::stringify(pair.first) | ||||
|                 << ", " | ||||
|                 << ::Catch::Detail::stringify(pair.second) | ||||
|                 << " }"; | ||||
|             return oss.str(); | ||||
|             return rss.str(); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| @@ -334,11 +334,11 @@ namespace Catch { | ||||
|     template<typename ...Types> | ||||
|     struct StringMaker<std::tuple<Types...>> { | ||||
|         static std::string convert(const std::tuple<Types...>& tuple) { | ||||
|             std::ostringstream os; | ||||
|             os << '{'; | ||||
|             Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, os); | ||||
|             os << " }"; | ||||
|             return os.str(); | ||||
|             ReusableStringStream rss; | ||||
|             rss << '{'; | ||||
|             Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); | ||||
|             rss << " }"; | ||||
|             return rss.str(); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| @@ -358,10 +358,10 @@ struct ratio_string { | ||||
|  | ||||
| template <class Ratio> | ||||
| std::string ratio_string<Ratio>::symbol() { | ||||
|     std::ostringstream oss; | ||||
|     oss << '[' << Ratio::num << '/' | ||||
|     Catch::ReusableStringStream rss; | ||||
|     rss << '[' << Ratio::num << '/' | ||||
|         << Ratio::den << ']'; | ||||
|     return oss.str(); | ||||
|     return rss.str(); | ||||
| } | ||||
| template <> | ||||
| struct ratio_string<std::atto> { | ||||
| @@ -394,33 +394,33 @@ namespace Catch { | ||||
|     template<typename Value, typename Ratio> | ||||
|     struct StringMaker<std::chrono::duration<Value, Ratio>> { | ||||
|         static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { | ||||
|             std::ostringstream oss; | ||||
|             oss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; | ||||
|             return oss.str(); | ||||
|             ReusableStringStream rss; | ||||
|             rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; | ||||
|             return rss.str(); | ||||
|         } | ||||
|     }; | ||||
|     template<typename Value> | ||||
|     struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { | ||||
|         static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { | ||||
|             std::ostringstream oss; | ||||
|             oss << duration.count() << " s"; | ||||
|             return oss.str(); | ||||
|             ReusableStringStream rss; | ||||
|             rss << duration.count() << " s"; | ||||
|             return rss.str(); | ||||
|         } | ||||
|     }; | ||||
|     template<typename Value> | ||||
|     struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { | ||||
|         static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { | ||||
|             std::ostringstream oss; | ||||
|             oss << duration.count() << " m"; | ||||
|             return oss.str(); | ||||
|             ReusableStringStream rss; | ||||
|             rss << duration.count() << " m"; | ||||
|             return rss.str(); | ||||
|         } | ||||
|     }; | ||||
|     template<typename Value> | ||||
|     struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { | ||||
|         static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { | ||||
|             std::ostringstream oss; | ||||
|             oss << duration.count() << " h"; | ||||
|             return oss.str(); | ||||
|             ReusableStringStream rss; | ||||
|             rss << duration.count() << " h"; | ||||
|             return rss.str(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include "catch_enforce.h" | ||||
| #include "catch_string_manip.h" | ||||
|  | ||||
| #include <sstream> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,6 @@ | ||||
| #include "catch_stream.h" | ||||
| #include "catch_compiler_capabilities.h" | ||||
|  | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch { | ||||
| @@ -73,10 +72,9 @@ namespace Catch { | ||||
|  | ||||
|         template<typename T> | ||||
|         XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { | ||||
|             m_oss.clear(); | ||||
|             m_oss.str(std::string()); | ||||
|             m_oss << attribute; | ||||
|             return writeAttribute( name, m_oss.str() ); | ||||
|             ReusableStringStream rss; | ||||
|             rss << attribute; | ||||
|             return writeAttribute( name, rss.str() ); | ||||
|         } | ||||
|  | ||||
|         XmlWriter& writeText( std::string const& text, bool indent = true ); | ||||
| @@ -100,7 +98,6 @@ namespace Catch { | ||||
|         std::vector<std::string> m_tags; | ||||
|         std::string m_indent; | ||||
|         std::ostream& m_os; | ||||
|         std::ostringstream m_oss; | ||||
|     }; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -8,16 +8,15 @@ | ||||
| #ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED | ||||
|  | ||||
| #include "../internal/catch_enforce.h" | ||||
| #include "../internal/catch_interfaces_reporter.h" | ||||
|  | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <cstring> | ||||
| #include <cfloat> | ||||
| #include <cstdio> | ||||
| #include <assert.h> | ||||
| #include <memory> | ||||
| #include <ostream> | ||||
|  | ||||
| namespace Catch { | ||||
|     void prepareExpandedExpression(AssertionResult& result); | ||||
| @@ -33,7 +32,8 @@ namespace Catch { | ||||
|             stream( _config.stream() ) | ||||
|         { | ||||
|             m_reporterPrefs.shouldRedirectStdOut = false; | ||||
|             CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); | ||||
|             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) | ||||
|                 throw std::domain_error( "Verbosity level not supported by this reporter" ); | ||||
|         } | ||||
|  | ||||
|         ReporterPreferences getPreferences() const override { | ||||
| @@ -147,7 +147,8 @@ namespace Catch { | ||||
|             stream( _config.stream() ) | ||||
|         { | ||||
|             m_reporterPrefs.shouldRedirectStdOut = false; | ||||
|             CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); | ||||
|             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) | ||||
|                 throw std::domain_error( "Verbosity level not supported by this reporter" ); | ||||
|         } | ||||
|         ~CumulativeReporterBase() override = default; | ||||
|  | ||||
|   | ||||
| @@ -543,9 +543,9 @@ namespace Catch { | ||||
|                 colour( _colour ) | ||||
|             {} | ||||
|             SummaryColumn addRow( std::size_t count ) { | ||||
|                 std::ostringstream oss; | ||||
|                 oss << count; | ||||
|                 std::string row = oss.str(); | ||||
|                 ReusableStringStream rss; | ||||
|                 rss << count; | ||||
|                 std::string row = rss.str(); | ||||
|                 for( auto& oldRow : rows ) { | ||||
|                     while( oldRow.size() < row.size() ) | ||||
|                         oldRow = ' ' + oldRow; | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
| #include "../internal/catch_timer.h" | ||||
|  | ||||
| #include <assert.h> | ||||
|  | ||||
| #include <sstream> | ||||
| #include <ctime> | ||||
| #include <algorithm> | ||||
|  | ||||
| @@ -230,15 +230,15 @@ namespace Catch { | ||||
|                 xml.writeAttribute( "message", result.getExpandedExpression() ); | ||||
|                 xml.writeAttribute( "type", result.getTestMacroName() ); | ||||
|  | ||||
|                 std::ostringstream oss; | ||||
|                 ReusableStringStream rss; | ||||
|                 if( !result.getMessage().empty() ) | ||||
|                     oss << result.getMessage() << '\n'; | ||||
|                     rss << result.getMessage() << '\n'; | ||||
|                 for( auto const& msg : stats.infoMessages ) | ||||
|                     if( msg.type == ResultWas::Info ) | ||||
|                         oss << msg.message << '\n'; | ||||
|                         rss << msg.message << '\n'; | ||||
|  | ||||
|                 oss << "at " << result.getSourceInfo(); | ||||
|                 xml.writeText( oss.str(), false ); | ||||
|                 rss << "at " << result.getSourceInfo(); | ||||
|                 xml.writeText( rss.str(), false ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,8 @@ | ||||
| // file can be distributed as a single header that works with the main | ||||
| // Catch single header. | ||||
|  | ||||
| #include "../internal/catch_enforce.h" | ||||
|  | ||||
| #include <cstring> | ||||
|  | ||||
| #ifdef __clang__ | ||||
| @@ -69,9 +71,9 @@ namespace Catch { | ||||
|             AssertionResult const& result = assertionStats.assertionResult; | ||||
|             if( !result.isOk() ) { | ||||
|  | ||||
|                 std::ostringstream msg; | ||||
|                 ReusableStringStream msg; | ||||
|                 if( !m_headerPrintedForThisSection ) | ||||
|                     printSectionHeader( msg ); | ||||
|                     printSectionHeader( msg.get() ); | ||||
|                 m_headerPrintedForThisSection = true; | ||||
|  | ||||
|                 msg << result.getSourceInfo() << "\n"; | ||||
|   | ||||
| @@ -8,6 +8,8 @@ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <sstream> | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wweak-vtables" | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include <iostream> | ||||
| #include <cerrno> | ||||
| #include <limits> | ||||
| #include <sstream> | ||||
|  | ||||
| TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { | ||||
|     int a = 1; | ||||
|   | ||||
| @@ -15,10 +15,11 @@ | ||||
|                                  // that is triggered when compiling as Win32|Release | ||||
| #endif | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace Catch { | ||||
|     std::string toString( const std::pair<int, int>& value ) { | ||||
|         std::ostringstream oss; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash