141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Copyright 2007, Google Inc.
241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// All rights reserved.
341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Redistribution and use in source and binary forms, with or without
541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// modification, are permitted provided that the following conditions are
641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// met:
741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//     * Redistributions of source code must retain the above copyright
941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// notice, this list of conditions and the following disclaimer.
1041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//     * Redistributions in binary form must reproduce the above
1141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// copyright notice, this list of conditions and the following disclaimer
1241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// in the documentation and/or other materials provided with the
1341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// distribution.
1441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//     * Neither the name of Google Inc. nor the names of its
1541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// contributors may be used to endorse or promote products derived from
1641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// this software without specific prior written permission.
1741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
1841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
3041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Author: wan@google.com (Zhanyong Wan)
3141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
3241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Google Test - The Google C++ Testing Framework
3341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
3441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// This file implements a universal value printer that can print a
3541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// value of any type T:
3641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
3741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
3841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//
3941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// It uses the << operator when possible, and prints the bytes in the
4041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// object otherwise.  A user can override its behavior for a class
4141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// type Foo by defining either operator<<(::std::ostream&, const Foo&)
4241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
4341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// defines Foo.
4441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
4541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-printers.h"
4641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <ctype.h>
4741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <stdio.h>
4841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <ostream>  // NOLINT
4941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <string>
5041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-port.h"
5141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
5241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace testing {
5341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
5441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace {
5541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
5641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotusing ::std::ostream;
5741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
5841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE  // Windows CE does not define _snprintf_s.
5941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# define snprintf _snprintf
6041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif _MSC_VER >= 1400  // VC 8.0 and later deprecate snprintf and _snprintf.
6141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# define snprintf _snprintf_s
6241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif _MSC_VER
6341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# define snprintf _snprintf
6441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_OS_WINDOWS_MOBILE
6541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
6641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a segment of bytes in the given object.
6741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
6841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                                size_t count, ostream* os) {
6941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  char text[5] = "";
7041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  for (size_t i = 0; i != count; i++) {
7141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const size_t j = start + i;
7241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    if (i != 0) {
7341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // Organizes the bytes into groups of 2 for easy parsing by
7441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // human.
7541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      if ((j % 2) == 0)
7641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        *os << ' ';
7741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      else
7841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        *os << '-';
7941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    }
8041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
8141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << text;
8241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
8341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
8441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
8541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints the bytes in the given value to the given ostream.
8641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
8741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                              ostream* os) {
8841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // Tells the user how big the object is.
8941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << count << "-byte object <";
9041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
9141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const size_t kThreshold = 132;
9241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const size_t kChunkSize = 64;
9341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // If the object size is bigger than kThreshold, we'll have to omit
9441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // some details by printing only the first and the last kChunkSize
9541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // bytes.
9641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // TODO(wan): let the user control the threshold using a flag.
9741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (count < kThreshold) {
9841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
9941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  } else {
10041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
10141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << " ... ";
10241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // Rounds up to 2-byte boundary.
10341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
10441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
10541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
10641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << ">";
10741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
10841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
10941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}  // namespace
11041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
11141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace internal2 {
11241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
11341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
11441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// given object.  The delegation simplifies the implementation, which
11541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// uses the << operator and thus is easier done outside of the
11641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// ::testing::internal namespace, which contains a << operator that
11741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// sometimes conflicts with the one in STL.
11841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
11941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                          ostream* os) {
12041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintBytesInObjectToImpl(obj_bytes, count, os);
12141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
12241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
12341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}  // namespace internal2
12441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
12541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace internal {
12641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
12741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Depending on the value of a char (or wchar_t), we print it in one
12841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// of three formats:
12941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
13041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
13141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot//   - as a special escape sequence (e.g. '\r', '\n').
13241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotenum CharFormat {
13341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  kAsIs,
13441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  kHexEscape,
13541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  kSpecialEscape
13641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot};
13741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
13841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Returns true if c is a printable ASCII character.  We test the
13941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// value of c directly instead of calling isprint(), which is buggy on
14041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Windows Mobile.
14141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotinline bool IsPrintableAscii(wchar_t c) {
14241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return 0x20 <= c && c <= 0x7E;
14341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
14441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
14541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a wide or narrow char c as a character literal without the
14641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// quotes, escaping it when necessary; returns how c was formatted.
14741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// The template argument UnsignedChar is the unsigned version of Char,
14841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// which is the type of c.
14941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabottemplate <typename UnsignedChar, typename Char>
15041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
15141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  switch (static_cast<wchar_t>(c)) {
15241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\0':
15341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\0";
15441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
15541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\'':
15641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\'";
15741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
15841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\\':
15941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\\\";
16041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
16141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\a':
16241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\a";
16341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
16441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\b':
16541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\b";
16641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
16741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\f':
16841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\f";
16941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
17041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\n':
17141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\n";
17241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
17341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\r':
17441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\r";
17541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
17641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\t':
17741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\t";
17841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
17941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\v':
18041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\v";
18141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      break;
18241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    default:
18341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      if (IsPrintableAscii(c)) {
18441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        *os << static_cast<char>(c);
18541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        return kAsIs;
18641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      } else {
18741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        *os << String::Format("\\x%X", static_cast<UnsignedChar>(c));
18841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot        return kHexEscape;
18941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      }
19041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
19141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return kSpecialEscape;
19241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
19341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
19441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a char c as if it's part of a string literal, escaping it when
19541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// necessary; returns how c was formatted.
19641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
19741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  switch (c) {
19841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'\'':
19941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "'";
20041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      return kAsIs;
20141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    case L'"':
20241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\\\"";
20341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      return kSpecialEscape;
20441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    default:
20541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      return PrintAsCharLiteralTo<wchar_t>(c, os);
20641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
20741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
20841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
20941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a char c as if it's part of a string literal, escaping it when
21041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// necessary; returns how c was formatted.
21141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
21241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
21341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
21441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
21541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a wide or narrow character c and its code.  '\0' is printed
21641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// as "'\\0'", other unprintable characters are also properly escaped
21741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// using the standard C++ escape sequence.  The template argument
21841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// UnsignedChar is the unsigned version of Char, which is the type of c.
21941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabottemplate <typename UnsignedChar, typename Char>
22041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintCharAndCodeTo(Char c, ostream* os) {
22141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // First, print c as a literal in the most readable form we can find.
22241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << ((sizeof(c) > 1) ? "L'" : "'");
22341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
22441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << "'";
22541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
22641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // To aid user debugging, we also print c's code in decimal, unless
22741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // it's 0 (in which case c was printed as '\\0', making the code
22841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // obvious).
22941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (c == 0)
23041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    return;
23141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << " (" << String::Format("%d", c).c_str();
23241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
23341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // For more convenience, we print c's code again in hexidecimal,
23441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // unless c was already printed in the form '\x##' or the code is in
23541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  // [1, 9].
23641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (format == kHexEscape || (1 <= c && c <= 9)) {
23741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    // Do nothing.
23841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  } else {
23941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << String::Format(", 0x%X",
24041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                          static_cast<UnsignedChar>(c)).c_str();
24141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
24241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << ")";
24341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
24441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
24541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintTo(unsigned char c, ::std::ostream* os) {
24641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintCharAndCodeTo<unsigned char>(c, os);
24741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
24841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintTo(signed char c, ::std::ostream* os) {
24941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintCharAndCodeTo<unsigned char>(c, os);
25041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
25141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
25241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a wchar_t as a symbol if it is printable or as its internal
25341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
25441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintTo(wchar_t wc, ostream* os) {
25541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintCharAndCodeTo<wchar_t>(wc, os);
25641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
25741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
25841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints the given array of characters to the ostream.
25941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// The array starts at *begin, the length is len, it may include '\0' characters
26041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// and may not be null-terminated.
26141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
26241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << "\"";
26341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  bool is_previous_hex = false;
26441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  for (size_t index = 0; index < len; ++index) {
26541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const char cur = begin[index];
26641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    if (is_previous_hex && IsXDigit(cur)) {
26741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // Previous character is of '\x..' form and this character can be
26841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // interpreted as another hexadecimal digit in its number. Break string to
26941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // disambiguate.
27041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\" \"";
27141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    }
27241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
27341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
27441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << "\"";
27541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
27641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
27741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a (const) char array of 'len' elements, starting at address 'begin'.
27841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid UniversalPrintArray(const char* begin, size_t len, ostream* os) {
27941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintCharsAsStringTo(begin, len, os);
28041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
28141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
28241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints the given array of wide characters to the ostream.
28341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// The array starts at *begin, the length is len, it may include L'\0'
28441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// characters and may not be null-terminated.
28541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
28641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot                                     ostream* os) {
28741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << "L\"";
28841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  bool is_previous_hex = false;
28941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  for (size_t index = 0; index < len; ++index) {
29041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    const wchar_t cur = begin[index];
29141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
29241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // Previous character is of '\x..' form and this character can be
29341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // interpreted as another hexadecimal digit in its number. Break string to
29441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      // disambiguate.
29541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot      *os << "\" L\"";
29641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    }
29741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
29841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
29941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  *os << "\"";
30041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
30141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
30241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints the given C string to the ostream.
30341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintTo(const char* s, ostream* os) {
30441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (s == NULL) {
30541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << "NULL";
30641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  } else {
30741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << ImplicitCast_<const void*>(s) << " pointing to ";
30841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    PrintCharsAsStringTo(s, strlen(s), os);
30941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
31041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
31141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
31241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// MSVC compiler can be configured to define whar_t as a typedef
31341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// of unsigned short. Defining an overload for const wchar_t* in that case
31441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// would cause pointers to unsigned shorts be printed as wide strings,
31541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// possibly accessing more memory than intended and causing invalid
31641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
31741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// wchar_t is implemented as a native type.
31841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
31941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints the given wide C string to the ostream.
32041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintTo(const wchar_t* s, ostream* os) {
32141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  if (s == NULL) {
32241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << "NULL";
32341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  } else {
32441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    *os << ImplicitCast_<const void*>(s) << " pointing to ";
32541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot    PrintWideCharsAsStringTo(s, wcslen(s), os);
32641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  }
32741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
32841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // wchar_t is native
32941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
33041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a ::string object.
33141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_HAS_GLOBAL_STRING
33241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintStringTo(const ::string& s, ostream* os) {
33341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintCharsAsStringTo(s.data(), s.size(), os);
33441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
33541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_HAS_GLOBAL_STRING
33641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
33741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintStringTo(const ::std::string& s, ostream* os) {
33841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintCharsAsStringTo(s.data(), s.size(), os);
33941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
34041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
34141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Prints a ::wstring object.
34241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_HAS_GLOBAL_WSTRING
34341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintWideStringTo(const ::wstring& s, ostream* os) {
34441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintWideCharsAsStringTo(s.data(), s.size(), os);
34541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
34641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_HAS_GLOBAL_WSTRING
34741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
34841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_HAS_STD_WSTRING
34941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid PrintWideStringTo(const ::std::wstring& s, ostream* os) {
35041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot  PrintWideCharsAsStringTo(s.data(), s.size(), os);
35141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}
35241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif  // GTEST_HAS_STD_WSTRING
35341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
35441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}  // namespace internal
35541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot
35641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}  // namespace testing
357