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