gtest-printers.h (googletest-release-1.10.0) | : | gtest-printers.h (googletest-release-1.11.0) | ||
---|---|---|---|---|
skipping to change at line 99 | skipping to change at line 99 | |||
// iterator but not a forward iterator, this inferred type may not | // iterator but not a forward iterator, this inferred type may not | |||
// match value_type, and the print output may be incorrect. In | // match value_type, and the print output may be incorrect. In | |||
// practice, this is rarely a problem as for most containers | // practice, this is rarely a problem as for most containers | |||
// const_iterator is a forward iterator. We'll fix this if there's an | // const_iterator is a forward iterator. We'll fix this if there's an | |||
// actual need for it. Note that this fix cannot rely on value_type | // actual need for it. Note that this fix cannot rely on value_type | |||
// being defined as many user-defined container types don't have | // being defined as many user-defined container types don't have | |||
// value_type. | // value_type. | |||
// GOOGLETEST_CM0001 DO NOT DELETE | // GOOGLETEST_CM0001 DO NOT DELETE | |||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ | |||
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ | #define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ | |||
#include <functional> | #include <functional> | |||
#include <memory> | ||||
#include <ostream> // NOLINT | #include <ostream> // NOLINT | |||
#include <sstream> | #include <sstream> | |||
#include <string> | #include <string> | |||
#include <tuple> | #include <tuple> | |||
#include <type_traits> | #include <type_traits> | |||
#include <utility> | #include <utility> | |||
#include <vector> | #include <vector> | |||
#include "gtest/internal/gtest-internal.h" | #include "gtest/internal/gtest-internal.h" | |||
#include "gtest/internal/gtest-port.h" | #include "gtest/internal/gtest-port.h" | |||
#if GTEST_HAS_ABSL | ||||
#include "absl/strings/string_view.h" | ||||
#include "absl/types/optional.h" | ||||
#include "absl/types/variant.h" | ||||
#endif // GTEST_HAS_ABSL | ||||
namespace testing { | namespace testing { | |||
// Definitions in the 'internal' and 'internal2' name spaces are | // Definitions in the internal* namespaces are subject to change without notice. | |||
// subject to change without notice. DO NOT USE THEM IN USER CODE! | // DO NOT USE THEM IN USER CODE! | |||
namespace internal2 { | namespace internal { | |||
// Prints the given number of bytes in the given object to the given | template <typename T> | |||
// ostream. | void UniversalPrint(const T& value, ::std::ostream* os); | |||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, | ||||
size_t count, | ||||
::std::ostream* os); | ||||
// For selecting which printer to use when a given type has neither << | // Used to print an STL-style container when the user doesn't define | |||
// nor PrintTo(). | // a PrintTo() for it. | |||
enum TypeKind { | struct ContainerPrinter { | |||
kProtobuf, // a protobuf type | template <typename T, | |||
kConvertibleToInteger, // a type implicitly convertible to BiggestInt | typename = typename std::enable_if< | |||
// (e.g. a named or unnamed enum type) | (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && | |||
#if GTEST_HAS_ABSL | !IsRecursiveContainer<T>::value>::type> | |||
kConvertibleToStringView, // a type implicitly convertible to | static void PrintValue(const T& container, std::ostream* os) { | |||
// absl::string_view | const size_t kMaxCount = 32; // The maximum number of elements to print. | |||
#endif | *os << '{'; | |||
kOtherType // anything else | size_t count = 0; | |||
for (auto&& elem : container) { | ||||
if (count > 0) { | ||||
*os << ','; | ||||
if (count == kMaxCount) { // Enough has been printed. | ||||
*os << " ..."; | ||||
break; | ||||
} | ||||
} | ||||
*os << ' '; | ||||
// We cannot call PrintTo(elem, os) here as PrintTo() doesn't | ||||
// handle `elem` being a native array. | ||||
internal::UniversalPrint(elem, os); | ||||
++count; | ||||
} | ||||
if (count > 0) { | ||||
*os << ' '; | ||||
} | ||||
*os << '}'; | ||||
} | ||||
}; | }; | |||
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called | // Used to print a pointer that is neither a char pointer nor a member | |||
// by the universal printer to print a value of type T when neither | // pointer, when the user doesn't define PrintTo() for it. (A member | |||
// operator<< nor PrintTo() is defined for T, where kTypeKind is the | // variable pointer or member function pointer doesn't really point to | |||
// "kind" of T as defined by enum TypeKind. | // a location in the address space. Their representation is | |||
template <typename T, TypeKind kTypeKind> | // implementation-defined. Therefore they will be printed as raw | |||
class TypeWithoutFormatter { | // bytes.) | |||
public: | struct FunctionPointerPrinter { | |||
// This default version is called when kTypeKind is kOtherType. | template <typename T, typename = typename std::enable_if< | |||
std::is_function<T>::value>::type> | ||||
static void PrintValue(T* p, ::std::ostream* os) { | ||||
if (p == nullptr) { | ||||
*os << "NULL"; | ||||
} else { | ||||
// T is a function type, so '*os << p' doesn't do what we want | ||||
// (it just prints p as bool). We want to print p as a const | ||||
// void*. | ||||
*os << reinterpret_cast<const void*>(p); | ||||
} | ||||
} | ||||
}; | ||||
struct PointerPrinter { | ||||
template <typename T> | ||||
static void PrintValue(T* p, ::std::ostream* os) { | ||||
if (p == nullptr) { | ||||
*os << "NULL"; | ||||
} else { | ||||
// T is not a function type. We just call << to print p, | ||||
// relying on ADL to pick up user-defined << for their pointer | ||||
// types, if any. | ||||
*os << p; | ||||
} | ||||
} | ||||
}; | ||||
namespace internal_stream_operator_without_lexical_name_lookup { | ||||
// The presence of an operator<< here will terminate lexical scope lookup | ||||
// straight away (even though it cannot be a match because of its argument | ||||
// types). Thus, the two operator<< calls in StreamPrinter will find only ADL | ||||
// candidates. | ||||
struct LookupBlocker {}; | ||||
void operator<<(LookupBlocker, LookupBlocker); | ||||
struct StreamPrinter { | ||||
template <typename T, | ||||
// Don't accept member pointers here. We'd print them via implicit | ||||
// conversion to bool, which isn't useful. | ||||
typename = typename std::enable_if< | ||||
!std::is_member_pointer<T>::value>::type, | ||||
// Only accept types for which we can find a streaming operator via | ||||
// ADL (possibly involving implicit conversions). | ||||
typename = decltype(std::declval<std::ostream&>() | ||||
<< std::declval<const T&>())> | ||||
static void PrintValue(const T& value, ::std::ostream* os) { | static void PrintValue(const T& value, ::std::ostream* os) { | |||
PrintBytesInObjectTo( | // Call streaming operator found by ADL, possibly with implicit conversions | |||
static_cast<const unsigned char*>( | // of the arguments. | |||
reinterpret_cast<const void*>(std::addressof(value))), | *os << value; | |||
sizeof(value), os); | ||||
} | } | |||
}; | }; | |||
// We print a protobuf using its ShortDebugString() when the string | } // namespace internal_stream_operator_without_lexical_name_lookup | |||
// doesn't exceed this many characters; otherwise we print it using | ||||
// DebugString() for better readability. | ||||
const size_t kProtobufOneLinerMaxLength = 50; | ||||
template <typename T> | struct ProtobufPrinter { | |||
class TypeWithoutFormatter<T, kProtobuf> { | // We print a protobuf using its ShortDebugString() when the string | |||
public: | // doesn't exceed this many characters; otherwise we print it using | |||
// DebugString() for better readability. | ||||
static const size_t kProtobufOneLinerMaxLength = 50; | ||||
template <typename T, | ||||
typename = typename std::enable_if< | ||||
internal::HasDebugStringAndShortDebugString<T>::value>::type> | ||||
static void PrintValue(const T& value, ::std::ostream* os) { | static void PrintValue(const T& value, ::std::ostream* os) { | |||
std::string pretty_str = value.ShortDebugString(); | std::string pretty_str = value.ShortDebugString(); | |||
if (pretty_str.length() > kProtobufOneLinerMaxLength) { | if (pretty_str.length() > kProtobufOneLinerMaxLength) { | |||
pretty_str = "\n" + value.DebugString(); | pretty_str = "\n" + value.DebugString(); | |||
} | } | |||
*os << ("<" + pretty_str + ">"); | *os << ("<" + pretty_str + ">"); | |||
} | } | |||
}; | }; | |||
template <typename T> | struct ConvertibleToIntegerPrinter { | |||
class TypeWithoutFormatter<T, kConvertibleToInteger> { | ||||
public: | ||||
// Since T has no << operator or PrintTo() but can be implicitly | // Since T has no << operator or PrintTo() but can be implicitly | |||
// converted to BiggestInt, we print it as a BiggestInt. | // converted to BiggestInt, we print it as a BiggestInt. | |||
// | // | |||
// Most likely T is an enum type (either named or unnamed), in which | // Most likely T is an enum type (either named or unnamed), in which | |||
// case printing it as an integer is the desired behavior. In case | // case printing it as an integer is the desired behavior. In case | |||
// T is not an enum, printing it as an integer is the best we can do | // T is not an enum, printing it as an integer is the best we can do | |||
// given that it has no user-defined printer. | // given that it has no user-defined printer. | |||
static void PrintValue(const T& value, ::std::ostream* os) { | static void PrintValue(internal::BiggestInt value, ::std::ostream* os) { | |||
const internal::BiggestInt kBigInt = value; | *os << value; | |||
*os << kBigInt; | ||||
} | } | |||
}; | }; | |||
#if GTEST_HAS_ABSL | struct ConvertibleToStringViewPrinter { | |||
template <typename T> | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
class TypeWithoutFormatter<T, kConvertibleToStringView> { | static void PrintValue(internal::StringView value, ::std::ostream* os) { | |||
public: | internal::UniversalPrint(value, os); | |||
// Since T has neither operator<< nor PrintTo() but can be implicitly | } | |||
// converted to absl::string_view, we print it as a absl::string_view. | ||||
// | ||||
// Note: the implementation is further below, as it depends on | ||||
// internal::PrintTo symbol which is defined later in the file. | ||||
static void PrintValue(const T& value, ::std::ostream* os); | ||||
}; | ||||
#endif | ||||
// Prints the given value to the given ostream. If the value is a | ||||
// protocol message, its debug string is printed; if it's an enum or | ||||
// of a type implicitly convertible to BiggestInt, it's printed as an | ||||
// integer; otherwise the bytes in the value are printed. This is | ||||
// what UniversalPrinter<T>::Print() does when it knows nothing about | ||||
// type T and T has neither << operator nor PrintTo(). | ||||
// | ||||
// A user can override this behavior for a class type Foo by defining | ||||
// a << operator in the namespace where Foo is defined. | ||||
// | ||||
// We put this operator in namespace 'internal2' instead of 'internal' | ||||
// to simplify the implementation, as much code in 'internal' needs to | ||||
// use << in STL, which would conflict with our own << were it defined | ||||
// in 'internal'. | ||||
// | ||||
// Note that this operator<< takes a generic std::basic_ostream<Char, | ||||
// CharTraits> type instead of the more restricted std::ostream. If | ||||
// we define it to take an std::ostream instead, we'll get an | ||||
// "ambiguous overloads" compiler error when trying to print a type | ||||
// Foo that supports streaming to std::basic_ostream<Char, | ||||
// CharTraits>, as the compiler cannot tell whether | ||||
// operator<<(std::ostream&, const T&) or | ||||
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more | ||||
// specific. | ||||
template <typename Char, typename CharTraits, typename T> | ||||
::std::basic_ostream<Char, CharTraits>& operator<<( | ||||
::std::basic_ostream<Char, CharTraits>& os, const T& x) { | ||||
TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value | ||||
? kProtobuf | ||||
: std::is_convertible< | ||||
const T&, internal::BiggestInt>::value | ||||
? kConvertibleToInteger | ||||
: | ||||
#if GTEST_HAS_ABSL | ||||
std::is_convertible< | ||||
const T&, absl::string_view>::value | ||||
? kConvertibleToStringView | ||||
: | ||||
#endif | #endif | |||
kOtherType)>::PrintValue(x, &os); | }; | |||
return os; | ||||
} | ||||
} // namespace internal2 | // Prints the given number of bytes in the given object to the given | |||
} // namespace testing | // ostream. | |||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, | ||||
size_t count, | ||||
::std::ostream* os); | ||||
struct RawBytesPrinter { | ||||
// SFINAE on `sizeof` to make sure we have a complete type. | ||||
template <typename T, size_t = sizeof(T)> | ||||
static void PrintValue(const T& value, ::std::ostream* os) { | ||||
PrintBytesInObjectTo( | ||||
static_cast<const unsigned char*>( | ||||
// Load bearing cast to void* to support iOS | ||||
reinterpret_cast<const void*>(std::addressof(value))), | ||||
sizeof(value), os); | ||||
} | ||||
}; | ||||
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up | struct FallbackPrinter { | |||
// magic needed for implementing UniversalPrinter won't work. | template <typename T> | |||
namespace testing_internal { | static void PrintValue(const T&, ::std::ostream* os) { | |||
*os << "(incomplete type)"; | ||||
// Used to print a value that is not an STL-style container when the | } | |||
// user doesn't define PrintTo() for it. | }; | |||
template <typename T> | ||||
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { | ||||
// With the following statement, during unqualified name lookup, | ||||
// testing::internal2::operator<< appears as if it was declared in | ||||
// the nearest enclosing namespace that contains both | ||||
// ::testing_internal and ::testing::internal2, i.e. the global | ||||
// namespace. For more details, refer to the C++ Standard section | ||||
// 7.3.4-1 [namespace.udir]. This allows us to fall back onto | ||||
// testing::internal2::operator<< in case T doesn't come with a << | ||||
// operator. | ||||
// | ||||
// We cannot write 'using ::testing::internal2::operator<<;', which | ||||
// gcc 3.3 fails to compile due to a compiler bug. | ||||
using namespace ::testing::internal2; // NOLINT | ||||
// Assuming T is defined in namespace foo, in the next statement, | // Try every printer in order and return the first one that works. | |||
// the compiler will consider all of: | template <typename T, typename E, typename Printer, typename... Printers> | |||
// | struct FindFirstPrinter : FindFirstPrinter<T, E, Printers...> {}; | |||
// 1. foo::operator<< (thanks to Koenig look-up), | ||||
// 2. ::operator<< (as the current namespace is enclosed in ::), | template <typename T, typename Printer, typename... Printers> | |||
// 3. testing::internal2::operator<< (thanks to the using statement above). | struct FindFirstPrinter< | |||
// | T, decltype(Printer::PrintValue(std::declval<const T&>(), nullptr)), | |||
// The operator<< whose type matches T best will be picked. | Printer, Printers...> { | |||
// | using type = Printer; | |||
// We deliberately allow #2 to be a candidate, as sometimes it's | }; | |||
// impossible to define #1 (e.g. when foo is ::std, defining | ||||
// anything in it is undefined behavior unless you are a compiler | // Select the best printer in the following order: | |||
// vendor.). | // - Print containers (they have begin/end/etc). | |||
*os << value; | // - Print function pointers. | |||
// - Print object pointers. | ||||
// - Use the stream operator, if available. | ||||
// - Print protocol buffers. | ||||
// - Print types convertible to BiggestInt. | ||||
// - Print types convertible to StringView, if available. | ||||
// - Fallback to printing the raw bytes of the object. | ||||
template <typename T> | ||||
void PrintWithFallback(const T& value, ::std::ostream* os) { | ||||
using Printer = typename FindFirstPrinter< | ||||
T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter, | ||||
internal_stream_operator_without_lexical_name_lookup::StreamPrinter, | ||||
ProtobufPrinter, ConvertibleToIntegerPrinter, | ||||
ConvertibleToStringViewPrinter, RawBytesPrinter, FallbackPrinter>::type; | ||||
Printer::PrintValue(value, os); | ||||
} | } | |||
} // namespace testing_internal | ||||
namespace testing { | ||||
namespace internal { | ||||
// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a | // FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a | |||
// value of type ToPrint that is an operand of a comparison assertion | // value of type ToPrint that is an operand of a comparison assertion | |||
// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in | // (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in | |||
// the comparison, and is used to help determine the best way to | // the comparison, and is used to help determine the best way to | |||
// format the value. In particular, when the value is a C string | // format the value. In particular, when the value is a C string | |||
// (char pointer) and the other operand is an STL string object, we | // (char pointer) and the other operand is an STL string object, we | |||
// want to format the C string as a string, since we know it is | // want to format the C string as a string, since we know it is | |||
// compared by value with the string object. If the value is a char | // compared by value with the string object. If the value is a char | |||
// pointer but the other operand is not an STL string object, we don't | // pointer but the other operand is not an STL string object, we don't | |||
// know whether the pointer is supposed to point to a NUL-terminated | // know whether the pointer is supposed to point to a NUL-terminated | |||
skipping to change at line 342 | skipping to change at line 361 | |||
public: \ | public: \ | |||
static ::std::string Format(CharType* value) { \ | static ::std::string Format(CharType* value) { \ | |||
return ::testing::PrintToString(static_cast<const void*>(value)); \ | return ::testing::PrintToString(static_cast<const void*>(value)); \ | |||
} \ | } \ | |||
} | } | |||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); | GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); | |||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); | GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); | |||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); | GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); | |||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); | GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); | |||
#ifdef __cpp_char8_t | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t); | ||||
#endif | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char16_t); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char16_t); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char32_t); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t); | ||||
#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ | #undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ | |||
// If a C string is compared with an STL string object, we know it's meant | // If a C string is compared with an STL string object, we know it's meant | |||
// to point to a NUL-terminated string, and thus can print it as a string. | // to point to a NUL-terminated string, and thus can print it as a string. | |||
#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ | #define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ | |||
template <> \ | template <> \ | |||
class FormatForComparison<CharType*, OtherStringType> { \ | class FormatForComparison<CharType*, OtherStringType> { \ | |||
public: \ | public: \ | |||
static ::std::string Format(CharType* value) { \ | static ::std::string Format(CharType* value) { \ | |||
return ::testing::PrintToString(value); \ | return ::testing::PrintToString(value); \ | |||
} \ | } \ | |||
} | } | |||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); | GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); | |||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); | GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); | |||
#ifdef __cpp_char8_t | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string); | ||||
#endif | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char16_t, ::std::u16string); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char16_t, ::std::u16string); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char32_t, ::std::u32string); | ||||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char32_t, ::std::u32string); | ||||
#if GTEST_HAS_STD_WSTRING | #if GTEST_HAS_STD_WSTRING | |||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); | GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); | |||
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); | GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); | |||
#endif | #endif | |||
#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ | #undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ | |||
// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) | // Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) | |||
// operand to be used in a failure message. The type (but not value) | // operand to be used in a failure message. The type (but not value) | |||
skipping to change at line 391 | skipping to change at line 426 | |||
// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given | // UniversalPrinter<T>::Print(value, ostream_ptr) prints the given | |||
// value to the given ostream. The caller must ensure that | // value to the given ostream. The caller must ensure that | |||
// 'ostream_ptr' is not NULL, or the behavior is undefined. | // 'ostream_ptr' is not NULL, or the behavior is undefined. | |||
// | // | |||
// We define UniversalPrinter as a class template (as opposed to a | // We define UniversalPrinter as a class template (as opposed to a | |||
// function template), as we need to partially specialize it for | // function template), as we need to partially specialize it for | |||
// reference types, which cannot be done with function templates. | // reference types, which cannot be done with function templates. | |||
template <typename T> | template <typename T> | |||
class UniversalPrinter; | class UniversalPrinter; | |||
template <typename T> | ||||
void UniversalPrint(const T& value, ::std::ostream* os); | ||||
enum DefaultPrinterType { | ||||
kPrintContainer, | ||||
kPrintPointer, | ||||
kPrintFunctionPointer, | ||||
kPrintOther, | ||||
}; | ||||
template <DefaultPrinterType type> struct WrapPrinterType {}; | ||||
// Used to print an STL-style container when the user doesn't define | ||||
// a PrintTo() for it. | ||||
template <typename C> | ||||
void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */, | ||||
const C& container, ::std::ostream* os) { | ||||
const size_t kMaxCount = 32; // The maximum number of elements to print. | ||||
*os << '{'; | ||||
size_t count = 0; | ||||
for (typename C::const_iterator it = container.begin(); | ||||
it != container.end(); ++it, ++count) { | ||||
if (count > 0) { | ||||
*os << ','; | ||||
if (count == kMaxCount) { // Enough has been printed. | ||||
*os << " ..."; | ||||
break; | ||||
} | ||||
} | ||||
*os << ' '; | ||||
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't | ||||
// handle *it being a native array. | ||||
internal::UniversalPrint(*it, os); | ||||
} | ||||
if (count > 0) { | ||||
*os << ' '; | ||||
} | ||||
*os << '}'; | ||||
} | ||||
// Used to print a pointer that is neither a char pointer nor a member | ||||
// pointer, when the user doesn't define PrintTo() for it. (A member | ||||
// variable pointer or member function pointer doesn't really point to | ||||
// a location in the address space. Their representation is | ||||
// implementation-defined. Therefore they will be printed as raw | ||||
// bytes.) | ||||
template <typename T> | ||||
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */, | ||||
T* p, ::std::ostream* os) { | ||||
if (p == nullptr) { | ||||
*os << "NULL"; | ||||
} else { | ||||
// T is not a function type. We just call << to print p, | ||||
// relying on ADL to pick up user-defined << for their pointer | ||||
// types, if any. | ||||
*os << p; | ||||
} | ||||
} | ||||
template <typename T> | ||||
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */, | ||||
T* p, ::std::ostream* os) { | ||||
if (p == nullptr) { | ||||
*os << "NULL"; | ||||
} else { | ||||
// T is a function type, so '*os << p' doesn't do what we want | ||||
// (it just prints p as bool). We want to print p as a const | ||||
// void*. | ||||
*os << reinterpret_cast<const void*>(p); | ||||
} | ||||
} | ||||
// Used to print a non-container, non-pointer value when the user | ||||
// doesn't define PrintTo() for it. | ||||
template <typename T> | ||||
void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */, | ||||
const T& value, ::std::ostream* os) { | ||||
::testing_internal::DefaultPrintNonContainerTo(value, os); | ||||
} | ||||
// Prints the given value using the << operator if it has one; | // Prints the given value using the << operator if it has one; | |||
// otherwise prints the bytes in it. This is what | // otherwise prints the bytes in it. This is what | |||
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized | // UniversalPrinter<T>::Print() does when PrintTo() is not specialized | |||
// or overloaded for type T. | // or overloaded for type T. | |||
// | // | |||
// A user can override this behavior for a class type Foo by defining | // A user can override this behavior for a class type Foo by defining | |||
// an overload of PrintTo() in the namespace where Foo is defined. We | // an overload of PrintTo() in the namespace where Foo is defined. We | |||
// give the user this option as sometimes defining a << operator for | // give the user this option as sometimes defining a << operator for | |||
// Foo is not desirable (e.g. the coding style may prevent doing it, | // Foo is not desirable (e.g. the coding style may prevent doing it, | |||
// or there is already a << operator but it doesn't do what the user | // or there is already a << operator but it doesn't do what the user | |||
// wants). | // wants). | |||
template <typename T> | template <typename T> | |||
void PrintTo(const T& value, ::std::ostream* os) { | void PrintTo(const T& value, ::std::ostream* os) { | |||
// DefaultPrintTo() is overloaded. The type of its first argument | internal::PrintWithFallback(value, os); | |||
// determines which version will be picked. | ||||
// | ||||
// Note that we check for container types here, prior to we check | ||||
// for protocol message types in our operator<<. The rationale is: | ||||
// | ||||
// For protocol messages, we want to give people a chance to | ||||
// override Google Mock's format by defining a PrintTo() or | ||||
// operator<<. For STL containers, other formats can be | ||||
// incompatible with Google Mock's format for the container | ||||
// elements; therefore we check for container types here to ensure | ||||
// that our format is used. | ||||
// | ||||
// Note that MSVC and clang-cl do allow an implicit conversion from | ||||
// pointer-to-function to pointer-to-object, but clang-cl warns on it. | ||||
// So don't use ImplicitlyConvertible if it can be helped since it will | ||||
// cause this warning, and use a separate overload of DefaultPrintTo for | ||||
// function pointers so that the `*os << p` in the object pointer overload | ||||
// doesn't cause that warning either. | ||||
DefaultPrintTo( | ||||
WrapPrinterType < | ||||
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && | ||||
!IsRecursiveContainer<T>::value | ||||
? kPrintContainer | ||||
: !std::is_pointer<T>::value | ||||
? kPrintOther | ||||
: std::is_function<typename std::remove_pointer<T>::type>::value | ||||
? kPrintFunctionPointer | ||||
: kPrintPointer > (), | ||||
value, os); | ||||
} | } | |||
// The following list of PrintTo() overloads tells | // The following list of PrintTo() overloads tells | |||
// UniversalPrinter<T>::Print() how to print standard types (built-in | // UniversalPrinter<T>::Print() how to print standard types (built-in | |||
// types, strings, plain arrays, and pointers). | // types, strings, plain arrays, and pointers). | |||
// Overloads for various char types. | // Overloads for various char types. | |||
GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); | GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); | |||
GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); | GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); | |||
inline void PrintTo(char c, ::std::ostream* os) { | inline void PrintTo(char c, ::std::ostream* os) { | |||
skipping to change at line 543 | skipping to change at line 470 | |||
// Overload for wchar_t type. | // Overload for wchar_t type. | |||
// Prints a wchar_t as a symbol if it is printable or as its internal | // Prints a wchar_t as a symbol if it is printable or as its internal | |||
// code otherwise and also as its decimal code (except for L'\0'). | // code otherwise and also as its decimal code (except for L'\0'). | |||
// The L'\0' char is printed as "L'\\0'". The decimal code is printed | // The L'\0' char is printed as "L'\\0'". The decimal code is printed | |||
// as signed integer when wchar_t is implemented by the compiler | // as signed integer when wchar_t is implemented by the compiler | |||
// as a signed type and is printed as an unsigned integer when wchar_t | // as a signed type and is printed as an unsigned integer when wchar_t | |||
// is implemented as an unsigned type. | // is implemented as an unsigned type. | |||
GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); | GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); | |||
GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os); | ||||
inline void PrintTo(char16_t c, ::std::ostream* os) { | ||||
PrintTo(ImplicitCast_<char32_t>(c), os); | ||||
} | ||||
#ifdef __cpp_char8_t | ||||
inline void PrintTo(char8_t c, ::std::ostream* os) { | ||||
PrintTo(ImplicitCast_<char32_t>(c), os); | ||||
} | ||||
#endif | ||||
// Overloads for C strings. | // Overloads for C strings. | |||
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); | GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); | |||
inline void PrintTo(char* s, ::std::ostream* os) { | inline void PrintTo(char* s, ::std::ostream* os) { | |||
PrintTo(ImplicitCast_<const char*>(s), os); | PrintTo(ImplicitCast_<const char*>(s), os); | |||
} | } | |||
// signed/unsigned char is often used for representing binary data, so | // signed/unsigned char is often used for representing binary data, so | |||
// we print pointers to it as void* to be safe. | // we print pointers to it as void* to be safe. | |||
inline void PrintTo(const signed char* s, ::std::ostream* os) { | inline void PrintTo(const signed char* s, ::std::ostream* os) { | |||
PrintTo(ImplicitCast_<const void*>(s), os); | PrintTo(ImplicitCast_<const void*>(s), os); | |||
} | } | |||
inline void PrintTo(signed char* s, ::std::ostream* os) { | inline void PrintTo(signed char* s, ::std::ostream* os) { | |||
PrintTo(ImplicitCast_<const void*>(s), os); | PrintTo(ImplicitCast_<const void*>(s), os); | |||
} | } | |||
inline void PrintTo(const unsigned char* s, ::std::ostream* os) { | inline void PrintTo(const unsigned char* s, ::std::ostream* os) { | |||
PrintTo(ImplicitCast_<const void*>(s), os); | PrintTo(ImplicitCast_<const void*>(s), os); | |||
} | } | |||
inline void PrintTo(unsigned char* s, ::std::ostream* os) { | inline void PrintTo(unsigned char* s, ::std::ostream* os) { | |||
PrintTo(ImplicitCast_<const void*>(s), os); | PrintTo(ImplicitCast_<const void*>(s), os); | |||
} | } | |||
#ifdef __cpp_char8_t | ||||
// Overloads for u8 strings. | ||||
GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os); | ||||
inline void PrintTo(char8_t* s, ::std::ostream* os) { | ||||
PrintTo(ImplicitCast_<const char8_t*>(s), os); | ||||
} | ||||
#endif | ||||
// Overloads for u16 strings. | ||||
GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os); | ||||
inline void PrintTo(char16_t* s, ::std::ostream* os) { | ||||
PrintTo(ImplicitCast_<const char16_t*>(s), os); | ||||
} | ||||
// Overloads for u32 strings. | ||||
GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os); | ||||
inline void PrintTo(char32_t* s, ::std::ostream* os) { | ||||
PrintTo(ImplicitCast_<const char32_t*>(s), os); | ||||
} | ||||
// MSVC can be configured to define wchar_t as a typedef of unsigned | // MSVC can be configured to define wchar_t as a typedef of unsigned | |||
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native | // short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native | |||
// type. When wchar_t is a typedef, defining an overload for const | // type. When wchar_t is a typedef, defining an overload for const | |||
// wchar_t* would cause unsigned short* be printed as a wide string, | // wchar_t* would cause unsigned short* be printed as a wide string, | |||
// possibly causing invalid memory accesses. | // possibly causing invalid memory accesses. | |||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) | #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) | |||
// Overloads for wide C strings | // Overloads for wide C strings | |||
GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); | GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); | |||
inline void PrintTo(wchar_t* s, ::std::ostream* os) { | inline void PrintTo(wchar_t* s, ::std::ostream* os) { | |||
skipping to change at line 597 | skipping to change at line 551 | |||
UniversalPrint(a[i], os); | UniversalPrint(a[i], os); | |||
} | } | |||
} | } | |||
// Overloads for ::std::string. | // Overloads for ::std::string. | |||
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); | GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); | |||
inline void PrintTo(const ::std::string& s, ::std::ostream* os) { | inline void PrintTo(const ::std::string& s, ::std::ostream* os) { | |||
PrintStringTo(s, 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. | // Overloads for ::std::wstring. | |||
#if GTEST_HAS_STD_WSTRING | #if GTEST_HAS_STD_WSTRING | |||
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); | GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); | |||
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { | inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { | |||
PrintWideStringTo(s, os); | PrintWideStringTo(s, os); | |||
} | } | |||
#endif // GTEST_HAS_STD_WSTRING | #endif // GTEST_HAS_STD_WSTRING | |||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Overload for absl::string_view. | // Overload for internal::StringView. | |||
inline void PrintTo(absl::string_view sp, ::std::ostream* os) { | inline void PrintTo(internal::StringView sp, ::std::ostream* os) { | |||
PrintTo(::std::string(sp), os); | PrintTo(::std::string(sp), os); | |||
} | } | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } | inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } | |||
template <typename T> | template <typename T> | |||
void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) { | void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) { | |||
UniversalPrinter<T&>::Print(ref.get(), os); | UniversalPrinter<T&>::Print(ref.get(), os); | |||
} | } | |||
inline const void* VoidifyPointer(const void* p) { return p; } | ||||
inline const void* VoidifyPointer(volatile const void* p) { | ||||
return const_cast<const void*>(p); | ||||
} | ||||
template <typename T, typename Ptr> | ||||
void PrintSmartPointer(const Ptr& ptr, std::ostream* os, char) { | ||||
if (ptr == nullptr) { | ||||
*os << "(nullptr)"; | ||||
} else { | ||||
// We can't print the value. Just print the pointer.. | ||||
*os << "(" << (VoidifyPointer)(ptr.get()) << ")"; | ||||
} | ||||
} | ||||
template <typename T, typename Ptr, | ||||
typename = typename std::enable_if<!std::is_void<T>::value && | ||||
!std::is_array<T>::value>::type> | ||||
void PrintSmartPointer(const Ptr& ptr, std::ostream* os, int) { | ||||
if (ptr == nullptr) { | ||||
*os << "(nullptr)"; | ||||
} else { | ||||
*os << "(ptr = " << (VoidifyPointer)(ptr.get()) << ", value = "; | ||||
UniversalPrinter<T>::Print(*ptr, os); | ||||
*os << ")"; | ||||
} | ||||
} | ||||
template <typename T, typename D> | ||||
void PrintTo(const std::unique_ptr<T, D>& ptr, std::ostream* os) { | ||||
(PrintSmartPointer<T>)(ptr, os, 0); | ||||
} | ||||
template <typename T> | ||||
void PrintTo(const std::shared_ptr<T>& ptr, std::ostream* os) { | ||||
(PrintSmartPointer<T>)(ptr, os, 0); | ||||
} | ||||
// Helper function for printing a tuple. T must be instantiated with | // Helper function for printing a tuple. T must be instantiated with | |||
// a tuple type. | // a tuple type. | |||
template <typename T> | template <typename T> | |||
void PrintTupleTo(const T&, std::integral_constant<size_t, 0>, | void PrintTupleTo(const T&, std::integral_constant<size_t, 0>, | |||
::std::ostream*) {} | ::std::ostream*) {} | |||
template <typename T, size_t I> | template <typename T, size_t I> | |||
void PrintTupleTo(const T& t, std::integral_constant<size_t, I>, | void PrintTupleTo(const T& t, std::integral_constant<size_t, I>, | |||
::std::ostream* os) { | ::std::ostream* os) { | |||
PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os); | PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os); | |||
skipping to change at line 684 | skipping to change at line 695 | |||
// PrintTo() function defined in its namespace, that function will | // PrintTo() function defined in its namespace, that function will | |||
// be visible here. Since it is more specific than the generic ones | // be visible here. Since it is more specific than the generic ones | |||
// in ::testing::internal, it will be picked by the compiler in the | // in ::testing::internal, it will be picked by the compiler in the | |||
// following statement - exactly what we want. | // following statement - exactly what we want. | |||
PrintTo(value, os); | PrintTo(value, os); | |||
} | } | |||
GTEST_DISABLE_MSC_WARNINGS_POP_() | GTEST_DISABLE_MSC_WARNINGS_POP_() | |||
}; | }; | |||
#if GTEST_HAS_ABSL | // Remove any const-qualifiers before passing a type to UniversalPrinter. | |||
template <typename T> | ||||
class UniversalPrinter<const T> : public UniversalPrinter<T> {}; | ||||
// Printer for absl::optional | #if GTEST_INTERNAL_HAS_ANY | |||
// Printer for std::any / absl::any | ||||
template <> | ||||
class UniversalPrinter<Any> { | ||||
public: | ||||
static void Print(const Any& value, ::std::ostream* os) { | ||||
if (value.has_value()) { | ||||
*os << "value of type " << GetTypeName(value); | ||||
} else { | ||||
*os << "no value"; | ||||
} | ||||
} | ||||
private: | ||||
static std::string GetTypeName(const Any& value) { | ||||
#if GTEST_HAS_RTTI | ||||
return internal::GetTypeName(value.type()); | ||||
#else | ||||
static_cast<void>(value); // possibly unused | ||||
return "<unknown_type>"; | ||||
#endif // GTEST_HAS_RTTI | ||||
} | ||||
}; | ||||
#endif // GTEST_INTERNAL_HAS_ANY | ||||
#if GTEST_INTERNAL_HAS_OPTIONAL | ||||
// Printer for std::optional / absl::optional | ||||
template <typename T> | template <typename T> | |||
class UniversalPrinter<::absl::optional<T>> { | class UniversalPrinter<Optional<T>> { | |||
public: | public: | |||
static void Print(const ::absl::optional<T>& value, ::std::ostream* os) { | static void Print(const Optional<T>& value, ::std::ostream* os) { | |||
*os << '('; | *os << '('; | |||
if (!value) { | if (!value) { | |||
*os << "nullopt"; | *os << "nullopt"; | |||
} else { | } else { | |||
UniversalPrint(*value, os); | UniversalPrint(*value, os); | |||
} | } | |||
*os << ')'; | *os << ')'; | |||
} | } | |||
}; | }; | |||
// Printer for absl::variant | #endif // GTEST_INTERNAL_HAS_OPTIONAL | |||
#if GTEST_INTERNAL_HAS_VARIANT | ||||
// Printer for std::variant / absl::variant | ||||
template <typename... T> | template <typename... T> | |||
class UniversalPrinter<::absl::variant<T...>> { | class UniversalPrinter<Variant<T...>> { | |||
public: | public: | |||
static void Print(const ::absl::variant<T...>& value, ::std::ostream* os) { | static void Print(const Variant<T...>& value, ::std::ostream* os) { | |||
*os << '('; | *os << '('; | |||
absl::visit(Visitor{os}, value); | #if GTEST_HAS_ABSL | |||
absl::visit(Visitor{os, value.index()}, value); | ||||
#else | ||||
std::visit(Visitor{os, value.index()}, value); | ||||
#endif // GTEST_HAS_ABSL | ||||
*os << ')'; | *os << ')'; | |||
} | } | |||
private: | private: | |||
struct Visitor { | struct Visitor { | |||
template <typename U> | template <typename U> | |||
void operator()(const U& u) const { | void operator()(const U& u) const { | |||
*os << "'" << GetTypeName<U>() << "' with value "; | *os << "'" << GetTypeName<U>() << "(index = " << index | |||
<< ")' with value "; | ||||
UniversalPrint(u, os); | UniversalPrint(u, os); | |||
} | } | |||
::std::ostream* os; | ::std::ostream* os; | |||
std::size_t index; | ||||
}; | }; | |||
}; | }; | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_VARIANT | |||
// UniversalPrintArray(begin, len, os) prints an array of 'len' | // UniversalPrintArray(begin, len, os) prints an array of 'len' | |||
// elements, starting at address 'begin'. | // elements, starting at address 'begin'. | |||
template <typename T> | template <typename T> | |||
void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { | void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { | |||
if (len == 0) { | if (len == 0) { | |||
*os << "{}"; | *os << "{}"; | |||
} else { | } else { | |||
*os << "{ "; | *os << "{ "; | |||
const size_t kThreshold = 18; | const size_t kThreshold = 18; | |||
skipping to change at line 753 | skipping to change at line 806 | |||
*os << ", ..., "; | *os << ", ..., "; | |||
PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); | PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); | |||
} | } | |||
*os << " }"; | *os << " }"; | |||
} | } | |||
} | } | |||
// This overload prints a (const) char array compactly. | // This overload prints a (const) char array compactly. | |||
GTEST_API_ void UniversalPrintArray( | GTEST_API_ void UniversalPrintArray( | |||
const char* begin, size_t len, ::std::ostream* os); | 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. | // This overload prints a (const) wchar_t array compactly. | |||
GTEST_API_ void UniversalPrintArray( | GTEST_API_ void UniversalPrintArray( | |||
const wchar_t* begin, size_t len, ::std::ostream* os); | const wchar_t* begin, size_t len, ::std::ostream* os); | |||
// Implements printing an array type T[N]. | // Implements printing an array type T[N]. | |||
template <typename T, size_t N> | template <typename T, size_t N> | |||
class UniversalPrinter<T[N]> { | class UniversalPrinter<T[N]> { | |||
public: | public: | |||
// Prints the given array, omitting some elements when there are too | // Prints the given array, omitting some elements when there are too | |||
// many. | // many. | |||
skipping to change at line 825 | skipping to change at line 892 | |||
public: | public: | |||
static void Print(const char* str, ::std::ostream* os) { | static void Print(const char* str, ::std::ostream* os) { | |||
if (str == nullptr) { | if (str == nullptr) { | |||
*os << "NULL"; | *os << "NULL"; | |||
} else { | } else { | |||
UniversalPrint(std::string(str), os); | UniversalPrint(std::string(str), os); | |||
} | } | |||
} | } | |||
}; | }; | |||
template <> | template <> | |||
class UniversalTersePrinter<char*> { | class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> { | |||
}; | ||||
#ifdef __cpp_char8_t | ||||
template <> | ||||
class UniversalTersePrinter<const char8_t*> { | ||||
public: | public: | |||
static void Print(char* str, ::std::ostream* os) { | static void Print(const char8_t* str, ::std::ostream* os) { | |||
UniversalTersePrinter<const char*>::Print(str, 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(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 | #if GTEST_HAS_STD_WSTRING | |||
template <> | template <> | |||
class UniversalTersePrinter<const wchar_t*> { | class UniversalTersePrinter<const wchar_t*> { | |||
public: | public: | |||
static void Print(const wchar_t* str, ::std::ostream* os) { | static void Print(const wchar_t* str, ::std::ostream* os) { | |||
if (str == nullptr) { | if (str == nullptr) { | |||
*os << "NULL"; | *os << "NULL"; | |||
} else { | } else { | |||
UniversalPrint(::std::wstring(str), os); | UniversalPrint(::std::wstring(str), os); | |||
skipping to change at line 903 | skipping to change at line 1013 | |||
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { | Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { | |||
Strings result; | Strings result; | |||
TersePrintPrefixToStrings( | TersePrintPrefixToStrings( | |||
value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(), | value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(), | |||
&result); | &result); | |||
return result; | return result; | |||
} | } | |||
} // namespace internal | } // namespace internal | |||
#if GTEST_HAS_ABSL | ||||
namespace internal2 { | ||||
template <typename T> | ||||
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue( | ||||
const T& value, ::std::ostream* os) { | ||||
internal::PrintTo(absl::string_view(value), os); | ||||
} | ||||
} // namespace internal2 | ||||
#endif | ||||
template <typename T> | template <typename T> | |||
::std::string PrintToString(const T& value) { | ::std::string PrintToString(const T& value) { | |||
::std::stringstream ss; | ::std::stringstream ss; | |||
internal::UniversalTersePrinter<T>::Print(value, &ss); | internal::UniversalTersePrinter<T>::Print(value, &ss); | |||
return ss.str(); | return ss.str(); | |||
} | } | |||
} // namespace testing | } // namespace testing | |||
// Include any custom printer added by the local installation. | // Include any custom printer added by the local installation. | |||
// We must include this header at the end to make sure it can use the | // We must include this header at the end to make sure it can use the | |||
// declarations from this file. | // declarations from this file. | |||
#include "gtest/internal/custom/gtest-printers.h" | #include "gtest/internal/custom/gtest-printers.h" | |||
#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ | #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ | |||
End of changes. 46 change blocks. | ||||
283 lines changed or deleted | 383 lines changed or added |