43#include "gtest/gtest-printers.h"
54#include "gtest/internal/gtest-port.h"
55#include "src/gtest-internal-inl.h"
64GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
65GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
66GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
67GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
68void PrintByteSegmentInObjectTo(
const unsigned char* obj_bytes,
size_t start,
69 size_t count, ostream* os) {
71 for (
size_t i = 0; i != count; i++) {
72 const size_t j = start + i;
81 GTEST_SNPRINTF_(text,
sizeof(text),
"%02X", obj_bytes[j]);
87void PrintBytesInObjectToImpl(
const unsigned char* obj_bytes,
size_t count,
90 *os << count <<
"-byte object <";
92 const size_t kThreshold = 132;
93 const size_t kChunkSize = 64;
97 if (count < kThreshold) {
98 PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
100 PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
103 const size_t resume_pos = (count - kChunkSize + 1) / 2 * 2;
104 PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
113template <
typename CharType>
114char32_t ToChar32(CharType in) {
115 return static_cast<char32_t>(
116 static_cast<typename std::make_unsigned<CharType>::type
>(in));
128void PrintBytesInObjectTo(
const unsigned char* obj_bytes,
size_t count,
130 PrintBytesInObjectToImpl(obj_bytes, count, os);
138enum CharFormat { kAsIs, kHexEscape, kSpecialEscape };
143inline bool IsPrintableAscii(
char32_t c) {
return 0x20 <= c && c <= 0x7E; }
148template <
typename Char>
149static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
150 const char32_t u_c = ToChar32(c);
183 if (IsPrintableAscii(u_c)) {
184 *os << static_cast<char>(c);
187 ostream::fmtflags flags = os->flags();
188 *os <<
"\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
193 return kSpecialEscape;
198static CharFormat PrintAsStringLiteralTo(
char32_t c, ostream* os) {
205 return kSpecialEscape;
207 return PrintAsCharLiteralTo(c, os);
211static const char* GetCharWidthPrefix(
char) {
return ""; }
213static const char* GetCharWidthPrefix(
signed char) {
return ""; }
215static const char* GetCharWidthPrefix(
unsigned char) {
return ""; }
218static const char* GetCharWidthPrefix(
char8_t) {
return "u8"; }
221static const char* GetCharWidthPrefix(
char16_t) {
return "u"; }
223static const char* GetCharWidthPrefix(
char32_t) {
return "U"; }
225static const char* GetCharWidthPrefix(
wchar_t) {
return "L"; }
229static CharFormat PrintAsStringLiteralTo(
char c, ostream* os) {
230 return PrintAsStringLiteralTo(ToChar32(c), os);
234static CharFormat PrintAsStringLiteralTo(
char8_t c, ostream* os) {
235 return PrintAsStringLiteralTo(ToChar32(c), os);
239static CharFormat PrintAsStringLiteralTo(
char16_t c, ostream* os) {
240 return PrintAsStringLiteralTo(ToChar32(c), os);
243static CharFormat PrintAsStringLiteralTo(
wchar_t c, ostream* os) {
244 return PrintAsStringLiteralTo(ToChar32(c), os);
250template <
typename Char>
251void PrintCharAndCodeTo(Char c, ostream* os) {
253 *os << GetCharWidthPrefix(c) <<
"'";
254 const CharFormat format = PrintAsCharLiteralTo(c, os);
261 *os <<
" (" <<
static_cast<int>(c);
266 if (format == kHexEscape || (1 <= c && c <= 9)) {
269 *os <<
", 0x" << String::FormatHexInt(
static_cast<int>(c));
274void PrintTo(
unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
275void PrintTo(
signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
279void PrintTo(
wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
282void PrintTo(
char32_t c, ::std::ostream* os) {
283 *os << std::hex <<
"U+" << std::uppercase << std::setfill(
'0') << std::setw(4)
284 <<
static_cast<uint32_t
>(c);
288#if defined(__SIZEOF_INT128__)
289void PrintTo(__uint128_t v, ::std::ostream* os) {
297 char* p = buf +
sizeof(buf);
302 uint64_t high =
static_cast<uint64_t
>(v >> 64);
303 uint64_t low =
static_cast<uint64_t
>(v);
306 while (high != 0 || low != 0) {
307 uint64_t high_mod = high % 10;
314 const uint64_t carry = 6 * high_mod + low % 10;
315 low = low / 10 + high_mod * 1844674407370955161 + carry / 10;
317 char digit =
static_cast<char>(carry % 10);
318 *--p =
static_cast<char>(
'0' + digit);
322void PrintTo(__int128_t v, ::std::ostream* os) {
323 __uint128_t uv =
static_cast<__uint128_t
>(v);
336template <
typename CharType>
337GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
338 GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
339 GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static CharFormat
340 PrintCharsAsStringTo(
const CharType* begin,
size_t len, ostream* os) {
341 const char*
const quote_prefix = GetCharWidthPrefix(*begin);
342 *os << quote_prefix <<
"\"";
343 bool is_previous_hex =
false;
344 CharFormat print_format = kAsIs;
345 for (
size_t index = 0; index < len; ++index) {
346 const CharType cur = begin[index];
347 if (is_previous_hex && IsXDigit(cur)) {
351 *os <<
"\" " << quote_prefix <<
"\"";
353 is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
355 if (is_previous_hex) {
356 print_format = kHexEscape;
365template <
typename CharType>
366GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
367 GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
368 GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void
369 UniversalPrintCharArray(
const CharType* begin,
size_t len,
378 if (len > 0 && begin[len - 1] ==
'\0') {
379 PrintCharsAsStringTo(begin, len - 1, os);
387 PrintCharsAsStringTo(begin, len, os);
388 *os <<
" (no terminating NUL)";
392void UniversalPrintArray(
const char* begin,
size_t len, ostream* os) {
393 UniversalPrintCharArray(begin, len, os);
399void UniversalPrintArray(
const char8_t* begin,
size_t len, ostream* os) {
400 UniversalPrintCharArray(begin, len, os);
406void UniversalPrintArray(
const char16_t* begin,
size_t len, ostream* os) {
407 UniversalPrintCharArray(begin, len, os);
412void UniversalPrintArray(
const char32_t* begin,
size_t len, ostream* os) {
413 UniversalPrintCharArray(begin, len, os);
418void UniversalPrintArray(
const wchar_t* begin,
size_t len, ostream* os) {
419 UniversalPrintCharArray(begin, len, os);
425template <
typename Char>
426void PrintCStringTo(
const Char* s, ostream* os) {
430 *os << ImplicitCast_<const void*>(s) <<
" pointing to ";
431 PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
437void PrintTo(
const char* s, ostream* os) { PrintCStringTo(s, os); }
440void PrintTo(
const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
443void PrintTo(
const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
445void PrintTo(
const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
453#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
455void PrintTo(
const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
460bool ContainsUnprintableControlCodes(
const char* str,
size_t length) {
461 const unsigned char* s =
reinterpret_cast<const unsigned char*
>(str);
463 for (
size_t i = 0; i < length; i++) {
464 unsigned char ch = *s++;
465 if (std::iscntrl(ch)) {
479bool IsUTF8TrailByte(
unsigned char t) {
return 0x80 <= t && t <= 0xbf; }
481bool IsValidUTF8(
const char* str,
size_t length) {
482 const unsigned char* s =
reinterpret_cast<const unsigned char*
>(str);
484 for (
size_t i = 0; i < length;) {
485 unsigned char lead = s[i++];
492 }
else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
494 }
else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
495 IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
497 (lead != 0xe0 || s[i] >= 0xa0) &&
498 (lead != 0xed || s[i] < 0xa0)) {
500 }
else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
501 IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
502 IsUTF8TrailByte(s[i + 2]) &&
504 (lead != 0xf0 || s[i] >= 0x90) &&
505 (lead != 0xf4 || s[i] < 0x90)) {
514void ConditionalPrintAsText(
const char* str,
size_t length, ostream* os) {
515 if (!ContainsUnprintableControlCodes(str, length) &&
516 IsValidUTF8(str, length)) {
517 *os <<
"\n As Text: \"" << str <<
"\"";
523void PrintStringTo(const ::std::string& s, ostream* os) {
524 if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
525 if (GTEST_FLAG_GET(print_utf8)) {
526 ConditionalPrintAsText(s.data(), s.size(), os);
532void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
533 PrintCharsAsStringTo(s.data(), s.size(), os);
537void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
538 PrintCharsAsStringTo(s.data(), s.size(), os);
541void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
542 PrintCharsAsStringTo(s.data(), s.size(), os);
545#if GTEST_HAS_STD_WSTRING
546void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
547 PrintCharsAsStringTo(s.data(), s.size(), os);