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
9 #if defined(__clang__)
10 # pragma clang diagnostic push
11 # pragma clang diagnostic ignored "-Wexit-time-destructors"
12 # pragma clang diagnostic ignored "-Wglobal-constructors"
13 #endif
14
15 // Enable specific decls locally
16 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
17 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
18 #endif
19
20 #include "catch_tostring.h"
21 #include "catch_interfaces_config.h"
22 #include "catch_context.h"
23
24 #include <cmath>
25 #include <iomanip>
26
27 namespace Catch {
28
29 namespace Detail {
30
31 const std::string unprintableString = "{?}";
32
33 namespace {
34 const int hexThreshold = 255;
35
36 struct Endianness {
37 enum Arch { Big, Little };
38
whichCatch::Detail::__anon31f3fbfa0111::Endianness39 static Arch which() {
40 union _{
41 int asInt;
42 char asChar[sizeof (int)];
43 } u;
44
45 u.asInt = 1;
46 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
47 }
48 };
49 }
50
rawMemoryToString(const void * object,std::size_t size)51 std::string rawMemoryToString( const void *object, std::size_t size ) {
52 // Reverse order for little endian architectures
53 int i = 0, end = static_cast<int>( size ), inc = 1;
54 if( Endianness::which() == Endianness::Little ) {
55 i = end-1;
56 end = inc = -1;
57 }
58
59 unsigned char const *bytes = static_cast<unsigned char const *>(object);
60 ReusableStringStream rss;
61 rss << "0x" << std::setfill('0') << std::hex;
62 for( ; i != end; i += inc )
63 rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
64 return rss.str();
65 }
66 }
67
68
69 template<typename T>
fpToString(T value,int precision)70 std::string fpToString( T value, int precision ) {
71 if (std::isnan(value)) {
72 return "nan";
73 }
74
75 ReusableStringStream rss;
76 rss << std::setprecision( precision )
77 << std::fixed
78 << value;
79 std::string d = rss.str();
80 std::size_t i = d.find_last_not_of( '0' );
81 if( i != std::string::npos && i != d.size()-1 ) {
82 if( d[i] == '.' )
83 i++;
84 d = d.substr( 0, i+1 );
85 }
86 return d;
87 }
88
89
90 //// ======================================================= ////
91 //
92 // Out-of-line defs for full specialization of StringMaker
93 //
94 //// ======================================================= ////
95
convert(const std::string & str)96 std::string StringMaker<std::string>::convert(const std::string& str) {
97 if (!getCurrentContext().getConfig()->showInvisibles()) {
98 return '"' + str + '"';
99 }
100
101 std::string s("\"");
102 for (char c : str) {
103 switch (c) {
104 case '\n':
105 s.append("\\n");
106 break;
107 case '\t':
108 s.append("\\t");
109 break;
110 default:
111 s.push_back(c);
112 break;
113 }
114 }
115 s.append("\"");
116 return s;
117 }
118
119 #ifdef CATCH_CONFIG_WCHAR
convert(const std::wstring & wstr)120 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
121 std::string s;
122 s.reserve(wstr.size());
123 for (auto c : wstr) {
124 s += (c <= 0xff) ? static_cast<char>(c) : '?';
125 }
126 return ::Catch::Detail::stringify(s);
127 }
128 #endif
129
convert(char const * str)130 std::string StringMaker<char const*>::convert(char const* str) {
131 if (str) {
132 return ::Catch::Detail::stringify(std::string{ str });
133 } else {
134 return{ "{null string}" };
135 }
136 }
convert(char * str)137 std::string StringMaker<char*>::convert(char* str) {
138 if (str) {
139 return ::Catch::Detail::stringify(std::string{ str });
140 } else {
141 return{ "{null string}" };
142 }
143 }
144 #ifdef CATCH_CONFIG_WCHAR
convert(wchar_t const * str)145 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
146 if (str) {
147 return ::Catch::Detail::stringify(std::wstring{ str });
148 } else {
149 return{ "{null string}" };
150 }
151 }
convert(wchar_t * str)152 std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
153 if (str) {
154 return ::Catch::Detail::stringify(std::wstring{ str });
155 } else {
156 return{ "{null string}" };
157 }
158 }
159 #endif
160
161
convert(int value)162 std::string StringMaker<int>::convert(int value) {
163 return ::Catch::Detail::stringify(static_cast<long long>(value));
164 }
convert(long value)165 std::string StringMaker<long>::convert(long value) {
166 return ::Catch::Detail::stringify(static_cast<long long>(value));
167 }
convert(long long value)168 std::string StringMaker<long long>::convert(long long value) {
169 ReusableStringStream rss;
170 rss << value;
171 if (value > Detail::hexThreshold) {
172 rss << " (0x" << std::hex << value << ')';
173 }
174 return rss.str();
175 }
176
convert(unsigned int value)177 std::string StringMaker<unsigned int>::convert(unsigned int value) {
178 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
179 }
convert(unsigned long value)180 std::string StringMaker<unsigned long>::convert(unsigned long value) {
181 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
182 }
convert(unsigned long long value)183 std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
184 ReusableStringStream rss;
185 rss << value;
186 if (value > Detail::hexThreshold) {
187 rss << " (0x" << std::hex << value << ')';
188 }
189 return rss.str();
190 }
191
192
convert(bool b)193 std::string StringMaker<bool>::convert(bool b) {
194 return b ? "true" : "false";
195 }
196
convert(char value)197 std::string StringMaker<char>::convert(char value) {
198 if (value == '\r') {
199 return "'\\r'";
200 } else if (value == '\f') {
201 return "'\\f'";
202 } else if (value == '\n') {
203 return "'\\n'";
204 } else if (value == '\t') {
205 return "'\\t'";
206 } else if ('\0' <= value && value < ' ') {
207 return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
208 } else {
209 char chstr[] = "' '";
210 chstr[1] = value;
211 return chstr;
212 }
213 }
convert(signed char c)214 std::string StringMaker<signed char>::convert(signed char c) {
215 return ::Catch::Detail::stringify(static_cast<char>(c));
216 }
convert(unsigned char c)217 std::string StringMaker<unsigned char>::convert(unsigned char c) {
218 return ::Catch::Detail::stringify(static_cast<char>(c));
219 }
220
convert(std::nullptr_t)221 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) {
222 return "nullptr";
223 }
224
convert(float value)225 std::string StringMaker<float>::convert(float value) {
226 return fpToString(value, 5) + 'f';
227 }
convert(double value)228 std::string StringMaker<double>::convert(double value) {
229 return fpToString(value, 10);
230 }
231
symbol()232 std::string ratio_string<std::atto>::symbol() { return "a"; }
symbol()233 std::string ratio_string<std::femto>::symbol() { return "f"; }
symbol()234 std::string ratio_string<std::pico>::symbol() { return "p"; }
symbol()235 std::string ratio_string<std::nano>::symbol() { return "n"; }
symbol()236 std::string ratio_string<std::micro>::symbol() { return "u"; }
symbol()237 std::string ratio_string<std::milli>::symbol() { return "m"; }
238
239
240 } // end namespace Catch
241
242 #if defined(__clang__)
243 # pragma clang diagnostic pop
244 #endif
245
246