00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "gtest/gtest-printers.h"
00046 #include <ctype.h>
00047 #include <stdio.h>
00048 #include <cwchar>
00049 #include <ostream>
00050 #include <string>
00051 #include "gtest/internal/gtest-port.h"
00052
00053 namespace testing {
00054
00055 namespace {
00056
00057 using ::std::ostream;
00058
00059
00060 GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
00061 GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
00062 GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
00063 void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
00064 size_t count, ostream* os) {
00065 char text[5] = "";
00066 for (size_t i = 0; i != count; i++) {
00067 const size_t j = start + i;
00068 if (i != 0) {
00069
00070
00071 if ((j % 2) == 0)
00072 *os << ' ';
00073 else
00074 *os << '-';
00075 }
00076 GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
00077 *os << text;
00078 }
00079 }
00080
00081
00082 void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
00083 ostream* os) {
00084
00085 *os << count << "-byte object <";
00086
00087 const size_t kThreshold = 132;
00088 const size_t kChunkSize = 64;
00089
00090
00091
00092
00093 if (count < kThreshold) {
00094 PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
00095 } else {
00096 PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
00097 *os << " ... ";
00098
00099 const size_t resume_pos = (count - kChunkSize + 1)/2*2;
00100 PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
00101 }
00102 *os << ">";
00103 }
00104
00105 }
00106
00107 namespace internal2 {
00108
00109
00110
00111
00112
00113
00114 void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
00115 ostream* os) {
00116 PrintBytesInObjectToImpl(obj_bytes, count, os);
00117 }
00118
00119 }
00120
00121 namespace internal {
00122
00123
00124
00125
00126
00127
00128 enum CharFormat {
00129 kAsIs,
00130 kHexEscape,
00131 kSpecialEscape
00132 };
00133
00134
00135
00136
00137 inline bool IsPrintableAscii(wchar_t c) {
00138 return 0x20 <= c && c <= 0x7E;
00139 }
00140
00141
00142
00143
00144
00145 template <typename UnsignedChar, typename Char>
00146 static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
00147 switch (static_cast<wchar_t>(c)) {
00148 case L'\0':
00149 *os << "\\0";
00150 break;
00151 case L'\'':
00152 *os << "\\'";
00153 break;
00154 case L'\\':
00155 *os << "\\\\";
00156 break;
00157 case L'\a':
00158 *os << "\\a";
00159 break;
00160 case L'\b':
00161 *os << "\\b";
00162 break;
00163 case L'\f':
00164 *os << "\\f";
00165 break;
00166 case L'\n':
00167 *os << "\\n";
00168 break;
00169 case L'\r':
00170 *os << "\\r";
00171 break;
00172 case L'\t':
00173 *os << "\\t";
00174 break;
00175 case L'\v':
00176 *os << "\\v";
00177 break;
00178 default:
00179 if (IsPrintableAscii(c)) {
00180 *os << static_cast<char>(c);
00181 return kAsIs;
00182 } else {
00183 *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
00184 return kHexEscape;
00185 }
00186 }
00187 return kSpecialEscape;
00188 }
00189
00190
00191
00192 static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
00193 switch (c) {
00194 case L'\'':
00195 *os << "'";
00196 return kAsIs;
00197 case L'"':
00198 *os << "\\\"";
00199 return kSpecialEscape;
00200 default:
00201 return PrintAsCharLiteralTo<wchar_t>(c, os);
00202 }
00203 }
00204
00205
00206
00207 static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
00208 return PrintAsStringLiteralTo(
00209 static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
00210 }
00211
00212
00213
00214
00215
00216 template <typename UnsignedChar, typename Char>
00217 void PrintCharAndCodeTo(Char c, ostream* os) {
00218
00219 *os << ((sizeof(c) > 1) ? "L'" : "'");
00220 const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
00221 *os << "'";
00222
00223
00224
00225
00226 if (c == 0)
00227 return;
00228 *os << " (" << static_cast<int>(c);
00229
00230
00231
00232
00233 if (format == kHexEscape || (1 <= c && c <= 9)) {
00234
00235 } else {
00236 *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
00237 }
00238 *os << ")";
00239 }
00240
00241 void PrintTo(unsigned char c, ::std::ostream* os) {
00242 PrintCharAndCodeTo<unsigned char>(c, os);
00243 }
00244 void PrintTo(signed char c, ::std::ostream* os) {
00245 PrintCharAndCodeTo<unsigned char>(c, os);
00246 }
00247
00248
00249
00250 void PrintTo(wchar_t wc, ostream* os) {
00251 PrintCharAndCodeTo<wchar_t>(wc, os);
00252 }
00253
00254
00255
00256
00257
00258 template <typename CharType>
00259 GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
00260 GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
00261 GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
00262 static void PrintCharsAsStringTo(
00263 const CharType* begin, size_t len, ostream* os) {
00264 const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
00265 *os << kQuoteBegin;
00266 bool is_previous_hex = false;
00267 for (size_t index = 0; index < len; ++index) {
00268 const CharType cur = begin[index];
00269 if (is_previous_hex && IsXDigit(cur)) {
00270
00271
00272
00273 *os << "\" " << kQuoteBegin;
00274 }
00275 is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
00276 }
00277 *os << "\"";
00278 }
00279
00280
00281
00282 template <typename CharType>
00283 GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
00284 GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
00285 GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
00286 static void UniversalPrintCharArray(
00287 const CharType* begin, size_t len, ostream* os) {
00288
00289
00290
00291
00292
00293
00294
00295 if (len > 0 && begin[len - 1] == '\0') {
00296 PrintCharsAsStringTo(begin, len - 1, os);
00297 return;
00298 }
00299
00300
00301
00302
00303
00304 PrintCharsAsStringTo(begin, len, os);
00305 *os << " (no terminating NUL)";
00306 }
00307
00308
00309 void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
00310 UniversalPrintCharArray(begin, len, os);
00311 }
00312
00313
00314
00315 void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
00316 UniversalPrintCharArray(begin, len, os);
00317 }
00318
00319
00320 void PrintTo(const char* s, ostream* os) {
00321 if (s == NULL) {
00322 *os << "NULL";
00323 } else {
00324 *os << ImplicitCast_<const void*>(s) << " pointing to ";
00325 PrintCharsAsStringTo(s, strlen(s), os);
00326 }
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
00336
00337 void PrintTo(const wchar_t* s, ostream* os) {
00338 if (s == NULL) {
00339 *os << "NULL";
00340 } else {
00341 *os << ImplicitCast_<const void*>(s) << " pointing to ";
00342 PrintCharsAsStringTo(s, std::wcslen(s), os);
00343 }
00344 }
00345 #endif // wchar_t is native
00346
00347
00348 #if GTEST_HAS_GLOBAL_STRING
00349 void PrintStringTo(const ::string& s, ostream* os) {
00350 PrintCharsAsStringTo(s.data(), s.size(), os);
00351 }
00352 #endif // GTEST_HAS_GLOBAL_STRING
00353
00354 void PrintStringTo(const ::std::string& s, ostream* os) {
00355 PrintCharsAsStringTo(s.data(), s.size(), os);
00356 }
00357
00358
00359 #if GTEST_HAS_GLOBAL_WSTRING
00360 void PrintWideStringTo(const ::wstring& s, ostream* os) {
00361 PrintCharsAsStringTo(s.data(), s.size(), os);
00362 }
00363 #endif // GTEST_HAS_GLOBAL_WSTRING
00364
00365 #if GTEST_HAS_STD_WSTRING
00366 void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
00367 PrintCharsAsStringTo(s.data(), s.size(), os);
00368 }
00369 #endif // GTEST_HAS_STD_WSTRING
00370
00371 }
00372
00373 }