/* * Created by Phil on 8/5/2012. * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED #include #include #include #include #include #include #ifdef __OBJC__ #include "catch_objc_arc.hpp" #endif // We need a dummy global operator<< so we can bring it into Catch namespace later struct Catch_global_namespace_dummy; std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); namespace Catch { // Bring in operator<< from global namespace into Catch namespace using ::operator<<; namespace Detail { extern const std::string unprintableString; std::string rawMemoryToString( const void *object, std::size_t size ); template std::string rawMemoryToString( const T& object ) { return rawMemoryToString( &object, sizeof(object) ); } template class IsStreamInsertable { template static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); template static auto test(...)->std::false_type; public: static const bool value = decltype(test(0))::value; }; } // namespace Detail // If we decide for C++14, change these to enable_if_ts template struct StringMaker { template static typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type convert(const Fake& t) { std::ostringstream sstr; sstr << t; return sstr.str(); } template static typename std::enable_if::value, std::string>::type convert(const Fake&) { return Detail::unprintableString; } }; namespace Detail { // This function dispatches all stringification requests inside of Catch. // Should be preferably called fully qualified, like ::Catch::Detail::stringify template std::string stringify(const T& e) { return ::Catch::StringMaker::type>::type>::convert(e); } } // namespace Detail // Some predefined specializations template<> struct StringMaker { static std::string convert(const std::string& str); }; template<> struct StringMaker { static std::string convert(const std::wstring& wstr); }; template<> struct StringMaker { static std::string convert(char const * str); }; template<> struct StringMaker { static std::string convert(char * str); }; template<> struct StringMaker { static std::string convert(wchar_t const * str); }; template<> struct StringMaker { static std::string convert(wchar_t * str); }; template struct StringMaker { static std::string convert(const char* str) { return ::Catch::Detail::stringify(std::string{ str }); } }; template struct StringMaker { static std::string convert(const char* str) { return ::Catch::Detail::stringify(std::string{ str }); } }; template struct StringMaker { static std::string convert(const char* str) { return ::Catch::Detail::stringify(std::string{ str }); } }; template<> struct StringMaker { static std::string convert(int value); }; template<> struct StringMaker { static std::string convert(long value); }; template<> struct StringMaker { static std::string convert(long long value); }; template<> struct StringMaker { static std::string convert(unsigned int value); }; template<> struct StringMaker { static std::string convert(unsigned long value); }; template<> struct StringMaker { static std::string convert(unsigned long long value); }; template<> struct StringMaker { static std::string convert(bool b); }; template<> struct StringMaker { static std::string convert(char c); }; template<> struct StringMaker { static std::string convert(signed char c); }; template<> struct StringMaker { static std::string convert(unsigned char c); }; template<> struct StringMaker { static std::string convert(std::nullptr_t); }; template<> struct StringMaker { static std::string convert(float value); }; template<> struct StringMaker { static std::string convert(double value); }; template struct StringMaker { template static std::string convert(U* p) { if (p) { return ::Catch::Detail::rawMemoryToString(p); } else { return "nullptr"; } } }; template struct StringMaker { static std::string convert(R C::* p) { if (p) { return ::Catch::Detail::rawMemoryToString(p); } else { return "nullptr"; } } }; namespace Detail { template std::string rangeToString(InputIterator first, InputIterator last) { std::ostringstream oss; oss << "{ "; if (first != last) { oss << ::Catch::Detail::stringify(*first); for (++first; first != last; ++first) oss << ", " << ::Catch::Detail::stringify(*first); } oss << " }"; return oss.str(); } } template struct StringMaker > { static std::string convert( std::vector const& v ) { return ::Catch::Detail::rangeToString( v.begin(), v.end() ); } }; // === Pair === template struct StringMaker > { static std::string convert(const std::pair& pair) { std::ostringstream oss; oss << "{ " << ::Catch::Detail::stringify(pair.first) << ", " << ::Catch::Detail::stringify(pair.second) << " }"; return oss.str(); } }; 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 struct StringMaker> { static std::string convert(const std::tuple& tuple) { std::ostringstream os; os << '{'; Detail::TupleElementPrinter>::print(tuple, os); os << " }"; return os.str(); } }; template struct EnumStringMaker { static std::string convert(const T& t) { return ::Catch::Detail::stringify(static_cast::type>(t)); } }; #ifdef __OBJC__ template<> struct StringMaker { static std::string convert(NSString * nsstring) { if (!nsstring) return "nil"; return std::string("@") + [nsstring UTF8String]; } }; template<> struct StringMaker { static std::string convert(NSObject* nsObject) { return ::Catch::Detail::stringify([nsObject description]); } }; namespace Detail { inline std::string stringify( NSString* nsstring ) { return StringMaker::convert( nsstring ); } } // namespace Detail #endif // __OBJC__ } // namespace Catch #endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED