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@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 52namespace testing { 53 54namespace { 55 56using ::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. 67void 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. 86void 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 111namespace 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. 118void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, 119 ostream* os) { 120 PrintBytesInObjectToImpl(obj_bytes, count, os); 121} 122 123} // namespace internal2 124 125namespace 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'). 132enum 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. 141inline 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. 149template <typename UnsignedChar, typename Char> 150static 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. 196static 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. 211static 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. 219template <typename UnsignedChar, typename Char> 220void 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 245void PrintTo(unsigned char c, ::std::ostream* os) { 246 PrintCharAndCodeTo<unsigned char>(c, os); 247} 248void 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'". 254void 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. 261static 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'. 278void 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. 285static 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. 303void 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. 320void 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 332void PrintStringTo(const ::string& s, ostream* os) { 333 PrintCharsAsStringTo(s.data(), s.size(), os); 334} 335#endif // GTEST_HAS_GLOBAL_STRING 336 337void 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 343void 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 349void 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