diff --git a/api/units/time_delta.h b/api/units/time_delta.h index b82047285f..6e69333fca 100644 --- a/api/units/time_delta.h +++ b/api/units/time_delta.h @@ -188,17 +188,35 @@ class TimeDelta { return microseconds_ == timedelta_impl::kMinusInfinityVal; } TimeDelta operator+(const TimeDelta& other) const { + if (IsPlusInfinity() || other.IsPlusInfinity()) { + RTC_DCHECK(!IsMinusInfinity()); + RTC_DCHECK(!other.IsMinusInfinity()); + return PlusInfinity(); + } else if (IsMinusInfinity() || other.IsMinusInfinity()) { + RTC_DCHECK(!IsPlusInfinity()); + RTC_DCHECK(!other.IsPlusInfinity()); + return MinusInfinity(); + } return TimeDelta::us(us() + other.us()); } TimeDelta operator-(const TimeDelta& other) const { + if (IsPlusInfinity() || other.IsMinusInfinity()) { + RTC_DCHECK(!IsMinusInfinity()); + RTC_DCHECK(!other.IsPlusInfinity()); + return PlusInfinity(); + } else if (IsMinusInfinity() || other.IsPlusInfinity()) { + RTC_DCHECK(!IsPlusInfinity()); + RTC_DCHECK(!other.IsMinusInfinity()); + return MinusInfinity(); + } return TimeDelta::us(us() - other.us()); } TimeDelta& operator-=(const TimeDelta& other) { - microseconds_ -= other.us(); + *this = *this - other; return *this; } TimeDelta& operator+=(const TimeDelta& other) { - microseconds_ += other.us(); + *this = *this + other; return *this; } constexpr double operator/(const TimeDelta& other) const { diff --git a/api/units/time_delta_unittest.cc b/api/units/time_delta_unittest.cc index 9eddee73ad..e5906bfd4a 100644 --- a/api/units/time_delta_unittest.cc +++ b/api/units/time_delta_unittest.cc @@ -164,6 +164,26 @@ TEST(TimeDeltaTest, MathOperations) { EXPECT_EQ(TimeDelta::us(-kValueA).Abs().us(), kValueA); EXPECT_EQ(TimeDelta::us(kValueA).Abs().us(), kValueA); + + TimeDelta mutable_delta = TimeDelta::ms(kValueA); + mutable_delta += TimeDelta::ms(kValueB); + EXPECT_EQ(mutable_delta, TimeDelta::ms(kValueA + kValueB)); + mutable_delta -= TimeDelta::ms(kValueB); + EXPECT_EQ(mutable_delta, TimeDelta::ms(kValueA)); +} + +TEST(TimeDeltaTest, InfinityOperations) { + const int64_t kValue = 267; + const TimeDelta finite = TimeDelta::ms(kValue); + EXPECT_TRUE((TimeDelta::PlusInfinity() + finite).IsPlusInfinity()); + EXPECT_TRUE((TimeDelta::PlusInfinity() - finite).IsPlusInfinity()); + EXPECT_TRUE((finite + TimeDelta::PlusInfinity()).IsPlusInfinity()); + EXPECT_TRUE((finite - TimeDelta::MinusInfinity()).IsPlusInfinity()); + + EXPECT_TRUE((TimeDelta::MinusInfinity() + finite).IsMinusInfinity()); + EXPECT_TRUE((TimeDelta::MinusInfinity() - finite).IsMinusInfinity()); + EXPECT_TRUE((finite + TimeDelta::MinusInfinity()).IsMinusInfinity()); + EXPECT_TRUE((finite - TimeDelta::PlusInfinity()).IsMinusInfinity()); } } // namespace test } // namespace webrtc diff --git a/api/units/timestamp.h b/api/units/timestamp.h index 6e5e3925ac..d7e6a8db34 100644 --- a/api/units/timestamp.h +++ b/api/units/timestamp.h @@ -162,17 +162,23 @@ class Timestamp { return TimeDelta::us(us() - other.us()); } Timestamp operator-(const TimeDelta& delta) const { + RTC_DCHECK(!delta.IsPlusInfinity()); + if (IsInfinite() || delta.IsMinusInfinity()) + return Infinity(); return Timestamp::us(us() - delta.us()); } Timestamp operator+(const TimeDelta& delta) const { + RTC_DCHECK(!delta.IsMinusInfinity()); + if (IsInfinite() || delta.IsPlusInfinity()) + return Infinity(); return Timestamp::us(us() + delta.us()); } Timestamp& operator-=(const TimeDelta& other) { - microseconds_ -= other.us(); + *this = *this - other; return *this; } Timestamp& operator+=(const TimeDelta& other) { - microseconds_ += other.us(); + *this = *this + other; return *this; } constexpr bool operator==(const Timestamp& other) const { diff --git a/api/units/timestamp_unittest.cc b/api/units/timestamp_unittest.cc index db894cca44..ff0c79e071 100644 --- a/api/units/timestamp_unittest.cc +++ b/api/units/timestamp_unittest.cc @@ -118,10 +118,27 @@ TEST(UnitConversionTest, TimestampAndTimeDeltaMath) { const Timestamp time_a = Timestamp::ms(kValueA); const Timestamp time_b = Timestamp::ms(kValueB); const TimeDelta delta_a = TimeDelta::ms(kValueA); + const TimeDelta delta_b = TimeDelta::ms(kValueB); EXPECT_EQ((time_a - time_b), TimeDelta::ms(kValueA - kValueB)); EXPECT_EQ((time_b - delta_a), Timestamp::ms(kValueB - kValueA)); EXPECT_EQ((time_b + delta_a), Timestamp::ms(kValueB + kValueA)); + + Timestamp mutable_time = time_a; + mutable_time += delta_b; + EXPECT_EQ(mutable_time, time_a + delta_b); + mutable_time -= delta_b; + EXPECT_EQ(mutable_time, time_a); +} + +TEST(UnitConversionTest, InfinityOperations) { + const int64_t kValue = 267; + const Timestamp finite_time = Timestamp::ms(kValue); + const TimeDelta finite_delta = TimeDelta::ms(kValue); + EXPECT_TRUE((Timestamp::Infinity() + finite_delta).IsInfinite()); + EXPECT_TRUE((Timestamp::Infinity() - finite_delta).IsInfinite()); + EXPECT_TRUE((finite_time + TimeDelta::PlusInfinity()).IsInfinite()); + EXPECT_TRUE((finite_time - TimeDelta::MinusInfinity()).IsInfinite()); } } // namespace test } // namespace webrtc