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