1 // Copyright 2007, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 // 30 // Author: wan (at) google.com (Zhanyong Wan) 31 32 // Google Test - The Google C++ Testing Framework 33 // 34 // This file implements a universal value printer that can print a 35 // value of any type T: 36 // 37 // void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr); 38 // 39 // It uses the << operator when possible, and prints the bytes in the 40 // object otherwise. A user can override its behavior for a class 41 // type Foo by defining either operator<<(::std::ostream&, const Foo&) 42 // or void PrintTo(const Foo&, ::std::ostream*) in the namespace that 43 // defines Foo. 44 45 #include "gtest/gtest-printers.h" 46 #include <ctype.h> 47 #include <stdio.h> 48 #include <ostream> // NOLINT 49 #include <string> 50 #include "gtest/internal/gtest-port.h" 51 52 namespace testing { 53 54 namespace { 55 56 using ::std::ostream; 57 58 #if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s. 59 # define snprintf _snprintf 60 #elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf. 61 # define snprintf _snprintf_s 62 #elif _MSC_VER 63 # define snprintf _snprintf 64 #endif // GTEST_OS_WINDOWS_MOBILE 65 66 // Prints a segment of bytes in the given object. 67 void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, 68 size_t count, ostream* os) { 69 char text[5] = ""; 70 for (size_t i = 0; i != count; i++) { 71 const size_t j = start + i; 72 if (i != 0) { 73 // Organizes the bytes into groups of 2 for easy parsing by 74 // human. 75 if ((j % 2) == 0) 76 *os << ' '; 77 else 78 *os << '-'; 79 } 80 snprintf(text, sizeof(text), "%02X", obj_bytes[j]); 81 *os << text; 82 } 83 } 84 85 // Prints the bytes in the given value to the given ostream. 86 void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, 87 ostream* os) { 88 // Tells the user how big the object is. 89 *os << count << "-byte object <"; 90 91 const size_t kThreshold = 132; 92 const size_t kChunkSize = 64; 93 // If the object size is bigger than kThreshold, we'll have to omit 94 // some details by printing only the first and the last kChunkSize 95 // bytes. 96 // TODO(wan): let the user control the threshold using a flag. 97 if (count < kThreshold) { 98 PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); 99 } else { 100 PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); 101 *os << " ... "; 102 // Rounds up to 2-byte boundary. 103 const size_t resume_pos = (count - kChunkSize + 1)/2*2; 104 PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); 105 } 106 *os << ">"; 107 } 108 109 } // namespace 110 111 namespace internal2 { 112 113 // Delegates to PrintBytesInObjectToImpl() to print the bytes in the 114 // given object. The delegation simplifies the implementation, which 115 // uses the << operator and thus is easier done outside of the 116 // ::testing::internal namespace, which contains a << operator that 117 // sometimes conflicts with the one in STL. 118 void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, 119 ostream* os) { 120 PrintBytesInObjectToImpl(obj_bytes, count, os); 121 } 122 123 } // namespace internal2 124 125 namespace internal { 126 127 // Depending on the value of a char (or wchar_t), we print it in one 128 // of three formats: 129 // - as is if it's a printable ASCII (e.g. 'a', '2', ' '), 130 // - as a hexadecimal escape sequence (e.g. '\x7F'), or 131 // - as a special escape sequence (e.g. '\r', '\n'). 132 enum CharFormat { 133 kAsIs, 134 kHexEscape, 135 kSpecialEscape 136 }; 137 138 // Returns true if c is a printable ASCII character. We test the 139 // value of c directly instead of calling isprint(), which is buggy on 140 // Windows Mobile. 141 inline bool IsPrintableAscii(wchar_t c) { 142 return 0x20 <= c && c <= 0x7E; 143 } 144 145 // Prints a wide or narrow char c as a character literal without the 146 // quotes, escaping it when necessary; returns how c was formatted. 147 // The template argument UnsignedChar is the unsigned version of Char, 148 // which is the type of c. 149 template <typename UnsignedChar, typename Char> 150 static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { 151 switch (static_cast<wchar_t>(c)) { 152 case L'\0': 153 *os << "\\0"; 154 break; 155 case L'\'': 156 *os << "\\'"; 157 break; 158 case L'\\': 159 *os << "\\\\"; 160 break; 161 case L'\a': 162 *os << "\\a"; 163 break; 164 case L'\b': 165 *os << "\\b"; 166 break; 167 case L'\f': 168 *os << "\\f"; 169 break; 170 case L'\n': 171 *os << "\\n"; 172 break; 173 case L'\r': 174 *os << "\\r"; 175 break; 176 case L'\t': 177 *os << "\\t"; 178 break; 179 case L'\v': 180 *os << "\\v"; 181 break; 182 default: 183 if (IsPrintableAscii(c)) { 184 *os << static_cast<char>(c); 185 return kAsIs; 186 } else { 187 *os << String::Format("\\x%X", static_cast<UnsignedChar>(c)); 188 return kHexEscape; 189 } 190 } 191 return kSpecialEscape; 192 } 193 194 // Prints a char c as if it's part of a string literal, escaping it when 195 // necessary; returns how c was formatted. 196 static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) { 197 switch (c) { 198 case L'\'': 199 *os << "'"; 200 return kAsIs; 201 case L'"': 202 *os << "\\\""; 203 return kSpecialEscape; 204 default: 205 return PrintAsCharLiteralTo<wchar_t>(c, os); 206 } 207 } 208 209 // Prints a char c as if it's part of a string literal, escaping it when 210 // necessary; returns how c was formatted. 211 static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) { 212 return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os); 213 } 214 215 // Prints a wide or narrow character c and its code. '\0' is printed 216 // as "'\\0'", other unprintable characters are also properly escaped 217 // using the standard C++ escape sequence. The template argument 218 // UnsignedChar is the unsigned version of Char, which is the type of c. 219 template <typename UnsignedChar, typename Char> 220 void PrintCharAndCodeTo(Char c, ostream* os) { 221 // First, print c as a literal in the most readable form we can find. 222 *os << ((sizeof(c) > 1) ? "L'" : "'"); 223 const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os); 224 *os << "'"; 225 226 // To aid user debugging, we also print c's code in decimal, unless 227 // it's 0 (in which case c was printed as '\\0', making the code 228 // obvious). 229 if (c == 0) 230 return; 231 *os << " (" << String::Format("%d", c).c_str(); 232 233 // For more convenience, we print c's code again in hexadecimal, 234 // unless c was already printed in the form '\x##' or the code is in 235 // [1, 9]. 236 if (format == kHexEscape || (1 <= c && c <= 9)) { 237 // Do nothing. 238 } else { 239 *os << String::Format(", 0x%X", 240 static_cast<UnsignedChar>(c)).c_str(); 241 } 242 *os << ")"; 243 } 244 245 void PrintTo(unsigned char c, ::std::ostream* os) { 246 PrintCharAndCodeTo<unsigned char>(c, os); 247 } 248 void PrintTo(signed char c, ::std::ostream* os) { 249 PrintCharAndCodeTo<unsigned char>(c, os); 250 } 251 252 // Prints a wchar_t as a symbol if it is printable or as its internal 253 // code otherwise and also as its code. L'\0' is printed as "L'\\0'". 254 void PrintTo(wchar_t wc, ostream* os) { 255 PrintCharAndCodeTo<wchar_t>(wc, os); 256 } 257 258 // Prints the given array of characters to the ostream. 259 // The array starts at *begin, the length is len, it may include '\0' characters 260 // and may not be null-terminated. 261 static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { 262 *os << "\""; 263 bool is_previous_hex = false; 264 for (size_t index = 0; index < len; ++index) { 265 const char cur = begin[index]; 266 if (is_previous_hex && IsXDigit(cur)) { 267 // Previous character is of '\x..' form and this character can be 268 // interpreted as another hexadecimal digit in its number. Break string to 269 // disambiguate. 270 *os << "\" \""; 271 } 272 is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape; 273 } 274 *os << "\""; 275 } 276 277 // Prints a (const) char array of 'len' elements, starting at address 'begin'. 278 void UniversalPrintArray(const char* begin, size_t len, ostream* os) { 279 PrintCharsAsStringTo(begin, len, os); 280 } 281 282 // Prints the given array of wide characters to the ostream. 283 // The array starts at *begin, the length is len, it may include L'\0' 284 // characters and may not be null-terminated. 285 static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len, 286 ostream* os) { 287 *os << "L\""; 288 bool is_previous_hex = false; 289 for (size_t index = 0; index < len; ++index) { 290 const wchar_t cur = begin[index]; 291 if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) { 292 // Previous character is of '\x..' form and this character can be 293 // interpreted as another hexadecimal digit in its number. Break string to 294 // disambiguate. 295 *os << "\" L\""; 296 } 297 is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape; 298 } 299 *os << "\""; 300 } 301 302 // Prints the given C string to the ostream. 303 void PrintTo(const char* s, ostream* os) { 304 if (s == NULL) { 305 *os << "NULL"; 306 } else { 307 *os << ImplicitCast_<const void*>(s) << " pointing to "; 308 PrintCharsAsStringTo(s, strlen(s), os); 309 } 310 } 311 312 // MSVC compiler can be configured to define whar_t as a typedef 313 // of unsigned short. Defining an overload for const wchar_t* in that case 314 // would cause pointers to unsigned shorts be printed as wide strings, 315 // possibly accessing more memory than intended and causing invalid 316 // memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when 317 // wchar_t is implemented as a native type. 318 #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) 319 // Prints the given wide C string to the ostream. 320 void PrintTo(const wchar_t* s, ostream* os) { 321 if (s == NULL) { 322 *os << "NULL"; 323 } else { 324 *os << ImplicitCast_<const void*>(s) << " pointing to "; 325 PrintWideCharsAsStringTo(s, wcslen(s), os); 326 } 327 } 328 #endif // wchar_t is native 329 330 // Prints a ::string object. 331 #if GTEST_HAS_GLOBAL_STRING 332 void PrintStringTo(const ::string& s, ostream* os) { 333 PrintCharsAsStringTo(s.data(), s.size(), os); 334 } 335 #endif // GTEST_HAS_GLOBAL_STRING 336 337 void PrintStringTo(const ::std::string& s, ostream* os) { 338 PrintCharsAsStringTo(s.data(), s.size(), os); 339 } 340 341 // Prints a ::wstring object. 342 #if GTEST_HAS_GLOBAL_WSTRING 343 void PrintWideStringTo(const ::wstring& s, ostream* os) { 344 PrintWideCharsAsStringTo(s.data(), s.size(), os); 345 } 346 #endif // GTEST_HAS_GLOBAL_WSTRING 347 348 #if GTEST_HAS_STD_WSTRING 349 void PrintWideStringTo(const ::std::wstring& s, ostream* os) { 350 PrintWideCharsAsStringTo(s.data(), s.size(), os); 351 } 352 #endif // GTEST_HAS_STD_WSTRING 353 354 } // namespace internal 355 356 } // namespace testing 357