1 /*
2  *  Created by Phil on 23/4/2014.
3  *  Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #ifndef TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
9 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
10 
11 #include "catch_tostring.h"
12 #include "catch_interfaces_config.h"
13 
14 namespace Catch {
15 
16 namespace Detail {
17 
18     const std::string unprintableString = "{?}";
19 
20     namespace {
21         const int hexThreshold = 255;
22 
23         struct Endianness {
24             enum Arch { Big, Little };
25 
whichCatch::Detail::__anona54083a30111::Endianness26             static Arch which() {
27                 union _{
28                     int asInt;
29                     char asChar[sizeof (int)];
30                 } u;
31 
32                 u.asInt = 1;
33                 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
34             }
35         };
36     }
37 
rawMemoryToString(const void * object,std::size_t size)38     std::string rawMemoryToString( const void *object, std::size_t size )
39     {
40         // Reverse order for little endian architectures
41         int i = 0, end = static_cast<int>( size ), inc = 1;
42         if( Endianness::which() == Endianness::Little ) {
43             i = end-1;
44             end = inc = -1;
45         }
46 
47         unsigned char const *bytes = static_cast<unsigned char const *>(object);
48         std::ostringstream os;
49         os << "0x" << std::setfill('0') << std::hex;
50         for( ; i != end; i += inc )
51              os << std::setw(2) << static_cast<unsigned>(bytes[i]);
52        return os.str();
53     }
54 }
55 
toString(std::string const & value)56 std::string toString( std::string const& value ) {
57     std::string s = value;
58     if( getCurrentContext().getConfig()->showInvisibles() ) {
59         for(size_t i = 0; i < s.size(); ++i ) {
60             std::string subs;
61             switch( s[i] ) {
62             case '\n': subs = "\\n"; break;
63             case '\t': subs = "\\t"; break;
64             default: break;
65             }
66             if( !subs.empty() ) {
67                 s = s.substr( 0, i ) + subs + s.substr( i+1 );
68                 ++i;
69             }
70         }
71     }
72     return '"' + s + '"';
73 }
toString(std::wstring const & value)74 std::string toString( std::wstring const& value ) {
75 
76     std::string s;
77     s.reserve( value.size() );
78     for(size_t i = 0; i < value.size(); ++i )
79         s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
80     return Catch::toString( s );
81 }
82 
toString(const char * const value)83 std::string toString( const char* const value ) {
84     return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
85 }
86 
toString(char * const value)87 std::string toString( char* const value ) {
88     return Catch::toString( static_cast<const char*>( value ) );
89 }
90 
toString(const wchar_t * const value)91 std::string toString( const wchar_t* const value )
92 {
93     return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
94 }
95 
toString(wchar_t * const value)96 std::string toString( wchar_t* const value )
97 {
98     return Catch::toString( static_cast<const wchar_t*>( value ) );
99 }
100 
toString(int value)101 std::string toString( int value ) {
102     std::ostringstream oss;
103     oss << value;
104     if( value > Detail::hexThreshold )
105         oss << " (0x" << std::hex << value << ')';
106     return oss.str();
107 }
108 
toString(unsigned long value)109 std::string toString( unsigned long value ) {
110     std::ostringstream oss;
111     oss << value;
112     if( value > Detail::hexThreshold )
113         oss << " (0x" << std::hex << value << ')';
114     return oss.str();
115 }
116 
toString(unsigned int value)117 std::string toString( unsigned int value ) {
118     return Catch::toString( static_cast<unsigned long>( value ) );
119 }
120 
121 template<typename T>
fpToString(T value,int precision)122 std::string fpToString( T value, int precision ) {
123     std::ostringstream oss;
124     oss << std::setprecision( precision )
125         << std::fixed
126         << value;
127     std::string d = oss.str();
128     std::size_t i = d.find_last_not_of( '0' );
129     if( i != std::string::npos && i != d.size()-1 ) {
130         if( d[i] == '.' )
131             i++;
132         d = d.substr( 0, i+1 );
133     }
134     return d;
135 }
136 
toString(const double value)137 std::string toString( const double value ) {
138     return fpToString( value, 10 );
139 }
toString(const float value)140 std::string toString( const float value ) {
141     return fpToString( value, 5 ) + 'f';
142 }
143 
toString(bool value)144 std::string toString( bool value ) {
145     return value ? "true" : "false";
146 }
147 
toString(char value)148 std::string toString( char value ) {
149     if ( value == '\r' )
150         return "'\\r'";
151     if ( value == '\f' )
152         return "'\\f'";
153     if ( value == '\n' )
154         return "'\\n'";
155     if ( value == '\t' )
156         return "'\\t'";
157     if ( '\0' <= value && value < ' ' )
158         return toString( static_cast<unsigned int>( value ) );
159     char chstr[] = "' '";
160     chstr[1] = value;
161     return chstr;
162 }
163 
toString(signed char value)164 std::string toString( signed char value ) {
165     return toString( static_cast<char>( value ) );
166 }
167 
toString(unsigned char value)168 std::string toString( unsigned char value ) {
169     return toString( static_cast<char>( value ) );
170 }
171 
172 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
toString(long long value)173 std::string toString( long long value ) {
174     std::ostringstream oss;
175     oss << value;
176     if( value > Detail::hexThreshold )
177         oss << " (0x" << std::hex << value << ')';
178     return oss.str();
179 }
toString(unsigned long long value)180 std::string toString( unsigned long long value ) {
181     std::ostringstream oss;
182     oss << value;
183     if( value > Detail::hexThreshold )
184         oss << " (0x" << std::hex << value << ')';
185     return oss.str();
186 }
187 #endif
188 
189 #ifdef CATCH_CONFIG_CPP11_NULLPTR
toString(std::nullptr_t)190 std::string toString( std::nullptr_t ) {
191     return "nullptr";
192 }
193 #endif
194 
195 #ifdef __OBJC__
toString(NSString const * const & nsstring)196     std::string toString( NSString const * const& nsstring ) {
197         if( !nsstring )
198             return "nil";
199         return "@" + toString([nsstring UTF8String]);
200     }
toString(NSString * CATCH_ARC_STRONG & nsstring)201     std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) {
202         if( !nsstring )
203             return "nil";
204         return "@" + toString([nsstring UTF8String]);
205     }
toString(NSObject * const & nsObject)206     std::string toString( NSObject* const& nsObject ) {
207         return toString( [nsObject description] );
208     }
209 #endif
210 
211 } // end namespace Catch
212 
213 #endif // TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
214