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