Add conversions to and from double for units.
Bug: webrtc:8415 Change-Id: I6b1f7afb163daa327e45c51f1a3fb7cafbb1444e Reviewed-on: https://webrtc-review.googlesource.com/78183 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23451}
This commit is contained in:

committed by
Commit Bot

parent
f859e55d9b
commit
942b360d82
@ -16,6 +16,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/numerics/safe_conversions.h"
|
||||||
|
|
||||||
#include "api/units/data_size.h"
|
#include "api/units/data_size.h"
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
@ -43,28 +44,78 @@ class DataRate {
|
|||||||
static DataRate Infinity() {
|
static DataRate Infinity() {
|
||||||
return DataRate(data_rate_impl::kPlusInfinityVal);
|
return DataRate(data_rate_impl::kPlusInfinityVal);
|
||||||
}
|
}
|
||||||
static DataRate bits_per_second(int64_t bits_per_sec) {
|
|
||||||
RTC_DCHECK_GE(bits_per_sec, 0);
|
template <
|
||||||
return DataRate(bits_per_sec);
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static DataRate bps(T bits_per_second) {
|
||||||
|
RTC_DCHECK_GE(bits_per_second, 0);
|
||||||
|
RTC_DCHECK_LT(bits_per_second, data_rate_impl::kPlusInfinityVal);
|
||||||
|
return DataRate(rtc::dchecked_cast<int64_t>(bits_per_second));
|
||||||
}
|
}
|
||||||
static DataRate bps(int64_t bits_per_sec) {
|
template <
|
||||||
return DataRate::bits_per_second(bits_per_sec);
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static DataRate kbps(T kilobits_per_sec) {
|
||||||
|
RTC_DCHECK_GE(kilobits_per_sec, 0);
|
||||||
|
RTC_DCHECK_LT(kilobits_per_sec, data_rate_impl::kPlusInfinityVal / 1000);
|
||||||
|
return DataRate::bps(rtc::dchecked_cast<int64_t>(kilobits_per_sec) * 1000);
|
||||||
}
|
}
|
||||||
static DataRate kbps(int64_t kilobits_per_sec) {
|
|
||||||
return DataRate::bits_per_second(kilobits_per_sec * 1000);
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static DataRate bps(T bits_per_second) {
|
||||||
|
if (bits_per_second == std::numeric_limits<T>::infinity()) {
|
||||||
|
return Infinity();
|
||||||
|
} else {
|
||||||
|
RTC_DCHECK(!std::isnan(bits_per_second));
|
||||||
|
RTC_DCHECK_GE(bits_per_second, 0);
|
||||||
|
RTC_DCHECK_LT(bits_per_second, data_rate_impl::kPlusInfinityVal);
|
||||||
|
return DataRate(rtc::dchecked_cast<int64_t>(bits_per_second));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int64_t bits_per_second() const {
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static DataRate kbps(T kilobits_per_sec) {
|
||||||
|
return DataRate::bps(kilobits_per_sec * 1e3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type bps() const {
|
||||||
RTC_DCHECK(IsFinite());
|
RTC_DCHECK(IsFinite());
|
||||||
return bits_per_sec_;
|
return rtc::dchecked_cast<T>(bits_per_sec_);
|
||||||
}
|
}
|
||||||
int64_t bps() const { return bits_per_second(); }
|
template <typename T = int64_t>
|
||||||
int64_t kbps() const { return (bps() + 500) / 1000; }
|
typename std::enable_if<std::is_integral<T>::value, T>::type kbps() const {
|
||||||
|
return rtc::dchecked_cast<T>((bps() + 500) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type bps()
|
||||||
|
const {
|
||||||
|
if (IsInfinite()) {
|
||||||
|
return std::numeric_limits<T>::infinity();
|
||||||
|
} else {
|
||||||
|
return bits_per_sec_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type kbps()
|
||||||
|
const {
|
||||||
|
return bps<T>() * 1e-3;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsZero() const { return bits_per_sec_ == 0; }
|
bool IsZero() const { return bits_per_sec_ == 0; }
|
||||||
bool IsInfinite() const {
|
bool IsInfinite() const {
|
||||||
return bits_per_sec_ == data_rate_impl::kPlusInfinityVal;
|
return bits_per_sec_ == data_rate_impl::kPlusInfinityVal;
|
||||||
}
|
}
|
||||||
bool IsFinite() const { return !IsInfinite(); }
|
bool IsFinite() const { return !IsInfinite(); }
|
||||||
|
|
||||||
|
double operator/(const DataRate& other) const {
|
||||||
|
return bps<double>() / other.bps<double>();
|
||||||
|
}
|
||||||
bool operator==(const DataRate& other) const {
|
bool operator==(const DataRate& other) const {
|
||||||
return bits_per_sec_ == other.bits_per_sec_;
|
return bits_per_sec_ == other.bits_per_sec_;
|
||||||
}
|
}
|
||||||
@ -92,34 +143,32 @@ class DataRate {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline DataRate operator*(const DataRate& rate, const double& scalar) {
|
inline DataRate operator*(const DataRate& rate, const double& scalar) {
|
||||||
return DataRate::bits_per_second(std::round(rate.bits_per_second() * scalar));
|
return DataRate::bps(std::round(rate.bps() * scalar));
|
||||||
}
|
}
|
||||||
inline DataRate operator*(const double& scalar, const DataRate& rate) {
|
inline DataRate operator*(const double& scalar, const DataRate& rate) {
|
||||||
return rate * scalar;
|
return rate * scalar;
|
||||||
}
|
}
|
||||||
inline DataRate operator*(const DataRate& rate, const int64_t& scalar) {
|
inline DataRate operator*(const DataRate& rate, const int64_t& scalar) {
|
||||||
return DataRate::bits_per_second(rate.bits_per_second() * scalar);
|
return DataRate::bps(rate.bps() * scalar);
|
||||||
}
|
}
|
||||||
inline DataRate operator*(const int64_t& scalar, const DataRate& rate) {
|
inline DataRate operator*(const int64_t& scalar, const DataRate& rate) {
|
||||||
return rate * scalar;
|
return rate * scalar;
|
||||||
}
|
}
|
||||||
inline DataRate operator*(const DataRate& rate, const int32_t& scalar) {
|
inline DataRate operator*(const DataRate& rate, const int32_t& scalar) {
|
||||||
return DataRate::bits_per_second(rate.bits_per_second() * scalar);
|
return DataRate::bps(rate.bps() * scalar);
|
||||||
}
|
}
|
||||||
inline DataRate operator*(const int32_t& scalar, const DataRate& rate) {
|
inline DataRate operator*(const int32_t& scalar, const DataRate& rate) {
|
||||||
return rate * scalar;
|
return rate * scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DataRate operator/(const DataSize& size, const TimeDelta& duration) {
|
inline DataRate operator/(const DataSize& size, const TimeDelta& duration) {
|
||||||
return DataRate::bits_per_second(data_rate_impl::Microbits(size) /
|
return DataRate::bps(data_rate_impl::Microbits(size) / duration.us());
|
||||||
duration.us());
|
|
||||||
}
|
}
|
||||||
inline TimeDelta operator/(const DataSize& size, const DataRate& rate) {
|
inline TimeDelta operator/(const DataSize& size, const DataRate& rate) {
|
||||||
return TimeDelta::us(data_rate_impl::Microbits(size) /
|
return TimeDelta::us(data_rate_impl::Microbits(size) / rate.bps());
|
||||||
rate.bits_per_second());
|
|
||||||
}
|
}
|
||||||
inline DataSize operator*(const DataRate& rate, const TimeDelta& duration) {
|
inline DataSize operator*(const DataRate& rate, const TimeDelta& duration) {
|
||||||
int64_t microbits = rate.bits_per_second() * duration.us();
|
int64_t microbits = rate.bps() * duration.us();
|
||||||
return DataSize::bytes((microbits + 4000000) / 8000000);
|
return DataSize::bytes((microbits + 4000000) / 8000000);
|
||||||
}
|
}
|
||||||
inline DataSize operator*(const TimeDelta& duration, const DataRate& rate) {
|
inline DataSize operator*(const TimeDelta& duration, const DataRate& rate) {
|
||||||
|
@ -15,7 +15,6 @@ namespace webrtc {
|
|||||||
namespace test {
|
namespace test {
|
||||||
TEST(DataRateTest, GetBackSameValues) {
|
TEST(DataRateTest, GetBackSameValues) {
|
||||||
const int64_t kValue = 123 * 8;
|
const int64_t kValue = 123 * 8;
|
||||||
EXPECT_EQ(DataRate::bits_per_second(kValue).bits_per_second(), kValue);
|
|
||||||
EXPECT_EQ(DataRate::bps(kValue).bps(), kValue);
|
EXPECT_EQ(DataRate::bps(kValue).bps(), kValue);
|
||||||
EXPECT_EQ(DataRate::kbps(kValue).kbps(), kValue);
|
EXPECT_EQ(DataRate::kbps(kValue).kbps(), kValue);
|
||||||
}
|
}
|
||||||
@ -28,22 +27,22 @@ TEST(DataRateTest, GetDifferentPrefix) {
|
|||||||
TEST(DataRateTest, IdentityChecks) {
|
TEST(DataRateTest, IdentityChecks) {
|
||||||
const int64_t kValue = 3000;
|
const int64_t kValue = 3000;
|
||||||
EXPECT_TRUE(DataRate::Zero().IsZero());
|
EXPECT_TRUE(DataRate::Zero().IsZero());
|
||||||
EXPECT_FALSE(DataRate::bits_per_second(kValue).IsZero());
|
EXPECT_FALSE(DataRate::bps(kValue).IsZero());
|
||||||
|
|
||||||
EXPECT_TRUE(DataRate::Infinity().IsInfinite());
|
EXPECT_TRUE(DataRate::Infinity().IsInfinite());
|
||||||
EXPECT_FALSE(DataRate::Zero().IsInfinite());
|
EXPECT_FALSE(DataRate::Zero().IsInfinite());
|
||||||
EXPECT_FALSE(DataRate::bits_per_second(kValue).IsInfinite());
|
EXPECT_FALSE(DataRate::bps(kValue).IsInfinite());
|
||||||
|
|
||||||
EXPECT_FALSE(DataRate::Infinity().IsFinite());
|
EXPECT_FALSE(DataRate::Infinity().IsFinite());
|
||||||
EXPECT_TRUE(DataRate::bits_per_second(kValue).IsFinite());
|
EXPECT_TRUE(DataRate::bps(kValue).IsFinite());
|
||||||
EXPECT_TRUE(DataRate::Zero().IsFinite());
|
EXPECT_TRUE(DataRate::Zero().IsFinite());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DataRateTest, ComparisonOperators) {
|
TEST(DataRateTest, ComparisonOperators) {
|
||||||
const int64_t kSmall = 450;
|
const int64_t kSmall = 450;
|
||||||
const int64_t kLarge = 451;
|
const int64_t kLarge = 451;
|
||||||
const DataRate small = DataRate::bits_per_second(kSmall);
|
const DataRate small = DataRate::bps(kSmall);
|
||||||
const DataRate large = DataRate::bits_per_second(kLarge);
|
const DataRate large = DataRate::bps(kLarge);
|
||||||
|
|
||||||
EXPECT_EQ(DataRate::Zero(), DataRate::bps(0));
|
EXPECT_EQ(DataRate::Zero(), DataRate::bps(0));
|
||||||
EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity());
|
EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity());
|
||||||
@ -59,15 +58,36 @@ TEST(DataRateTest, ComparisonOperators) {
|
|||||||
EXPECT_GT(DataRate::Infinity(), large);
|
EXPECT_GT(DataRate::Infinity(), large);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(DataRateTest, ConvertsToAndFromDouble) {
|
||||||
|
const int64_t kValue = 128;
|
||||||
|
const double kDoubleValue = static_cast<double>(kValue);
|
||||||
|
const double kDoubleKbps = kValue * 1e-3;
|
||||||
|
const double kFloatKbps = static_cast<float>(kDoubleKbps);
|
||||||
|
|
||||||
|
EXPECT_EQ(DataRate::bps(kValue).bps<double>(), kDoubleValue);
|
||||||
|
EXPECT_EQ(DataRate::bps(kValue).kbps<double>(), kDoubleKbps);
|
||||||
|
EXPECT_EQ(DataRate::bps(kValue).kbps<float>(), kFloatKbps);
|
||||||
|
EXPECT_EQ(DataRate::bps(kDoubleValue).bps(), kValue);
|
||||||
|
EXPECT_EQ(DataRate::kbps(kDoubleKbps).bps(), kValue);
|
||||||
|
|
||||||
|
const double kInfinity = std::numeric_limits<double>::infinity();
|
||||||
|
EXPECT_EQ(DataRate::Infinity().bps<double>(), kInfinity);
|
||||||
|
EXPECT_TRUE(DataRate::bps(kInfinity).IsInfinite());
|
||||||
|
EXPECT_TRUE(DataRate::kbps(kInfinity).IsInfinite());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(DataRateTest, MathOperations) {
|
TEST(DataRateTest, MathOperations) {
|
||||||
const int64_t kValueA = 450;
|
const int64_t kValueA = 450;
|
||||||
const int64_t kValueB = 267;
|
const int64_t kValueB = 267;
|
||||||
const DataRate size_a = DataRate::bits_per_second(kValueA);
|
const DataRate rate_a = DataRate::bps(kValueA);
|
||||||
|
const DataRate rate_b = DataRate::bps(kValueB);
|
||||||
const int32_t kInt32Value = 123;
|
const int32_t kInt32Value = 123;
|
||||||
const double kFloatValue = 123.0;
|
const double kFloatValue = 123.0;
|
||||||
EXPECT_EQ((size_a * kValueB).bits_per_second(), kValueA * kValueB);
|
EXPECT_EQ((rate_a * kValueB).bps(), kValueA * kValueB);
|
||||||
EXPECT_EQ((size_a * kInt32Value).bits_per_second(), kValueA * kInt32Value);
|
EXPECT_EQ((rate_a * kInt32Value).bps(), kValueA * kInt32Value);
|
||||||
EXPECT_EQ((size_a * kFloatValue).bits_per_second(), kValueA * kFloatValue);
|
EXPECT_EQ((rate_a * kFloatValue).bps(), kValueA * kFloatValue);
|
||||||
|
|
||||||
|
EXPECT_EQ(rate_a / rate_b, static_cast<double>(kValueA) / kValueB);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) {
|
TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) {
|
||||||
@ -75,11 +95,11 @@ TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) {
|
|||||||
const int64_t kBitsPerSecond = 440;
|
const int64_t kBitsPerSecond = 440;
|
||||||
const int64_t kBytes = 44000;
|
const int64_t kBytes = 44000;
|
||||||
const TimeDelta delta_a = TimeDelta::seconds(kSeconds);
|
const TimeDelta delta_a = TimeDelta::seconds(kSeconds);
|
||||||
const DataRate rate_b = DataRate::bits_per_second(kBitsPerSecond);
|
const DataRate rate_b = DataRate::bps(kBitsPerSecond);
|
||||||
const DataSize size_c = DataSize::bytes(kBytes);
|
const DataSize size_c = DataSize::bytes(kBytes);
|
||||||
EXPECT_EQ((delta_a * rate_b).bytes(), kSeconds * kBitsPerSecond / 8);
|
EXPECT_EQ((delta_a * rate_b).bytes(), kSeconds * kBitsPerSecond / 8);
|
||||||
EXPECT_EQ((rate_b * delta_a).bytes(), kSeconds * kBitsPerSecond / 8);
|
EXPECT_EQ((rate_b * delta_a).bytes(), kSeconds * kBitsPerSecond / 8);
|
||||||
EXPECT_EQ((size_c / delta_a).bits_per_second(), kBytes * 8 / kSeconds);
|
EXPECT_EQ((size_c / delta_a).bps(), kBytes * 8 / kSeconds);
|
||||||
EXPECT_EQ((size_c / rate_b).seconds(), kBytes * 8 / kBitsPerSecond);
|
EXPECT_EQ((size_c / rate_b).seconds(), kBytes * 8 / kBitsPerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/numerics/safe_conversions.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace data_size_impl {
|
namespace data_size_impl {
|
||||||
@ -31,15 +33,46 @@ class DataSize {
|
|||||||
static DataSize Infinity() {
|
static DataSize Infinity() {
|
||||||
return DataSize(data_size_impl::kPlusInfinityVal);
|
return DataSize(data_size_impl::kPlusInfinityVal);
|
||||||
}
|
}
|
||||||
static DataSize bytes(int64_t bytes) {
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static DataSize bytes(T bytes) {
|
||||||
RTC_DCHECK_GE(bytes, 0);
|
RTC_DCHECK_GE(bytes, 0);
|
||||||
return DataSize(bytes);
|
RTC_DCHECK_LT(bytes, data_size_impl::kPlusInfinityVal);
|
||||||
|
return DataSize(rtc::dchecked_cast<int64_t>(bytes));
|
||||||
}
|
}
|
||||||
int64_t bytes() const {
|
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static DataSize bytes(T bytes) {
|
||||||
|
if (bytes == std::numeric_limits<T>::infinity()) {
|
||||||
|
return Infinity();
|
||||||
|
} else {
|
||||||
|
RTC_DCHECK(!std::isnan(bytes));
|
||||||
|
RTC_DCHECK_GE(bytes, 0);
|
||||||
|
RTC_DCHECK_LT(bytes, data_size_impl::kPlusInfinityVal);
|
||||||
|
return DataSize(rtc::dchecked_cast<int64_t>(bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type bytes() const {
|
||||||
RTC_DCHECK(IsFinite());
|
RTC_DCHECK(IsFinite());
|
||||||
return bytes_;
|
return rtc::dchecked_cast<T>(bytes_);
|
||||||
}
|
}
|
||||||
int64_t kilobytes() const { return (bytes() + 500) / 1000; }
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type bytes()
|
||||||
|
const {
|
||||||
|
if (IsInfinite()) {
|
||||||
|
return std::numeric_limits<T>::infinity();
|
||||||
|
} else {
|
||||||
|
return bytes_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsZero() const { return bytes_ == 0; }
|
bool IsZero() const { return bytes_ == 0; }
|
||||||
bool IsInfinite() const { return bytes_ == data_size_impl::kPlusInfinityVal; }
|
bool IsInfinite() const { return bytes_ == data_size_impl::kPlusInfinityVal; }
|
||||||
bool IsFinite() const { return !IsInfinite(); }
|
bool IsFinite() const { return !IsInfinite(); }
|
||||||
@ -57,6 +90,9 @@ class DataSize {
|
|||||||
bytes_ += other.bytes();
|
bytes_ += other.bytes();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
double operator/(const DataSize& other) const {
|
||||||
|
return bytes<double>() / other.bytes<double>();
|
||||||
|
}
|
||||||
bool operator==(const DataSize& other) const {
|
bool operator==(const DataSize& other) const {
|
||||||
return bytes_ == other.bytes_;
|
return bytes_ == other.bytes_;
|
||||||
}
|
}
|
||||||
@ -76,6 +112,7 @@ class DataSize {
|
|||||||
explicit DataSize(int64_t bytes) : bytes_(bytes) {}
|
explicit DataSize(int64_t bytes) : bytes_(bytes) {}
|
||||||
int64_t bytes_;
|
int64_t bytes_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline DataSize operator*(const DataSize& size, const double& scalar) {
|
inline DataSize operator*(const DataSize& size, const double& scalar) {
|
||||||
return DataSize::bytes(std::round(size.bytes() * scalar));
|
return DataSize::bytes(std::round(size.bytes() * scalar));
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,6 @@ TEST(DataSizeTest, GetBackSameValues) {
|
|||||||
EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue);
|
EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DataSizeTest, GetDifferentPrefix) {
|
|
||||||
const int64_t kValue = 123 * 8000;
|
|
||||||
EXPECT_EQ(DataSize::bytes(kValue).kilobytes(), kValue / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(DataSizeTest, IdentityChecks) {
|
TEST(DataSizeTest, IdentityChecks) {
|
||||||
const int64_t kValue = 3000;
|
const int64_t kValue = 3000;
|
||||||
EXPECT_TRUE(DataSize::Zero().IsZero());
|
EXPECT_TRUE(DataSize::Zero().IsZero());
|
||||||
@ -58,6 +53,18 @@ TEST(DataSizeTest, ComparisonOperators) {
|
|||||||
EXPECT_GT(DataSize::Infinity(), large);
|
EXPECT_GT(DataSize::Infinity(), large);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(DataSizeTest, ConvertsToAndFromDouble) {
|
||||||
|
const int64_t kValue = 128;
|
||||||
|
const double kDoubleValue = static_cast<double>(kValue);
|
||||||
|
|
||||||
|
EXPECT_EQ(DataSize::bytes(kValue).bytes<double>(), kDoubleValue);
|
||||||
|
EXPECT_EQ(DataSize::bytes(kDoubleValue).bytes(), kValue);
|
||||||
|
|
||||||
|
const double kInfinity = std::numeric_limits<double>::infinity();
|
||||||
|
EXPECT_EQ(DataSize::Infinity().bytes<double>(), kInfinity);
|
||||||
|
EXPECT_TRUE(DataSize::bytes(kInfinity).IsInfinite());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(DataSizeTest, MathOperations) {
|
TEST(DataSizeTest, MathOperations) {
|
||||||
const int64_t kValueA = 450;
|
const int64_t kValueA = 450;
|
||||||
const int64_t kValueB = 267;
|
const int64_t kValueB = 267;
|
||||||
@ -73,6 +80,7 @@ TEST(DataSizeTest, MathOperations) {
|
|||||||
EXPECT_EQ((size_a * kFloatValue).bytes(), kValueA * kFloatValue);
|
EXPECT_EQ((size_a * kFloatValue).bytes(), kValueA * kFloatValue);
|
||||||
|
|
||||||
EXPECT_EQ((size_a / 10).bytes(), kValueA / 10);
|
EXPECT_EQ((size_a / 10).bytes(), kValueA / 10);
|
||||||
|
EXPECT_EQ(size_a / size_b, static_cast<double>(kValueA) / kValueB);
|
||||||
|
|
||||||
DataSize mutable_size = DataSize::bytes(kValueA);
|
DataSize mutable_size = DataSize::bytes(kValueA);
|
||||||
mutable_size += size_b;
|
mutable_size += size_b;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/numerics/safe_conversions.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace timedelta_impl {
|
namespace timedelta_impl {
|
||||||
@ -41,33 +42,107 @@ class TimeDelta {
|
|||||||
static TimeDelta MinusInfinity() {
|
static TimeDelta MinusInfinity() {
|
||||||
return TimeDelta(timedelta_impl::kMinusInfinityVal);
|
return TimeDelta(timedelta_impl::kMinusInfinityVal);
|
||||||
}
|
}
|
||||||
static TimeDelta seconds(int64_t seconds) {
|
|
||||||
return TimeDelta::us(seconds * 1000000);
|
template <
|
||||||
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static TimeDelta seconds(T seconds) {
|
||||||
|
RTC_DCHECK_GT(seconds, timedelta_impl::kMinusInfinityVal / 1000000);
|
||||||
|
RTC_DCHECK_LT(seconds, timedelta_impl::kPlusInfinityVal / 1000000);
|
||||||
|
return TimeDelta(rtc::dchecked_cast<int64_t>(seconds) * 1000000);
|
||||||
}
|
}
|
||||||
static TimeDelta ms(int64_t milliseconds) {
|
template <
|
||||||
return TimeDelta::us(milliseconds * 1000);
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static TimeDelta ms(T milliseconds) {
|
||||||
|
RTC_DCHECK_GT(milliseconds, timedelta_impl::kMinusInfinityVal / 1000);
|
||||||
|
RTC_DCHECK_LT(milliseconds, timedelta_impl::kPlusInfinityVal / 1000);
|
||||||
|
return TimeDelta(rtc::dchecked_cast<int64_t>(milliseconds) * 1000);
|
||||||
}
|
}
|
||||||
static TimeDelta us(int64_t microseconds) {
|
template <
|
||||||
// Infinities only allowed via use of explicit constants.
|
typename T,
|
||||||
RTC_DCHECK(microseconds > std::numeric_limits<int64_t>::min());
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
RTC_DCHECK(microseconds < std::numeric_limits<int64_t>::max());
|
static TimeDelta us(T microseconds) {
|
||||||
return TimeDelta(microseconds);
|
RTC_DCHECK_GT(microseconds, timedelta_impl::kMinusInfinityVal);
|
||||||
}
|
RTC_DCHECK_LT(microseconds, timedelta_impl::kPlusInfinityVal);
|
||||||
int64_t seconds() const {
|
return TimeDelta(rtc::dchecked_cast<int64_t>(microseconds));
|
||||||
return (us() + (us() >= 0 ? 500000 : -500000)) / 1000000;
|
|
||||||
}
|
|
||||||
int64_t ms() const { return (us() + (us() >= 0 ? 500 : -500)) / 1000; }
|
|
||||||
int64_t us() const {
|
|
||||||
RTC_DCHECK(IsFinite());
|
|
||||||
return microseconds_;
|
|
||||||
}
|
|
||||||
int64_t ns() const {
|
|
||||||
RTC_DCHECK(us() > std::numeric_limits<int64_t>::min() / 1000);
|
|
||||||
RTC_DCHECK(us() < std::numeric_limits<int64_t>::max() / 1000);
|
|
||||||
return us() * 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double SecondsAsDouble() const;
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static TimeDelta seconds(T seconds) {
|
||||||
|
return TimeDelta::us(seconds * 1e6);
|
||||||
|
}
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static TimeDelta ms(T milliseconds) {
|
||||||
|
return TimeDelta::us(milliseconds * 1e3);
|
||||||
|
}
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static TimeDelta us(T microseconds) {
|
||||||
|
if (microseconds == std::numeric_limits<T>::infinity()) {
|
||||||
|
return PlusInfinity();
|
||||||
|
} else if (microseconds == -std::numeric_limits<T>::infinity()) {
|
||||||
|
return MinusInfinity();
|
||||||
|
} else {
|
||||||
|
RTC_DCHECK(!std::isnan(microseconds));
|
||||||
|
RTC_DCHECK_GT(microseconds, timedelta_impl::kMinusInfinityVal);
|
||||||
|
RTC_DCHECK_LT(microseconds, timedelta_impl::kPlusInfinityVal);
|
||||||
|
return TimeDelta(rtc::dchecked_cast<int64_t>(microseconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type seconds() const {
|
||||||
|
return rtc::dchecked_cast<T>((us() + (us() >= 0 ? 500000 : -500000)) /
|
||||||
|
1000000);
|
||||||
|
}
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type ms() const {
|
||||||
|
return rtc::dchecked_cast<T>((us() + (us() >= 0 ? 500 : -500)) / 1000);
|
||||||
|
}
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type us() const {
|
||||||
|
RTC_DCHECK(IsFinite());
|
||||||
|
return rtc::dchecked_cast<T>(microseconds_);
|
||||||
|
}
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type ns() const {
|
||||||
|
RTC_DCHECK_GE(us(), std::numeric_limits<T>::min() / 1000);
|
||||||
|
RTC_DCHECK_LE(us(), std::numeric_limits<T>::max() / 1000);
|
||||||
|
return rtc::dchecked_cast<T>(us() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type seconds()
|
||||||
|
const {
|
||||||
|
return us<T>() * 1e-6;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type ms()
|
||||||
|
const {
|
||||||
|
return us<T>() * 1e-3;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type us()
|
||||||
|
const {
|
||||||
|
if (IsPlusInfinity()) {
|
||||||
|
return std::numeric_limits<T>::infinity();
|
||||||
|
} else if (IsMinusInfinity()) {
|
||||||
|
return -std::numeric_limits<T>::infinity();
|
||||||
|
} else {
|
||||||
|
return microseconds_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type ns()
|
||||||
|
const {
|
||||||
|
return us<T>() * 1e3;
|
||||||
|
}
|
||||||
|
|
||||||
TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); }
|
TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); }
|
||||||
bool IsZero() const { return microseconds_ == 0; }
|
bool IsZero() const { return microseconds_ == 0; }
|
||||||
@ -96,7 +171,9 @@ class TimeDelta {
|
|||||||
microseconds_ += other.us();
|
microseconds_ += other.us();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
double operator/(const TimeDelta& other) const {
|
||||||
|
return us<double>() / other.us<double>();
|
||||||
|
}
|
||||||
bool operator==(const TimeDelta& other) const {
|
bool operator==(const TimeDelta& other) const {
|
||||||
return microseconds_ == other.microseconds_;
|
return microseconds_ == other.microseconds_;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,51 @@ TEST(TimeDeltaTest, ComparisonOperators) {
|
|||||||
EXPECT_LT(TimeDelta::MinusInfinity(), TimeDelta::Zero());
|
EXPECT_LT(TimeDelta::MinusInfinity(), TimeDelta::Zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TimeDeltaTest, CanBeInititializedFromLargeInt) {
|
||||||
|
const int kMaxInt = std::numeric_limits<int>::max();
|
||||||
|
EXPECT_EQ(TimeDelta::seconds(kMaxInt).us(),
|
||||||
|
static_cast<int64_t>(kMaxInt) * 1000000);
|
||||||
|
EXPECT_EQ(TimeDelta::ms(kMaxInt).us(), static_cast<int64_t>(kMaxInt) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimeDeltaTest, ConvertsToAndFromDouble) {
|
||||||
|
const int64_t kMicros = 17017;
|
||||||
|
const double kNanosDouble = kMicros * 1e3;
|
||||||
|
const double kMicrosDouble = kMicros;
|
||||||
|
const double kMillisDouble = kMicros * 1e-3;
|
||||||
|
const double kSecondsDouble = kMillisDouble * 1e-3;
|
||||||
|
|
||||||
|
EXPECT_EQ(TimeDelta::us(kMicros).seconds<double>(), kSecondsDouble);
|
||||||
|
EXPECT_EQ(TimeDelta::seconds(kSecondsDouble).us(), kMicros);
|
||||||
|
|
||||||
|
EXPECT_EQ(TimeDelta::us(kMicros).ms<double>(), kMillisDouble);
|
||||||
|
EXPECT_EQ(TimeDelta::ms(kMillisDouble).us(), kMicros);
|
||||||
|
|
||||||
|
EXPECT_EQ(TimeDelta::us(kMicros).us<double>(), kMicrosDouble);
|
||||||
|
EXPECT_EQ(TimeDelta::us(kMicrosDouble).us(), kMicros);
|
||||||
|
|
||||||
|
EXPECT_NEAR(TimeDelta::us(kMicros).ns<double>(), kNanosDouble, 1);
|
||||||
|
|
||||||
|
const double kPlusInfinity = std::numeric_limits<double>::infinity();
|
||||||
|
const double kMinusInfinity = -kPlusInfinity;
|
||||||
|
|
||||||
|
EXPECT_EQ(TimeDelta::PlusInfinity().seconds<double>(), kPlusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::MinusInfinity().seconds<double>(), kMinusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::PlusInfinity().ms<double>(), kPlusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::MinusInfinity().ms<double>(), kMinusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::PlusInfinity().us<double>(), kPlusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::MinusInfinity().us<double>(), kMinusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::PlusInfinity().ns<double>(), kPlusInfinity);
|
||||||
|
EXPECT_EQ(TimeDelta::MinusInfinity().ns<double>(), kMinusInfinity);
|
||||||
|
|
||||||
|
EXPECT_TRUE(TimeDelta::seconds(kPlusInfinity).IsPlusInfinity());
|
||||||
|
EXPECT_TRUE(TimeDelta::seconds(kMinusInfinity).IsMinusInfinity());
|
||||||
|
EXPECT_TRUE(TimeDelta::ms(kPlusInfinity).IsPlusInfinity());
|
||||||
|
EXPECT_TRUE(TimeDelta::ms(kMinusInfinity).IsMinusInfinity());
|
||||||
|
EXPECT_TRUE(TimeDelta::us(kPlusInfinity).IsPlusInfinity());
|
||||||
|
EXPECT_TRUE(TimeDelta::us(kMinusInfinity).IsMinusInfinity());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(TimeDeltaTest, MathOperations) {
|
TEST(TimeDeltaTest, MathOperations) {
|
||||||
const int64_t kValueA = 267;
|
const int64_t kValueA = 267;
|
||||||
const int64_t kValueB = 450;
|
const int64_t kValueB = 450;
|
||||||
@ -94,6 +139,9 @@ TEST(TimeDeltaTest, MathOperations) {
|
|||||||
EXPECT_EQ((TimeDelta::us(kValueA) * kInt32Value).us(), kValueA * kInt32Value);
|
EXPECT_EQ((TimeDelta::us(kValueA) * kInt32Value).us(), kValueA * kInt32Value);
|
||||||
EXPECT_EQ((TimeDelta::us(kValueA) * kFloatValue).us(), kValueA * kFloatValue);
|
EXPECT_EQ((TimeDelta::us(kValueA) * kFloatValue).us(), kValueA * kFloatValue);
|
||||||
|
|
||||||
|
EXPECT_EQ((delta_b / 10).ms(), kValueB / 10);
|
||||||
|
EXPECT_EQ(delta_b / delta_a, static_cast<double>(kValueB) / kValueA);
|
||||||
|
|
||||||
EXPECT_EQ(TimeDelta::us(-kValueA).Abs().us(), kValueA);
|
EXPECT_EQ(TimeDelta::us(-kValueA).Abs().us(), kValueA);
|
||||||
EXPECT_EQ(TimeDelta::us(kValueA).Abs().us(), kValueA);
|
EXPECT_EQ(TimeDelta::us(kValueA).Abs().us(), kValueA);
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,6 @@
|
|||||||
#include "rtc_base/strings/string_builder.h"
|
#include "rtc_base/strings/string_builder.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
double Timestamp::SecondsAsDouble() const {
|
|
||||||
if (IsInfinite()) {
|
|
||||||
return std::numeric_limits<double>::infinity();
|
|
||||||
} else {
|
|
||||||
return us() * 1e-6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToString(const Timestamp& value) {
|
std::string ToString(const Timestamp& value) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
rtc::SimpleStringBuilder sb(buf);
|
rtc::SimpleStringBuilder sb(buf);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/numerics/safe_conversions.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace timestamp_impl {
|
namespace timestamp_impl {
|
||||||
@ -34,22 +35,94 @@ class Timestamp {
|
|||||||
static Timestamp Infinity() {
|
static Timestamp Infinity() {
|
||||||
return Timestamp(timestamp_impl::kPlusInfinityVal);
|
return Timestamp(timestamp_impl::kPlusInfinityVal);
|
||||||
}
|
}
|
||||||
static Timestamp seconds(int64_t seconds) {
|
|
||||||
return Timestamp::us(seconds * 1000000);
|
template <
|
||||||
}
|
typename T,
|
||||||
static Timestamp ms(int64_t millis) { return Timestamp::us(millis * 1000); }
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
static Timestamp us(int64_t micros) {
|
static Timestamp seconds(T seconds) {
|
||||||
RTC_DCHECK_GE(micros, 0);
|
RTC_DCHECK_GE(seconds, 0);
|
||||||
return Timestamp(micros);
|
RTC_DCHECK_LT(seconds, timestamp_impl::kPlusInfinityVal / 1000000);
|
||||||
}
|
return Timestamp(rtc::dchecked_cast<int64_t>(seconds) * 1000000);
|
||||||
int64_t seconds() const { return (us() + 500000) / 1000000; }
|
|
||||||
int64_t ms() const { return (us() + 500) / 1000; }
|
|
||||||
int64_t us() const {
|
|
||||||
RTC_DCHECK(IsFinite());
|
|
||||||
return microseconds_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double SecondsAsDouble() const;
|
template <
|
||||||
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static Timestamp ms(T milliseconds) {
|
||||||
|
RTC_DCHECK_GE(milliseconds, 0);
|
||||||
|
RTC_DCHECK_LT(milliseconds, timestamp_impl::kPlusInfinityVal / 1000);
|
||||||
|
return Timestamp(rtc::dchecked_cast<int64_t>(milliseconds) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
||||||
|
static Timestamp us(T microseconds) {
|
||||||
|
RTC_DCHECK_GE(microseconds, 0);
|
||||||
|
RTC_DCHECK_LT(microseconds, timestamp_impl::kPlusInfinityVal);
|
||||||
|
return Timestamp(rtc::dchecked_cast<int64_t>(microseconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static Timestamp seconds(T seconds) {
|
||||||
|
return Timestamp::us(seconds * 1e6);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static Timestamp ms(T milliseconds) {
|
||||||
|
return Timestamp::us(milliseconds * 1e3);
|
||||||
|
}
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type* =
|
||||||
|
nullptr>
|
||||||
|
static Timestamp us(T microseconds) {
|
||||||
|
if (microseconds == std::numeric_limits<double>::infinity()) {
|
||||||
|
return Infinity();
|
||||||
|
} else {
|
||||||
|
RTC_DCHECK(!std::isnan(microseconds));
|
||||||
|
RTC_DCHECK_GE(microseconds, 0);
|
||||||
|
RTC_DCHECK_LT(microseconds, timestamp_impl::kPlusInfinityVal);
|
||||||
|
return Timestamp(rtc::dchecked_cast<int64_t>(microseconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type seconds() const {
|
||||||
|
return rtc::dchecked_cast<T>((us() + 500000) / 1000000);
|
||||||
|
}
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type ms() const {
|
||||||
|
return rtc::dchecked_cast<T>((us() + 500) / 1000);
|
||||||
|
}
|
||||||
|
template <typename T = int64_t>
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type us() const {
|
||||||
|
RTC_DCHECK(IsFinite());
|
||||||
|
return rtc::dchecked_cast<T>(microseconds_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type seconds()
|
||||||
|
const {
|
||||||
|
return us<T>() * 1e-6;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type ms()
|
||||||
|
const {
|
||||||
|
return us<T>() * 1e-3;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type us()
|
||||||
|
const {
|
||||||
|
if (IsInfinite()) {
|
||||||
|
return std::numeric_limits<T>::infinity();
|
||||||
|
} else {
|
||||||
|
return microseconds_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsInfinite() const {
|
bool IsInfinite() const {
|
||||||
return microseconds_ == timestamp_impl::kPlusInfinityVal;
|
return microseconds_ == timestamp_impl::kPlusInfinityVal;
|
||||||
|
@ -58,6 +58,39 @@ TEST(TimestampTest, ComparisonOperators) {
|
|||||||
EXPECT_GT(Timestamp::ms(kLarge), Timestamp::ms(kSmall));
|
EXPECT_GT(Timestamp::ms(kLarge), Timestamp::ms(kSmall));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TimestampTest, CanBeInititializedFromLargeInt) {
|
||||||
|
const int kMaxInt = std::numeric_limits<int>::max();
|
||||||
|
EXPECT_EQ(Timestamp::seconds(kMaxInt).us(),
|
||||||
|
static_cast<int64_t>(kMaxInt) * 1000000);
|
||||||
|
EXPECT_EQ(Timestamp::ms(kMaxInt).us(), static_cast<int64_t>(kMaxInt) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimestampTest, ConvertsToAndFromDouble) {
|
||||||
|
const int64_t kMicros = 17017;
|
||||||
|
const double kMicrosDouble = kMicros;
|
||||||
|
const double kMillisDouble = kMicros * 1e-3;
|
||||||
|
const double kSecondsDouble = kMillisDouble * 1e-3;
|
||||||
|
|
||||||
|
EXPECT_EQ(Timestamp::us(kMicros).seconds<double>(), kSecondsDouble);
|
||||||
|
EXPECT_EQ(Timestamp::seconds(kSecondsDouble).us(), kMicros);
|
||||||
|
|
||||||
|
EXPECT_EQ(Timestamp::us(kMicros).ms<double>(), kMillisDouble);
|
||||||
|
EXPECT_EQ(Timestamp::ms(kMillisDouble).us(), kMicros);
|
||||||
|
|
||||||
|
EXPECT_EQ(Timestamp::us(kMicros).us<double>(), kMicrosDouble);
|
||||||
|
EXPECT_EQ(Timestamp::us(kMicrosDouble).us(), kMicros);
|
||||||
|
|
||||||
|
const double kPlusInfinity = std::numeric_limits<double>::infinity();
|
||||||
|
|
||||||
|
EXPECT_EQ(Timestamp::Infinity().seconds<double>(), kPlusInfinity);
|
||||||
|
EXPECT_EQ(Timestamp::Infinity().ms<double>(), kPlusInfinity);
|
||||||
|
EXPECT_EQ(Timestamp::Infinity().us<double>(), kPlusInfinity);
|
||||||
|
|
||||||
|
EXPECT_TRUE(Timestamp::seconds(kPlusInfinity).IsInfinite());
|
||||||
|
EXPECT_TRUE(Timestamp::ms(kPlusInfinity).IsInfinite());
|
||||||
|
EXPECT_TRUE(Timestamp::us(kPlusInfinity).IsInfinite());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(UnitConversionTest, TimestampAndTimeDeltaMath) {
|
TEST(UnitConversionTest, TimestampAndTimeDeltaMath) {
|
||||||
const int64_t kValueA = 267;
|
const int64_t kValueA = 267;
|
||||||
const int64_t kValueB = 450;
|
const int64_t kValueB = 450;
|
||||||
|
Reference in New Issue
Block a user