| Index: webrtc/base/optional.h
|
| diff --git a/webrtc/base/optional.h b/webrtc/base/optional.h
|
| index f5354ee0f25fdb6eabcf6fa367e3db64152681ee..c8ed069d55570b1f6bf5e7191bcf121626dd0a0b 100644
|
| --- a/webrtc/base/optional.h
|
| +++ b/webrtc/base/optional.h
|
| @@ -15,6 +15,11 @@
|
| #include <memory>
|
| #include <utility>
|
|
|
| +#ifdef UNIT_TEST
|
| +#include <iomanip>
|
| +#include <ostream>
|
| +#endif // UNIT_TEST
|
| +
|
| #include "webrtc/base/array_view.h"
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/base/sanitizer.h"
|
| @@ -25,7 +30,9 @@ namespace optional_internal {
|
|
|
| #if RTC_HAS_ASAN
|
|
|
| -// This is a non-inlined function. The optimizer can't see inside it.
|
| +// This is a non-inlined function. The optimizer can't see inside it. It
|
| +// prevents the compiler from generating optimized code that reads value_ even
|
| +// if it is unset. Although safe, this causes memory sanitizers to complain.
|
| void* FunctionThatDoesNothingImpl(void*);
|
|
|
| template <typename T>
|
| @@ -296,6 +303,98 @@ class Optional final {
|
| };
|
| };
|
|
|
| +#ifdef UNIT_TEST
|
| +namespace optional_internal {
|
| +
|
| +// Checks if there's a valid PrintTo(const T&, std::ostream*) call for T.
|
| +template <typename T>
|
| +struct HasPrintTo {
|
| + private:
|
| + struct No {};
|
| +
|
| + template <typename T2>
|
| + static auto Test(const T2& obj)
|
| + -> decltype(PrintTo(obj, std::declval<std::ostream*>()));
|
| +
|
| + template <typename>
|
| + static No Test(...);
|
| +
|
| + public:
|
| + static constexpr bool value =
|
| + !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
|
| +};
|
| +
|
| +// Checks if there's a valid operator<<(std::ostream&, const T&) call for T.
|
| +template <typename T>
|
| +struct HasOstreamOperator {
|
| + private:
|
| + struct No {};
|
| +
|
| + template <typename T2>
|
| + static auto Test(const T2& obj)
|
| + -> decltype(std::declval<std::ostream&>() << obj);
|
| +
|
| + template <typename>
|
| + static No Test(...);
|
| +
|
| + public:
|
| + static constexpr bool value =
|
| + !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
|
| +};
|
| +
|
| +// Prefer using PrintTo to print the object.
|
| +template <typename T>
|
| +typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper(
|
| + const T& value,
|
| + std::ostream* os) {
|
| + PrintTo(value, os);
|
| +}
|
| +
|
| +// Fall back to operator<<(std::ostream&, ...) if it exists.
|
| +template <typename T>
|
| +typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
|
| + void>::type
|
| +OptionalPrintToHelper(const T& value, std::ostream* os) {
|
| + *os << value;
|
| +}
|
| +
|
| +inline void OptionalPrintObjectBytes(const unsigned char* bytes,
|
| + size_t size,
|
| + std::ostream* os) {
|
| + *os << "<optional with " << size << "-byte object [";
|
| + for (size_t i = 0; i != size; ++i) {
|
| + *os << (i == 0 ? "" : ((i & 1) ? "-" : " "));
|
| + *os << std::hex << std::setw(2) << std::setfill('0')
|
| + << static_cast<int>(bytes[i]);
|
| + }
|
| + *os << "]>";
|
| +}
|
| +
|
| +// As a final back-up, just print the contents of the objcets byte-wise.
|
| +template <typename T>
|
| +typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
|
| + void>::type
|
| +OptionalPrintToHelper(const T& value, std::ostream* os) {
|
| + OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value),
|
| + sizeof(value), os);
|
| +}
|
| +
|
| +} // namespace optional_internal
|
| +
|
| +// PrintTo is used by gtest to print out the results of tests. We want to ensure
|
| +// the object contained in an Optional can be printed out if it's set, while
|
| +// avoiding touching the object's storage if it is undefined.
|
| +template <typename T>
|
| +void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) {
|
| + if (opt) {
|
| + optional_internal::OptionalPrintToHelper(*opt, os);
|
| + } else {
|
| + *os << "<empty optional>";
|
| + }
|
| +}
|
| +
|
| +#endif // UNIT_TEST
|
| +
|
| } // namespace rtc
|
|
|
| #endif // WEBRTC_BASE_OPTIONAL_H_
|
|
|