gtest-printers.cc
Go to the documentation of this file.
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 
31 // Google Test - The Google C++ Testing and Mocking Framework
32 //
33 // This file implements a universal value printer that can print a
34 // value of any type T:
35 //
36 // void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
37 //
38 // It uses the << operator when possible, and prints the bytes in the
39 // object otherwise. A user can override its behavior for a class
40 // type Foo by defining either operator<<(::std::ostream&, const Foo&)
41 // or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
42 // defines Foo.
43 
44 #include "gtest/gtest-printers.h"
45 #include <stdio.h>
46 #include <cctype>
47 #include <cwchar>
48 #include <ostream> // NOLINT
49 #include <string>
51 #include "src/gtest-internal-inl.h"
52 
53 namespace testing {
54 
55 namespace {
56 
57 using ::std::ostream;
58 
59 // Prints a segment of bytes in the given object.
63 void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
64  size_t count, ostream* os) {
65  char text[5] = "";
66  for (size_t i = 0; i != count; i++) {
67  const size_t j = start + i;
68  if (i != 0) {
69  // Organizes the bytes into groups of 2 for easy parsing by
70  // human.
71  if ((j % 2) == 0)
72  *os << ' ';
73  else
74  *os << '-';
75  }
76  GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
77  *os << text;
78  }
79 }
80 
81 // Prints the bytes in the given value to the given ostream.
82 void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
83  ostream* os) {
84  // Tells the user how big the object is.
85  *os << count << "-byte object <";
86 
87  const size_t kThreshold = 132;
88  const size_t kChunkSize = 64;
89  // If the object size is bigger than kThreshold, we'll have to omit
90  // some details by printing only the first and the last kChunkSize
91  // bytes.
92  if (count < kThreshold) {
93  PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
94  } else {
95  PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
96  *os << " ... ";
97  // Rounds up to 2-byte boundary.
98  const size_t resume_pos = (count - kChunkSize + 1)/2*2;
99  PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
100  }
101  *os << ">";
102 }
103 
104 } // namespace
105 
106 namespace internal2 {
107 
108 // Delegates to PrintBytesInObjectToImpl() to print the bytes in the
109 // given object. The delegation simplifies the implementation, which
110 // uses the << operator and thus is easier done outside of the
111 // ::testing::internal namespace, which contains a << operator that
112 // sometimes conflicts with the one in STL.
113 void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
114  ostream* os) {
115  PrintBytesInObjectToImpl(obj_bytes, count, os);
116 }
117 
118 } // namespace internal2
119 
120 namespace internal {
121 
122 // Depending on the value of a char (or wchar_t), we print it in one
123 // of three formats:
124 // - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
125 // - as a hexadecimal escape sequence (e.g. '\x7F'), or
126 // - as a special escape sequence (e.g. '\r', '\n').
131 };
132 
133 // Returns true if c is a printable ASCII character. We test the
134 // value of c directly instead of calling isprint(), which is buggy on
135 // Windows Mobile.
136 inline bool IsPrintableAscii(wchar_t c) {
137  return 0x20 <= c && c <= 0x7E;
138 }
139 
140 // Prints a wide or narrow char c as a character literal without the
141 // quotes, escaping it when necessary; returns how c was formatted.
142 // The template argument UnsignedChar is the unsigned version of Char,
143 // which is the type of c.
144 template <typename UnsignedChar, typename Char>
145 static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
146  switch (static_cast<wchar_t>(c)) {
147  case L'\0':
148  *os << "\\0";
149  break;
150  case L'\'':
151  *os << "\\'";
152  break;
153  case L'\\':
154  *os << "\\\\";
155  break;
156  case L'\a':
157  *os << "\\a";
158  break;
159  case L'\b':
160  *os << "\\b";
161  break;
162  case L'\f':
163  *os << "\\f";
164  break;
165  case L'\n':
166  *os << "\\n";
167  break;
168  case L'\r':
169  *os << "\\r";
170  break;
171  case L'\t':
172  *os << "\\t";
173  break;
174  case L'\v':
175  *os << "\\v";
176  break;
177  default:
178  if (IsPrintableAscii(c)) {
179  *os << static_cast<char>(c);
180  return kAsIs;
181  } else {
182  ostream::fmtflags flags = os->flags();
183  *os << "\\x" << std::hex << std::uppercase
184  << static_cast<int>(static_cast<UnsignedChar>(c));
185  os->flags(flags);
186  return kHexEscape;
187  }
188  }
189  return kSpecialEscape;
190 }
191 
192 // Prints a wchar_t c as if it's part of a string literal, escaping it when
193 // necessary; returns how c was formatted.
194 static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
195  switch (c) {
196  case L'\'':
197  *os << "'";
198  return kAsIs;
199  case L'"':
200  *os << "\\\"";
201  return kSpecialEscape;
202  default:
203  return PrintAsCharLiteralTo<wchar_t>(c, os);
204  }
205 }
206 
207 // Prints a char c as if it's part of a string literal, escaping it when
208 // necessary; returns how c was formatted.
209 static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
210  return PrintAsStringLiteralTo(
211  static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
212 }
213 
214 // Prints a wide or narrow character c and its code. '\0' is printed
215 // as "'\\0'", other unprintable characters are also properly escaped
216 // using the standard C++ escape sequence. The template argument
217 // UnsignedChar is the unsigned version of Char, which is the type of c.
218 template <typename UnsignedChar, typename Char>
219 void PrintCharAndCodeTo(Char c, ostream* os) {
220  // First, print c as a literal in the most readable form we can find.
221  *os << ((sizeof(c) > 1) ? "L'" : "'");
222  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
223  *os << "'";
224 
225  // To aid user debugging, we also print c's code in decimal, unless
226  // it's 0 (in which case c was printed as '\\0', making the code
227  // obvious).
228  if (c == 0)
229  return;
230  *os << " (" << static_cast<int>(c);
231 
232  // For more convenience, we print c's code again in hexadecimal,
233  // unless c was already printed in the form '\x##' or the code is in
234  // [1, 9].
235  if (format == kHexEscape || (1 <= c && c <= 9)) {
236  // Do nothing.
237  } else {
238  *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
239  }
240  *os << ")";
241 }
242 
243 void PrintTo(unsigned char c, ::std::ostream* os) {
244  PrintCharAndCodeTo<unsigned char>(c, os);
245 }
246 void PrintTo(signed char c, ::std::ostream* os) {
247  PrintCharAndCodeTo<unsigned char>(c, os);
248 }
249 
250 // Prints a wchar_t as a symbol if it is printable or as its internal
251 // code otherwise and also as its code. L'\0' is printed as "L'\\0'".
252 void PrintTo(wchar_t wc, ostream* os) {
253  PrintCharAndCodeTo<wchar_t>(wc, os);
254 }
255 
256 // Prints the given array of characters to the ostream. CharType must be either
257 // char or wchar_t.
258 // The array starts at begin, the length is len, it may include '\0' characters
259 // and may not be NUL-terminated.
260 template <typename CharType>
265  const CharType* begin, size_t len, ostream* os) {
266  const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
267  *os << kQuoteBegin;
268  bool is_previous_hex = false;
269  CharFormat print_format = kAsIs;
270  for (size_t index = 0; index < len; ++index) {
271  const CharType cur = begin[index];
272  if (is_previous_hex && IsXDigit(cur)) {
273  // Previous character is of '\x..' form and this character can be
274  // interpreted as another hexadecimal digit in its number. Break string to
275  // disambiguate.
276  *os << "\" " << kQuoteBegin;
277  }
278  is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
279  // Remember if any characters required hex escaping.
280  if (is_previous_hex) {
281  print_format = kHexEscape;
282  }
283  }
284  *os << "\"";
285  return print_format;
286 }
287 
288 // Prints a (const) char/wchar_t array of 'len' elements, starting at address
289 // 'begin'. CharType must be either char or wchar_t.
290 template <typename CharType>
295  const CharType* begin, size_t len, ostream* os) {
296  // The code
297  // const char kFoo[] = "foo";
298  // generates an array of 4, not 3, elements, with the last one being '\0'.
299  //
300  // Therefore when printing a char array, we don't print the last element if
301  // it's '\0', such that the output matches the string literal as it's
302  // written in the source code.
303  if (len > 0 && begin[len - 1] == '\0') {
304  PrintCharsAsStringTo(begin, len - 1, os);
305  return;
306  }
307 
308  // If, however, the last element in the array is not '\0', e.g.
309  // const char kFoo[] = { 'f', 'o', 'o' };
310  // we must print the entire array. We also print a message to indicate
311  // that the array is not NUL-terminated.
313  *os << " (no terminating NUL)";
314 }
315 
316 // Prints a (const) char array of 'len' elements, starting at address 'begin'.
317 void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
319 }
320 
321 // Prints a (const) wchar_t array of 'len' elements, starting at address
322 // 'begin'.
323 void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
325 }
326 
327 // Prints the given C string to the ostream.
328 void PrintTo(const char* s, ostream* os) {
329  if (s == nullptr) {
330  *os << "NULL";
331  } else {
332  *os << ImplicitCast_<const void*>(s) << " pointing to ";
333  PrintCharsAsStringTo(s, strlen(s), os);
334  }
335 }
336 
337 // MSVC compiler can be configured to define whar_t as a typedef
338 // of unsigned short. Defining an overload for const wchar_t* in that case
339 // would cause pointers to unsigned shorts be printed as wide strings,
340 // possibly accessing more memory than intended and causing invalid
341 // memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
342 // wchar_t is implemented as a native type.
343 #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
344 // Prints the given wide C string to the ostream.
345 void PrintTo(const wchar_t* s, ostream* os) {
346  if (s == nullptr) {
347  *os << "NULL";
348  } else {
349  *os << ImplicitCast_<const void*>(s) << " pointing to ";
350  PrintCharsAsStringTo(s, wcslen(s), os);
351  }
352 }
353 #endif // wchar_t is native
354 
355 namespace {
356 
357 bool ContainsUnprintableControlCodes(const char* str, size_t length) {
358  const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
359 
360  for (size_t i = 0; i < length; i++) {
361  unsigned char ch = *s++;
362  if (std::iscntrl(ch)) {
363  switch (ch) {
364  case '\t':
365  case '\n':
366  case '\r':
367  break;
368  default:
369  return true;
370  }
371  }
372  }
373  return false;
374 }
375 
376 bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
377 
378 bool IsValidUTF8(const char* str, size_t length) {
379  const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
380 
381  for (size_t i = 0; i < length;) {
382  unsigned char lead = s[i++];
383 
384  if (lead <= 0x7f) {
385  continue; // single-byte character (ASCII) 0..7F
386  }
387  if (lead < 0xc2) {
388  return false; // trail byte or non-shortest form
389  } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
390  ++i; // 2-byte character
391  } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
392  IsUTF8TrailByte(s[i]) &&
393  IsUTF8TrailByte(s[i + 1]) &&
394  // check for non-shortest form and surrogate
395  (lead != 0xe0 || s[i] >= 0xa0) &&
396  (lead != 0xed || s[i] < 0xa0)) {
397  i += 2; // 3-byte character
398  } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
399  IsUTF8TrailByte(s[i]) &&
400  IsUTF8TrailByte(s[i + 1]) &&
401  IsUTF8TrailByte(s[i + 2]) &&
402  // check for non-shortest form
403  (lead != 0xf0 || s[i] >= 0x90) &&
404  (lead != 0xf4 || s[i] < 0x90)) {
405  i += 3; // 4-byte character
406  } else {
407  return false;
408  }
409  }
410  return true;
411 }
412 
413 void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
414  if (!ContainsUnprintableControlCodes(str, length) &&
415  IsValidUTF8(str, length)) {
416  *os << "\n As Text: \"" << str << "\"";
417  }
418 }
419 
420 } // anonymous namespace
421 
422 // Prints a ::string object.
423 #if GTEST_HAS_GLOBAL_STRING
424 void PrintStringTo(const ::string& s, ostream* os) {
425  if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
426  if (GTEST_FLAG(print_utf8)) {
427  ConditionalPrintAsText(s.data(), s.size(), os);
428  }
429  }
430 }
431 #endif // GTEST_HAS_GLOBAL_STRING
432 
433 void PrintStringTo(const ::std::string& s, ostream* os) {
434  if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
435  if (GTEST_FLAG(print_utf8)) {
436  ConditionalPrintAsText(s.data(), s.size(), os);
437  }
438  }
439 }
440 
441 // Prints a ::wstring object.
442 #if GTEST_HAS_GLOBAL_WSTRING
443 void PrintWideStringTo(const ::wstring& s, ostream* os) {
444  PrintCharsAsStringTo(s.data(), s.size(), os);
445 }
446 #endif // GTEST_HAS_GLOBAL_WSTRING
447 
448 #if GTEST_HAS_STD_WSTRING
449 void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
450  PrintCharsAsStringTo(s.data(), s.size(), os);
451 }
452 #endif // GTEST_HAS_STD_WSTRING
453 
454 } // namespace internal
455 
456 } // namespace testing
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
#define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
Definition: gtest-port.h:809
testing
Definition: gmock-actions.h:59
testing::internal::IsXDigit
bool IsXDigit(char ch)
Definition: gtest-port.h:2017
gtest-internal-inl.h
testing::internal::PrintStringTo
GTEST_API_ void PrintStringTo(const ::std::string &s, ::std::ostream *os)
length
GLenum GLuint GLenum GLsizei length
Definition: glcorearb.h:2695
testing::internal::PrintCharAndCodeTo
void PrintCharAndCodeTo(Char c, ostream *os)
Definition: gtest-printers.cc:219
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
#define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
Definition: gtest-port.h:821
testing::internal::PrintAsStringLiteralTo
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream *os)
Definition: gtest-printers.cc:194
s
XmlRpcServer s
testing::internal::UniversalPrintCharArray
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ static GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ void UniversalPrintCharArray(const CharType *begin, size_t len, ostream *os)
Definition: gtest-printers.cc:294
testing::internal::String::FormatHexInt
static std::string FormatHexInt(int value)
Definition: gtest.cc:1982
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
testing::internal2::PrintBytesInObjectTo
GTEST_API_ void PrintBytesInObjectTo(const unsigned char *obj_bytes, size_t count, ::std::ostream *os)
testing::gmock_generated_actions_test::Char
char Char(char ch)
Definition: gmock-generated-actions_test.cc:63
flags
GLbitfield flags
Definition: glcorearb.h:3585
GTEST_SNPRINTF_
#define GTEST_SNPRINTF_
Definition: gtest-port.h:2176
GTEST_FLAG
#define GTEST_FLAG(name)
Definition: gtest-port.h:2251
begin
static size_t begin(const upb_table *t)
Definition: php/ext/google/protobuf/upb.c:4898
testing::internal::wstring
::std::wstring wstring
Definition: gtest-port.h:887
start
GLuint start
Definition: glcorearb.h:2858
format
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:2773
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
#define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
Definition: gtest-port.h:797
testing::internal::CharFormat
CharFormat
Definition: gtest-printers.cc:127
gtest-port.h
update_failure_list.str
str
Definition: update_failure_list.py:41
testing::internal::UniversalPrintArray
void UniversalPrintArray(const T *begin, size_t len, ::std::ostream *os)
Definition: gtest-printers.h:753
testing::internal::kHexEscape
@ kHexEscape
Definition: gtest-printers.cc:129
testing::internal::PrintAsCharLiteralTo
static CharFormat PrintAsCharLiteralTo(Char c, ostream *os)
Definition: gtest-printers.cc:145
i
int i
Definition: gmock-matchers_test.cc:764
testing::internal::IsPrintableAscii
bool IsPrintableAscii(wchar_t c)
Definition: gtest-printers.cc:136
len
int len
Definition: php/ext/google/protobuf/map.c:206
testing::internal::PrintCharsAsStringTo
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ static GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ CharFormat PrintCharsAsStringTo(const CharType *begin, size_t len, ostream *os)
Definition: gtest-printers.cc:264
testing::internal::kSpecialEscape
@ kSpecialEscape
Definition: gtest-printers.cc:130
gtest-printers.h
ch
char ch
Definition: gmock-matchers_test.cc:3871
google::protobuf::python::IsValidUTF8
bool IsValidUTF8(PyObject *obj)
Definition: python/google/protobuf/pyext/message.cc:706
testing::internal::kAsIs
@ kAsIs
Definition: gtest-printers.cc:128
internal
Definition: any.pb.h:40
count
GLint GLsizei count
Definition: glcorearb.h:2830
index
GLuint index
Definition: glcorearb.h:3055
testing::internal::PrintTo
void PrintTo(const T &value, ::std::ostream *os)
Definition: gtest-printers.h:492


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:53