44#include "gtest/gtest-printers.h"
55#include "gtest/internal/gtest-port.h"
56#include "src/gtest-internal-inl.h"
65GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
66GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
67GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
68GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
69void PrintByteSegmentInObjectTo(
const unsigned char* obj_bytes,
size_t start,
70 size_t count, ostream* os) {
72 for (
size_t i = 0; i != count; i++) {
73 const size_t j = start + i;
82 GTEST_SNPRINTF_(text,
sizeof(text),
"%02X", obj_bytes[j]);
88void PrintBytesInObjectToImpl(
const unsigned char* obj_bytes,
size_t count,
91 *os << count <<
"-byte object <";
93 const size_t kThreshold = 132;
94 const size_t kChunkSize = 64;
98 if (count < kThreshold) {
99 PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
101 PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
104 const size_t resume_pos = (count - kChunkSize + 1)/2*2;
105 PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
114template <
typename CharType>
115char32_t ToChar32(CharType in) {
116 return static_cast<char32_t>(
117 static_cast<typename std::make_unsigned<CharType>::type
>(in));
129void PrintBytesInObjectTo(
const unsigned char* obj_bytes,
size_t count,
131 PrintBytesInObjectToImpl(obj_bytes, count, os);
148inline bool IsPrintableAscii(
char32_t c) {
return 0x20 <= c && c <= 0x7E; }
153template <
typename Char>
154static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
155 const char32_t u_c = ToChar32(c);
188 if (IsPrintableAscii(u_c)) {
189 *os << static_cast<char>(c);
192 ostream::fmtflags flags = os->flags();
193 *os <<
"\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
198 return kSpecialEscape;
203static CharFormat PrintAsStringLiteralTo(
char32_t c, ostream* os) {
210 return kSpecialEscape;
212 return PrintAsCharLiteralTo(c, os);
216static const char* GetCharWidthPrefix(
char) {
220static const char* GetCharWidthPrefix(
signed char) {
224static const char* GetCharWidthPrefix(
unsigned char) {
229static const char* GetCharWidthPrefix(
char8_t) {
234static const char* GetCharWidthPrefix(
char16_t) {
238static const char* GetCharWidthPrefix(
char32_t) {
242static const char* GetCharWidthPrefix(
wchar_t) {
248static CharFormat PrintAsStringLiteralTo(
char c, ostream* os) {
249 return PrintAsStringLiteralTo(ToChar32(c), os);
253static CharFormat PrintAsStringLiteralTo(
char8_t c, ostream* os) {
254 return PrintAsStringLiteralTo(ToChar32(c), os);
258static CharFormat PrintAsStringLiteralTo(
char16_t c, ostream* os) {
259 return PrintAsStringLiteralTo(ToChar32(c), os);
262static CharFormat PrintAsStringLiteralTo(
wchar_t c, ostream* os) {
263 return PrintAsStringLiteralTo(ToChar32(c), os);
269template <
typename Char>
270void PrintCharAndCodeTo(Char c, ostream* os) {
272 *os << GetCharWidthPrefix(c) <<
"'";
273 const CharFormat format = PrintAsCharLiteralTo(c, os);
281 *os <<
" (" <<
static_cast<int>(c);
286 if (format == kHexEscape || (1 <= c && c <= 9)) {
289 *os <<
", 0x" << String::FormatHexInt(
static_cast<int>(c));
294void PrintTo(
unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
295void PrintTo(
signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
299void PrintTo(
wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
302void PrintTo(
char32_t c, ::std::ostream* os) {
303 *os << std::hex <<
"U+" << std::uppercase << std::setfill(
'0') << std::setw(4)
304 <<
static_cast<uint32_t
>(c);
311template <
typename CharType>
312GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
313GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
314GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
315GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
316static CharFormat PrintCharsAsStringTo(
317 const CharType* begin,
size_t len, ostream* os) {
318 const char*
const quote_prefix = GetCharWidthPrefix(*begin);
319 *os << quote_prefix <<
"\"";
320 bool is_previous_hex =
false;
321 CharFormat print_format = kAsIs;
322 for (
size_t index = 0; index < len; ++index) {
323 const CharType cur = begin[index];
324 if (is_previous_hex && IsXDigit(cur)) {
328 *os <<
"\" " << quote_prefix <<
"\"";
330 is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
332 if (is_previous_hex) {
333 print_format = kHexEscape;
342template <
typename CharType>
343GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
344GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
345GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
346GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
347static void UniversalPrintCharArray(
348 const CharType* begin,
size_t len, ostream* os) {
356 if (len > 0 && begin[len - 1] ==
'\0') {
357 PrintCharsAsStringTo(begin, len - 1, os);
365 PrintCharsAsStringTo(begin, len, os);
366 *os <<
" (no terminating NUL)";
370void UniversalPrintArray(
const char* begin,
size_t len, ostream* os) {
371 UniversalPrintCharArray(begin, len, os);
377void UniversalPrintArray(
const char8_t* begin,
size_t len, ostream* os) {
378 UniversalPrintCharArray(begin, len, os);
384void UniversalPrintArray(
const char16_t* begin,
size_t len, ostream* os) {
385 UniversalPrintCharArray(begin, len, os);
390void UniversalPrintArray(
const char32_t* begin,
size_t len, ostream* os) {
391 UniversalPrintCharArray(begin, len, os);
396void UniversalPrintArray(
const wchar_t* begin,
size_t len, ostream* os) {
397 UniversalPrintCharArray(begin, len, os);
403template <
typename Char>
404void PrintCStringTo(
const Char* s, ostream* os) {
408 *os << ImplicitCast_<const void*>(s) <<
" pointing to ";
409 PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
415void PrintTo(
const char* s, ostream* os) { PrintCStringTo(s, os); }
418void PrintTo(
const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
421void PrintTo(
const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
423void PrintTo(
const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
431#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
433void PrintTo(
const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
438bool ContainsUnprintableControlCodes(
const char* str,
size_t length) {
439 const unsigned char *s =
reinterpret_cast<const unsigned char *
>(str);
441 for (
size_t i = 0; i < length; i++) {
442 unsigned char ch = *s++;
443 if (std::iscntrl(ch)) {
457bool IsUTF8TrailByte(
unsigned char t) {
return 0x80 <= t && t<= 0xbf; }
459bool IsValidUTF8(
const char* str,
size_t length) {
460 const unsigned char *s =
reinterpret_cast<const unsigned char *
>(str);
462 for (
size_t i = 0; i < length;) {
463 unsigned char lead = s[i++];
470 }
else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
472 }
else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
473 IsUTF8TrailByte(s[i]) &&
474 IsUTF8TrailByte(s[i + 1]) &&
476 (lead != 0xe0 || s[i] >= 0xa0) &&
477 (lead != 0xed || s[i] < 0xa0)) {
479 }
else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
480 IsUTF8TrailByte(s[i]) &&
481 IsUTF8TrailByte(s[i + 1]) &&
482 IsUTF8TrailByte(s[i + 2]) &&
484 (lead != 0xf0 || s[i] >= 0x90) &&
485 (lead != 0xf4 || s[i] < 0x90)) {
494void ConditionalPrintAsText(
const char* str,
size_t length, ostream* os) {
495 if (!ContainsUnprintableControlCodes(str, length) &&
496 IsValidUTF8(str, length)) {
497 *os <<
"\n As Text: \"" << str <<
"\"";
503void PrintStringTo(const ::std::string& s, ostream* os) {
504 if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
505 if (GTEST_FLAG(print_utf8)) {
506 ConditionalPrintAsText(s.data(), s.size(), os);
512void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
513 PrintCharsAsStringTo(s.data(), s.size(), os);
517void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
518 PrintCharsAsStringTo(s.data(), s.size(), os);
521void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
522 PrintCharsAsStringTo(s.data(), s.size(), os);
525#if GTEST_HAS_STD_WSTRING
526void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
527 PrintCharsAsStringTo(s.data(), s.size(), os);