Skip to content

Commit

Permalink
Googletest export
Browse files Browse the repository at this point in the history
Print std::u8string, std::u16string, and std::u32string as string literals

Previously, these types were printed as "{ U+123, U+456, U+789 }". However,
printed output in that form is difficult to compare against any literals that
might be defined in code. Instead, just treat these types like std::string
and std::wstring, escaping non-ASCII characters with a hexadecimal escape
sequence.

The tests have also been updated to cover the new functionality: as a bonus,
the tests now also pass with the MSVC toolchain.

Internally, the code has been reorganized to primarily operate in terms of
char32_t, under the assumption that char32_t will always be at least as big
as wchar_t. While that assumption is currently true, perhaps it won't be in
the future...

PiperOrigin-RevId: 364033132
  • Loading branch information
Abseil Team authored and derekmauro committed Mar 22, 2021
1 parent 3ff1e8b commit 1a8ecf1
Show file tree
Hide file tree
Showing 7 changed files with 394 additions and 181 deletions.
8 changes: 8 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ config_setting(
constraint_values = ["@platforms//os:windows"],
)

config_setting(
name = "msvc_compiler",
flag_values = {
"@bazel_tools//tools/cpp:compiler": "msvc-cl",
},
visibility = [":__subpackages__"],
)

config_setting(
name = "has_absl",
values = {"define": "absl=1"},
Expand Down
2 changes: 2 additions & 0 deletions googletest/cmake/internal_utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ macro(config_compiler_and_linker)
# Suppress "unreachable code" warning
# http://stackoverflow.com/questions/3232669 explains the issue.
set(cxx_base_flags "${cxx_base_flags} -wd4702")
# Ensure MSVC treats source files as UTF-8 encoded.
set(cxx_base_flags "${cxx_base_flags} -utf-8")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(cxx_base_flags "-Wall -Wshadow -Werror -Wconversion")
set(cxx_exception_flags "-fexceptions")
Expand Down
104 changes: 89 additions & 15 deletions googletest/include/gtest/gtest-printers.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,24 +505,21 @@ inline void PrintTo(unsigned char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
#ifdef __cpp_char8_t
inline void PrintTo(const char8_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
// Overloads for u8 strings.
void PrintTo(const char8_t* s, ::std::ostream* os);
inline void PrintTo(char8_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
PrintTo(ImplicitCast_<const char8_t*>(s), os);
}
#endif
inline void PrintTo(const char16_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
// Overloads for u16 strings.
void PrintTo(const char16_t* s, ::std::ostream* os);
inline void PrintTo(char16_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(const char32_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
PrintTo(ImplicitCast_<const char16_t*>(s), os);
}
// Overloads for u32 strings.
void PrintTo(const char32_t* s, ::std::ostream* os);
inline void PrintTo(char32_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
PrintTo(ImplicitCast_<const char32_t*>(s), os);
}

// MSVC can be configured to define wchar_t as a typedef of unsigned
Expand Down Expand Up @@ -558,6 +555,26 @@ inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}

// Overloads for ::std::u8string
#ifdef __cpp_char8_t
GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os);
inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
PrintU8StringTo(s, os);
}
#endif

// Overloads for ::std::u16string
GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
PrintU16StringTo(s, os);
}

// Overloads for ::std::u32string
GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
PrintU32StringTo(s, os);
}

// Overloads for ::std::wstring.
#if GTEST_HAS_STD_WSTRING
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
Expand Down Expand Up @@ -805,6 +822,20 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
GTEST_API_ void UniversalPrintArray(
const char* begin, size_t len, ::std::ostream* os);

#ifdef __cpp_char8_t
// This overload prints a (const) char8_t array compactly.
GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len,
::std::ostream* os);
#endif

// This overload prints a (const) char16_t array compactly.
GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len,
::std::ostream* os);

// This overload prints a (const) char32_t array compactly.
GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len,
::std::ostream* os);

// This overload prints a (const) wchar_t array compactly.
GTEST_API_ void UniversalPrintArray(
const wchar_t* begin, size_t len, ::std::ostream* os);
Expand Down Expand Up @@ -877,12 +908,55 @@ class UniversalTersePrinter<const char*> {
}
};
template <>
class UniversalTersePrinter<char*> {
class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
};

#ifdef __cpp_char8_t
template <>
class UniversalTersePrinter<const char8_t*> {
public:
static void Print(const char8_t* str, ::std::ostream* os) {
if (str == nullptr) {
*os << "NULL";
} else {
UniversalPrint(::std::u8string(str), os);
}
}
};
template <>
class UniversalTersePrinter<char8_t*>
: public UniversalTersePrinter<const char8_t*> {};
#endif

template <>
class UniversalTersePrinter<const char16_t*> {
public:
static void Print(const char16_t* str, ::std::ostream* os) {
if (str == nullptr) {
*os << "NULL";
} else {
UniversalPrint(::std::u16string(str), os);
}
}
};
template <>
class UniversalTersePrinter<char16_t*>
: public UniversalTersePrinter<const char16_t*> {};

template <>
class UniversalTersePrinter<const char32_t*> {
public:
static void Print(char* str, ::std::ostream* os) {
UniversalTersePrinter<const char*>::Print(str, os);
static void Print(const char32_t* str, ::std::ostream* os) {
if (str == nullptr) {
*os << "NULL";
} else {
UniversalPrint(::std::u32string(str), os);
}
}
};
template <>
class UniversalTersePrinter<char32_t*>
: public UniversalTersePrinter<const char32_t*> {};

#if GTEST_HAS_STD_WSTRING
template <>
Expand Down
13 changes: 13 additions & 0 deletions googletest/include/gtest/internal/gtest-port.h
Original file line number Diff line number Diff line change
Expand Up @@ -1936,6 +1936,19 @@ inline bool IsUpper(char ch) {
inline bool IsXDigit(char ch) {
return isxdigit(static_cast<unsigned char>(ch)) != 0;
}
#ifdef __cpp_char8_t
inline bool IsXDigit(char8_t ch) {
return isxdigit(static_cast<unsigned char>(ch)) != 0;
}
#endif
inline bool IsXDigit(char16_t ch) {
const unsigned char low_byte = static_cast<unsigned char>(ch);
return ch == low_byte && isxdigit(low_byte) != 0;
}
inline bool IsXDigit(char32_t ch) {
const unsigned char low_byte = static_cast<unsigned char>(ch);
return ch == low_byte && isxdigit(low_byte) != 0;
}
inline bool IsXDigit(wchar_t ch) {
const unsigned char low_byte = static_cast<unsigned char>(ch);
return ch == low_byte && isxdigit(low_byte) != 0;
Expand Down
Loading

0 comments on commit 1a8ecf1

Please sign in to comment.