Allow log print of data units.

Bug: webrtc:9709
Change-Id: I5987a9779e645115dc1893944302a73d540bcf2f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/125680
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27578}
This commit is contained in:
Sebastian Jansson
2019-04-11 16:48:15 +02:00
committed by Commit Bot
parent 4d7160e41d
commit b113862ccd
8 changed files with 65 additions and 8 deletions

View File

@ -85,6 +85,7 @@ if (rtc_include_tests) {
":data_size", ":data_size",
":time_delta", ":time_delta",
":timestamp", ":timestamp",
"../../rtc_base:logging",
"../../test:test_support", "../../test:test_support",
] ]
} }

View File

@ -107,6 +107,9 @@ inline DataSize operator*(const TimeDelta duration, const DataRate rate) {
} }
std::string ToString(DataRate value); std::string ToString(DataRate value);
inline std::string ToLogString(DataRate value) {
return ToString(value);
}
#ifdef UNIT_TEST #ifdef UNIT_TEST
inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982)

View File

@ -9,11 +9,19 @@
*/ */
#include "api/units/data_rate.h" #include "api/units/data_rate.h"
#include "rtc_base/logging.h"
#include "test/gtest.h" #include "test/gtest.h"
namespace webrtc { namespace webrtc {
namespace test { namespace test {
TEST(DataRateTest, CompilesWithChecksAndLogs) {
DataRate a = DataRate::kbps(300);
DataRate b = DataRate::kbps(210);
RTC_CHECK_GT(a, b);
RTC_LOG(LS_INFO) << a;
}
TEST(DataRateTest, ConstExpr) { TEST(DataRateTest, ConstExpr) {
constexpr int64_t kValue = 12345; constexpr int64_t kValue = 12345;
constexpr DataRate kDataRateZero = DataRate::Zero(); constexpr DataRate kDataRateZero = DataRate::Zero();

View File

@ -52,6 +52,9 @@ class DataSize final : public rtc_units_impl::RelativeUnit<DataSize> {
}; };
std::string ToString(DataSize value); std::string ToString(DataSize value);
inline std::string ToLogString(DataSize value) {
return ToString(value);
}
#ifdef UNIT_TEST #ifdef UNIT_TEST
inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982)

View File

@ -95,6 +95,9 @@ class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
}; };
std::string ToString(TimeDelta value); std::string ToString(TimeDelta value);
inline std::string ToLogString(TimeDelta value) {
return ToString(value);
}
#ifdef UNIT_TEST #ifdef UNIT_TEST
inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982)

View File

@ -133,6 +133,9 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
}; };
std::string ToString(Timestamp value); std::string ToString(Timestamp value);
inline std::string ToLogString(Timestamp value) {
return ToString(value);
}
#ifdef UNIT_TEST #ifdef UNIT_TEST
inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982)

View File

@ -125,6 +125,15 @@ struct Val {
T val; T val;
}; };
// Case for when we need to construct a temp string and then print that.
// (We can't use Val<CheckArgType::kStdString, const std::string*>
// because we need somewhere to store the temp string.)
struct ToStringVal {
static constexpr CheckArgType Type() { return CheckArgType::kStdString; }
const std::string* GetVal() const { return &val; }
std::string val;
};
inline Val<CheckArgType::kInt, int> MakeVal(int x) { inline Val<CheckArgType::kInt, int> MakeVal(int x) {
return {x}; return {x};
} }
@ -178,6 +187,15 @@ MakeVal(T x) {
return {static_cast<typename std::underlying_type<T>::type>(x)}; return {static_cast<typename std::underlying_type<T>::type>(x)};
} }
template <typename T,
typename T1 = typename std::decay<T>::type,
typename T2 = decltype(ToLogString(std::declval<T>())),
typename std::enable_if<std::is_same<T2, std::string>::value>::type* =
nullptr>
ToStringVal MakeVal(const T& x) {
return {ToLogString(x)};
}
// Ephemeral type that represents the result of the logging << operator. // Ephemeral type that represents the result of the logging << operator.
template <typename... Ts> template <typename... Ts>
class LogStreamer; class LogStreamer;

View File

@ -186,11 +186,10 @@ struct Val {
T val; T val;
}; };
// TODO(bugs.webrtc.org/9278): Get rid of this specialization when callers // Case for when we need to construct a temp string and then print that.
// don't need it anymore. No in-tree caller does, but some external callers // (We can't use Val<CheckArgType::kStdString, const std::string*>
// still do. // because we need somewhere to store the temp string.)
template <> struct ToStringVal {
struct Val<LogArgType::kStdString, std::string> {
static constexpr LogArgType Type() { return LogArgType::kStdString; } static constexpr LogArgType Type() { return LogArgType::kStdString; }
const std::string* GetVal() const { return &val; } const std::string* GetVal() const { return &val; }
std::string val; std::string val;
@ -265,26 +264,45 @@ inline Val<LogArgType::kLogMetadataTag, LogMetadataTag> MakeVal(
} }
#endif #endif
template <typename T, typename = void>
struct has_to_log_string : std::false_type {};
template <typename T>
struct has_to_log_string<
T,
typename std::enable_if<
std::is_same<std::string,
decltype(ToLogString(std::declval<T>()))>::value>::type>
: std::true_type {};
// Handle arbitrary types other than the above by falling back to stringstream. // Handle arbitrary types other than the above by falling back to stringstream.
// TODO(bugs.webrtc.org/9278): Get rid of this overload when callers don't need // TODO(bugs.webrtc.org/9278): Get rid of this overload when callers don't need
// it anymore. No in-tree caller does, but some external callers still do. // it anymore. No in-tree caller does, but some external callers still do.
template < template <
typename T, typename T,
typename T1 = typename T1 = typename std::decay<T>::type,
typename std::remove_cv<typename std::remove_reference<T>::type>::type,
typename std::enable_if< typename std::enable_if<
std::is_class<T1>::value && !std::is_same<T1, std::string>::value && std::is_class<T1>::value && !std::is_same<T1, std::string>::value &&
!std::is_same<T1, LogMetadata>::value && !std::is_same<T1, LogMetadata>::value &&
!has_to_log_string<T1>::value &&
#ifdef WEBRTC_ANDROID #ifdef WEBRTC_ANDROID
!std::is_same<T1, LogMetadataTag>::value && !std::is_same<T1, LogMetadataTag>::value &&
#endif #endif
!std::is_same<T1, LogMetadataErr>::value>::type* = nullptr> !std::is_same<T1, LogMetadataErr>::value>::type* = nullptr>
Val<LogArgType::kStdString, std::string> MakeVal(const T& x) { ToStringVal MakeVal(const T& x) {
std::ostringstream os; // no-presubmit-check TODO(webrtc:8982) std::ostringstream os; // no-presubmit-check TODO(webrtc:8982)
os << x; os << x;
return {os.str()}; return {os.str()};
} }
template <
typename T,
typename T1 = typename std::decay<T>::type,
typename std::enable_if<std::is_class<T1>::value &&
has_to_log_string<T1>::value>::type* = nullptr>
ToStringVal MakeVal(const T& x) {
return {ToLogString(x)};
}
void Log(const LogArgType* fmt, ...); void Log(const LogArgType* fmt, ...);
// Ephemeral type that represents the result of the logging << operator. // Ephemeral type that represents the result of the logging << operator.