From e638ada5c9212bd057de11022afb0cf22418bcd5 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Mon, 17 Feb 2020 15:00:07 +0100 Subject: [PATCH] Add DataSize and DataRate factories Bug: webrtc:9709 Change-Id: I8a3af8c62f7ed52de84efb8b1306701fa2e40278 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168606 Commit-Queue: Danil Chapovalov Reviewed-by: Sebastian Jansson Cr-Commit-Position: refs/heads/master@{#30533} --- api/units/data_rate.h | 28 ++++++++++--- api/units/data_rate_unittest.cc | 70 ++++++++++++++++----------------- api/units/data_size.h | 10 ++++- api/units/data_size_unittest.cc | 31 ++++++++------- 4 files changed, 84 insertions(+), 55 deletions(-) diff --git a/api/units/data_rate.h b/api/units/data_rate.h index 46c6d0fbbc..f83b9a1da4 100644 --- a/api/units/data_rate.h +++ b/api/units/data_rate.h @@ -31,8 +31,26 @@ namespace webrtc { // second (bps). class DataRate final : public rtc_units_impl::RelativeUnit { public: - DataRate() = delete; + template + static constexpr DataRate BitsPerSec(T value) { + static_assert(std::is_arithmetic::value, ""); + return FromValue(value); + } + template + static constexpr DataRate BytesPerSec(T value) { + static_assert(std::is_arithmetic::value, ""); + return FromFraction(8, value); + } + template + static constexpr DataRate KilobitsPerSec(T value) { + static_assert(std::is_arithmetic::value, ""); + return FromFraction(1000, value); + } static constexpr DataRate Infinity() { return PlusInfinity(); } + + DataRate() = delete; + // TODO(danilchap): Migrate all code to the 3 factories above and delete the + // 5 factories below. template static constexpr DataRate BitsPerSec() { return FromValue(bps); @@ -103,7 +121,7 @@ inline constexpr int64_t MillibytePerSec(const DataRate& size) { inline constexpr DataRate operator/(const DataSize size, const TimeDelta duration) { - return DataRate::bps(data_rate_impl::Microbits(size) / duration.us()); + return DataRate::BitsPerSec(data_rate_impl::Microbits(size) / duration.us()); } inline constexpr TimeDelta operator/(const DataSize size, const DataRate rate) { return TimeDelta::Micros(data_rate_impl::Microbits(size) / rate.bps()); @@ -111,7 +129,7 @@ inline constexpr TimeDelta operator/(const DataSize size, const DataRate rate) { inline constexpr DataSize operator*(const DataRate rate, const TimeDelta duration) { int64_t microbits = rate.bps() * duration.us(); - return DataSize::bytes((microbits + 4000000) / 8000000); + return DataSize::Bytes((microbits + 4000000) / 8000000); } inline constexpr DataSize operator*(const TimeDelta duration, const DataRate rate) { @@ -123,7 +141,7 @@ inline constexpr DataSize operator/(const DataRate rate, int64_t millihertz = frequency.millihertz(); // Note that the value is truncated here reather than rounded, potentially // introducing an error of .5 bytes if rounding were expected. - return DataSize::bytes(data_rate_impl::MillibytePerSec(rate) / millihertz); + return DataSize::Bytes(data_rate_impl::MillibytePerSec(rate) / millihertz); } inline constexpr Frequency operator/(const DataRate rate, const DataSize size) { return Frequency::MilliHertz(data_rate_impl::MillibytePerSec(rate) / @@ -136,7 +154,7 @@ inline constexpr DataRate operator*(const DataSize size, frequency.millihertz()); int64_t millibits_per_second = size.bytes() * 8 * frequency.millihertz(); - return DataRate::bps((millibits_per_second + 500) / 1000); + return DataRate::BitsPerSec((millibits_per_second + 500) / 1000); } inline constexpr DataRate operator*(const Frequency frequency, const DataSize size) { diff --git a/api/units/data_rate_unittest.cc b/api/units/data_rate_unittest.cc index 80b9f7b593..4a6dd21af3 100644 --- a/api/units/data_rate_unittest.cc +++ b/api/units/data_rate_unittest.cc @@ -17,8 +17,8 @@ namespace webrtc { namespace test { TEST(DataRateTest, CompilesWithChecksAndLogs) { - DataRate a = DataRate::kbps(300); - DataRate b = DataRate::kbps(210); + DataRate a = DataRate::KilobitsPerSec(300); + DataRate b = DataRate::KilobitsPerSec(210); RTC_CHECK_GT(a, b); RTC_LOG(LS_INFO) << a; } @@ -32,8 +32,8 @@ TEST(DataRateTest, ConstExpr) { static_assert(kDataRateInf.bps_or(-1) == -1, ""); static_assert(kDataRateInf > kDataRateZero, ""); - constexpr DataRate kDataRateBps = DataRate::BitsPerSec(); - constexpr DataRate kDataRateKbps = DataRate::KilobitsPerSec(); + constexpr DataRate kDataRateBps = DataRate::BitsPerSec(kValue); + constexpr DataRate kDataRateKbps = DataRate::KilobitsPerSec(kValue); static_assert(kDataRateBps.bps() == kValue, ""); static_assert(kDataRateBps.bps_or(0) == kValue, ""); static_assert(kDataRateKbps.kbps_or(0) == kValue, ""); @@ -41,36 +41,36 @@ TEST(DataRateTest, ConstExpr) { TEST(DataRateTest, GetBackSameValues) { const int64_t kValue = 123 * 8; - EXPECT_EQ(DataRate::bps(kValue).bps(), kValue); - EXPECT_EQ(DataRate::kbps(kValue).kbps(), kValue); + EXPECT_EQ(DataRate::BitsPerSec(kValue).bps(), kValue); + EXPECT_EQ(DataRate::KilobitsPerSec(kValue).kbps(), kValue); } TEST(DataRateTest, GetDifferentPrefix) { const int64_t kValue = 123 * 8000; - EXPECT_EQ(DataRate::bps(kValue).kbps(), kValue / 1000); + EXPECT_EQ(DataRate::BitsPerSec(kValue).kbps(), kValue / 1000); } TEST(DataRateTest, IdentityChecks) { const int64_t kValue = 3000; EXPECT_TRUE(DataRate::Zero().IsZero()); - EXPECT_FALSE(DataRate::bps(kValue).IsZero()); + EXPECT_FALSE(DataRate::BitsPerSec(kValue).IsZero()); EXPECT_TRUE(DataRate::Infinity().IsInfinite()); EXPECT_FALSE(DataRate::Zero().IsInfinite()); - EXPECT_FALSE(DataRate::bps(kValue).IsInfinite()); + EXPECT_FALSE(DataRate::BitsPerSec(kValue).IsInfinite()); EXPECT_FALSE(DataRate::Infinity().IsFinite()); - EXPECT_TRUE(DataRate::bps(kValue).IsFinite()); + EXPECT_TRUE(DataRate::BitsPerSec(kValue).IsFinite()); EXPECT_TRUE(DataRate::Zero().IsFinite()); } TEST(DataRateTest, ComparisonOperators) { const int64_t kSmall = 450; const int64_t kLarge = 451; - const DataRate small = DataRate::bps(kSmall); - const DataRate large = DataRate::bps(kLarge); + const DataRate small = DataRate::BitsPerSec(kSmall); + const DataRate large = DataRate::BitsPerSec(kLarge); - EXPECT_EQ(DataRate::Zero(), DataRate::bps(0)); + EXPECT_EQ(DataRate::Zero(), DataRate::BitsPerSec(0)); EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity()); EXPECT_EQ(small, small); EXPECT_LE(small, small); @@ -90,23 +90,23 @@ TEST(DataRateTest, ConvertsToAndFromDouble) { const double kDoubleKbps = kValue * 1e-3; const double kFloatKbps = static_cast(kDoubleKbps); - EXPECT_EQ(DataRate::bps(kValue).bps(), kDoubleValue); - EXPECT_EQ(DataRate::bps(kValue).kbps(), kDoubleKbps); - EXPECT_EQ(DataRate::bps(kValue).kbps(), kFloatKbps); - EXPECT_EQ(DataRate::bps(kDoubleValue).bps(), kValue); - EXPECT_EQ(DataRate::kbps(kDoubleKbps).bps(), kValue); + EXPECT_EQ(DataRate::BitsPerSec(kValue).bps(), kDoubleValue); + EXPECT_EQ(DataRate::BitsPerSec(kValue).kbps(), kDoubleKbps); + EXPECT_EQ(DataRate::BitsPerSec(kValue).kbps(), kFloatKbps); + EXPECT_EQ(DataRate::BitsPerSec(kDoubleValue).bps(), kValue); + EXPECT_EQ(DataRate::KilobitsPerSec(kDoubleKbps).bps(), kValue); const double kInfinity = std::numeric_limits::infinity(); EXPECT_EQ(DataRate::Infinity().bps(), kInfinity); - EXPECT_TRUE(DataRate::bps(kInfinity).IsInfinite()); - EXPECT_TRUE(DataRate::kbps(kInfinity).IsInfinite()); + EXPECT_TRUE(DataRate::BitsPerSec(kInfinity).IsInfinite()); + EXPECT_TRUE(DataRate::KilobitsPerSec(kInfinity).IsInfinite()); } TEST(DataRateTest, Clamping) { - const DataRate upper = DataRate::kbps(800); - const DataRate lower = DataRate::kbps(100); - const DataRate under = DataRate::kbps(100); - const DataRate inside = DataRate::kbps(500); - const DataRate over = DataRate::kbps(1000); + const DataRate upper = DataRate::KilobitsPerSec(800); + const DataRate lower = DataRate::KilobitsPerSec(100); + const DataRate under = DataRate::KilobitsPerSec(100); + const DataRate inside = DataRate::KilobitsPerSec(500); + const DataRate over = DataRate::KilobitsPerSec(1000); EXPECT_EQ(under.Clamped(lower, upper), lower); EXPECT_EQ(inside.Clamped(lower, upper), inside); EXPECT_EQ(over.Clamped(lower, upper), upper); @@ -125,8 +125,8 @@ TEST(DataRateTest, Clamping) { TEST(DataRateTest, MathOperations) { const int64_t kValueA = 450; const int64_t kValueB = 267; - const DataRate rate_a = DataRate::bps(kValueA); - const DataRate rate_b = DataRate::bps(kValueB); + const DataRate rate_a = DataRate::BitsPerSec(kValueA); + const DataRate rate_b = DataRate::BitsPerSec(kValueB); const int32_t kInt32Value = 123; const double kFloatValue = 123.0; @@ -142,7 +142,7 @@ TEST(DataRateTest, MathOperations) { EXPECT_EQ((rate_a / 10).bps(), kValueA / 10); EXPECT_NEAR((rate_a / 0.5).bps(), kValueA * 2, 1); - DataRate mutable_rate = DataRate::bps(kValueA); + DataRate mutable_rate = DataRate::BitsPerSec(kValueA); mutable_rate += rate_b; EXPECT_EQ(mutable_rate.bps(), kValueA + kValueB); mutable_rate -= rate_a; @@ -154,8 +154,8 @@ TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) { const int64_t kBitsPerSecond = 440; const int64_t kBytes = 44000; const TimeDelta delta_a = TimeDelta::Seconds(kSeconds); - const DataRate rate_b = DataRate::bps(kBitsPerSecond); - const DataSize size_c = DataSize::bytes(kBytes); + const DataRate rate_b = DataRate::BitsPerSec(kBitsPerSecond); + const DataSize size_c = DataSize::Bytes(kBytes); EXPECT_EQ((delta_a * rate_b).bytes(), kSeconds * kBitsPerSecond / 8); EXPECT_EQ((rate_b * delta_a).bytes(), kSeconds * kBitsPerSecond / 8); EXPECT_EQ((size_c / delta_a).bps(), kBytes * 8 / kSeconds); @@ -167,8 +167,8 @@ TEST(UnitConversionTest, DataRateAndDataSizeAndFrequency) { const int64_t kBitsPerSecond = 96000; const int64_t kBytes = 1200; const Frequency freq_a = Frequency::Hertz(kHertz); - const DataRate rate_b = DataRate::bps(kBitsPerSecond); - const DataSize size_c = DataSize::bytes(kBytes); + const DataRate rate_b = DataRate::BitsPerSec(kBitsPerSecond); + const DataSize size_c = DataSize::Bytes(kBytes); EXPECT_EQ((freq_a * size_c).bps(), kHertz * kBytes * 8); EXPECT_EQ((size_c * freq_a).bps(), kHertz * kBytes * 8); EXPECT_EQ((rate_b / size_c).hertz(), kBitsPerSecond / kBytes / 8); @@ -181,14 +181,14 @@ TEST(UnitConversionTest, DivisionFailsOnLargeSize) { // the implementation is changed, this test can safely be removed. const int64_t kJustSmallEnoughForDivision = std::numeric_limits::max() / 8000000; - const DataSize large_size = DataSize::bytes(kJustSmallEnoughForDivision); - const DataRate data_rate = DataRate::kbps(100); + const DataSize large_size = DataSize::Bytes(kJustSmallEnoughForDivision); + const DataRate data_rate = DataRate::KilobitsPerSec(100); const TimeDelta time_delta = TimeDelta::Millis(100); EXPECT_TRUE((large_size / data_rate).IsFinite()); EXPECT_TRUE((large_size / time_delta).IsFinite()); #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) && RTC_DCHECK_IS_ON const int64_t kToolargeForDivision = kJustSmallEnoughForDivision + 1; - const DataSize too_large_size = DataSize::bytes(kToolargeForDivision); + const DataSize too_large_size = DataSize::Bytes(kToolargeForDivision); EXPECT_DEATH(too_large_size / data_rate, ""); EXPECT_DEATH(too_large_size / time_delta, ""); #endif // GTEST_HAS_DEATH_TEST && !!defined(WEBRTC_ANDROID) && RTC_DCHECK_IS_ON diff --git a/api/units/data_size.h b/api/units/data_size.h index d294016489..82c4423529 100644 --- a/api/units/data_size.h +++ b/api/units/data_size.h @@ -24,8 +24,16 @@ namespace webrtc { // DataSize is a class represeting a count of bytes. class DataSize final : public rtc_units_impl::RelativeUnit { public: - DataSize() = delete; + template + static constexpr DataSize Bytes(T value) { + static_assert(std::is_arithmetic::value, ""); + return FromValue(value); + } static constexpr DataSize Infinity() { return PlusInfinity(); } + + DataSize() = delete; + // TODO(danilchap): Migrate all code to the factory above and delete the + // 2 factories below. template static constexpr DataSize Bytes() { return FromValue(bytes); diff --git a/api/units/data_size_unittest.cc b/api/units/data_size_unittest.cc index fe7f591dc0..eb8d98c1f0 100644 --- a/api/units/data_size_unittest.cc +++ b/api/units/data_size_unittest.cc @@ -9,6 +9,9 @@ */ #include "api/units/data_size.h" + +#include + #include "test/gtest.h" namespace webrtc { @@ -23,7 +26,7 @@ TEST(DataSizeTest, ConstExpr) { static_assert(kDataSizeInf.bytes_or(-1) == -1, ""); static_assert(kDataSizeInf > kDataSizeZero, ""); - constexpr DataSize kDataSize = DataSize::Bytes(); + constexpr DataSize kDataSize = DataSize::Bytes(kValue); static_assert(kDataSize.bytes_or(-1) == kValue, ""); EXPECT_EQ(kDataSize.bytes(), kValue); @@ -31,30 +34,30 @@ TEST(DataSizeTest, ConstExpr) { TEST(DataSizeTest, GetBackSameValues) { const int64_t kValue = 123 * 8; - EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue); + EXPECT_EQ(DataSize::Bytes(kValue).bytes(), kValue); } TEST(DataSizeTest, IdentityChecks) { const int64_t kValue = 3000; EXPECT_TRUE(DataSize::Zero().IsZero()); - EXPECT_FALSE(DataSize::bytes(kValue).IsZero()); + EXPECT_FALSE(DataSize::Bytes(kValue).IsZero()); EXPECT_TRUE(DataSize::Infinity().IsInfinite()); EXPECT_FALSE(DataSize::Zero().IsInfinite()); - EXPECT_FALSE(DataSize::bytes(kValue).IsInfinite()); + EXPECT_FALSE(DataSize::Bytes(kValue).IsInfinite()); EXPECT_FALSE(DataSize::Infinity().IsFinite()); - EXPECT_TRUE(DataSize::bytes(kValue).IsFinite()); + EXPECT_TRUE(DataSize::Bytes(kValue).IsFinite()); EXPECT_TRUE(DataSize::Zero().IsFinite()); } TEST(DataSizeTest, ComparisonOperators) { const int64_t kSmall = 450; const int64_t kLarge = 451; - const DataSize small = DataSize::bytes(kSmall); - const DataSize large = DataSize::bytes(kLarge); + const DataSize small = DataSize::Bytes(kSmall); + const DataSize large = DataSize::Bytes(kLarge); - EXPECT_EQ(DataSize::Zero(), DataSize::bytes(0)); + EXPECT_EQ(DataSize::Zero(), DataSize::Bytes(0)); EXPECT_EQ(DataSize::Infinity(), DataSize::Infinity()); EXPECT_EQ(small, small); EXPECT_LE(small, small); @@ -72,19 +75,19 @@ TEST(DataSizeTest, ConvertsToAndFromDouble) { const int64_t kValue = 128; const double kDoubleValue = static_cast(kValue); - EXPECT_EQ(DataSize::bytes(kValue).bytes(), kDoubleValue); - EXPECT_EQ(DataSize::bytes(kDoubleValue).bytes(), kValue); + EXPECT_EQ(DataSize::Bytes(kValue).bytes(), kDoubleValue); + EXPECT_EQ(DataSize::Bytes(kDoubleValue).bytes(), kValue); const double kInfinity = std::numeric_limits::infinity(); EXPECT_EQ(DataSize::Infinity().bytes(), kInfinity); - EXPECT_TRUE(DataSize::bytes(kInfinity).IsInfinite()); + EXPECT_TRUE(DataSize::Bytes(kInfinity).IsInfinite()); } TEST(DataSizeTest, MathOperations) { const int64_t kValueA = 450; const int64_t kValueB = 267; - const DataSize size_a = DataSize::bytes(kValueA); - const DataSize size_b = DataSize::bytes(kValueB); + const DataSize size_a = DataSize::Bytes(kValueA); + const DataSize size_b = DataSize::Bytes(kValueB); EXPECT_EQ((size_a + size_b).bytes(), kValueA + kValueB); EXPECT_EQ((size_a - size_b).bytes(), kValueA - kValueB); @@ -97,7 +100,7 @@ TEST(DataSizeTest, MathOperations) { EXPECT_EQ((size_a / 10).bytes(), kValueA / 10); EXPECT_EQ(size_a / size_b, static_cast(kValueA) / kValueB); - DataSize mutable_size = DataSize::bytes(kValueA); + DataSize mutable_size = DataSize::Bytes(kValueA); mutable_size += size_b; EXPECT_EQ(mutable_size.bytes(), kValueA + kValueB); mutable_size -= size_a;