blob: 8958b2469730cf200efa4824a88e84c6fb4ffc65 [file] [log] [blame]
Sebastian Jansson30bd4032018-04-13 13:56:17 +02001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Sebastian Jansson6fae6ec2018-05-08 10:43:18 +020011#ifndef API_UNITS_DATA_SIZE_H_
12#define API_UNITS_DATA_SIZE_H_
Sebastian Jansson30bd4032018-04-13 13:56:17 +020013
Sebastian Jansson2afd2812018-08-23 14:44:05 +020014#ifdef UNIT_TEST
15#include <ostream> // no-presubmit-check TODO(webrtc:8982)
16#endif // UNIT_TEST
17
Sebastian Jansson30bd4032018-04-13 13:56:17 +020018#include <stdint.h>
19#include <cmath>
20#include <limits>
21#include <string>
Sebastian Jansson942b3602018-05-30 15:47:44 +020022#include <type_traits>
Sebastian Jansson30bd4032018-04-13 13:56:17 +020023
24#include "rtc_base/checks.h"
Sebastian Jansson942b3602018-05-30 15:47:44 +020025#include "rtc_base/numerics/safe_conversions.h"
Sebastian Jansson30bd4032018-04-13 13:56:17 +020026
27namespace webrtc {
28namespace data_size_impl {
29constexpr int64_t kPlusInfinityVal = std::numeric_limits<int64_t>::max();
Sebastian Jansson30bd4032018-04-13 13:56:17 +020030} // namespace data_size_impl
31
Sebastian Jansson66fa5352018-04-30 16:54:57 +020032// DataSize is a class represeting a count of bytes.
Sebastian Jansson30bd4032018-04-13 13:56:17 +020033class DataSize {
34 public:
Sebastian Jansson3b69b192018-05-07 13:51:51 +020035 DataSize() = delete;
Sebastian Jansson8e064192018-08-07 12:34:33 +020036 static constexpr DataSize Zero() { return DataSize(0); }
37 static constexpr DataSize Infinity() {
Sebastian Jansson30bd4032018-04-13 13:56:17 +020038 return DataSize(data_size_impl::kPlusInfinityVal);
39 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +020040 template <int64_t bytes>
41 static constexpr DataSize Bytes() {
42 static_assert(bytes >= 0, "");
43 static_assert(bytes < data_size_impl::kPlusInfinityVal, "");
44 return DataSize(bytes);
45 }
Sebastian Jansson942b3602018-05-30 15:47:44 +020046
47 template <
48 typename T,
49 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
50 static DataSize bytes(T bytes) {
Sebastian Jansson30bd4032018-04-13 13:56:17 +020051 RTC_DCHECK_GE(bytes, 0);
Sebastian Jansson942b3602018-05-30 15:47:44 +020052 RTC_DCHECK_LT(bytes, data_size_impl::kPlusInfinityVal);
53 return DataSize(rtc::dchecked_cast<int64_t>(bytes));
Sebastian Jansson30bd4032018-04-13 13:56:17 +020054 }
Sebastian Jansson942b3602018-05-30 15:47:44 +020055
56 template <typename T,
57 typename std::enable_if<std::is_floating_point<T>::value>::type* =
58 nullptr>
59 static DataSize bytes(T bytes) {
60 if (bytes == std::numeric_limits<T>::infinity()) {
61 return Infinity();
62 } else {
63 RTC_DCHECK(!std::isnan(bytes));
64 RTC_DCHECK_GE(bytes, 0);
65 RTC_DCHECK_LT(bytes, data_size_impl::kPlusInfinityVal);
66 return DataSize(rtc::dchecked_cast<int64_t>(bytes));
67 }
68 }
69
70 template <typename T = int64_t>
71 typename std::enable_if<std::is_integral<T>::value, T>::type bytes() const {
Sebastian Jansson30bd4032018-04-13 13:56:17 +020072 RTC_DCHECK(IsFinite());
Sebastian Jansson942b3602018-05-30 15:47:44 +020073 return rtc::dchecked_cast<T>(bytes_);
Sebastian Jansson30bd4032018-04-13 13:56:17 +020074 }
Sebastian Jansson942b3602018-05-30 15:47:44 +020075
76 template <typename T>
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +020077 constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
78 bytes() const {
79 return IsInfinite() ? std::numeric_limits<T>::infinity() : bytes_;
80 }
81
82 constexpr int64_t bytes_or(int64_t fallback_value) const {
83 return IsFinite() ? bytes_ : fallback_value;
Sebastian Jansson942b3602018-05-30 15:47:44 +020084 }
85
Sebastian Jansson8e064192018-08-07 12:34:33 +020086 constexpr bool IsZero() const { return bytes_ == 0; }
87 constexpr bool IsInfinite() const {
88 return bytes_ == data_size_impl::kPlusInfinityVal;
89 }
90 constexpr bool IsFinite() const { return !IsInfinite(); }
Sebastian Jansson30bd4032018-04-13 13:56:17 +020091 DataSize operator-(const DataSize& other) const {
92 return DataSize::bytes(bytes() - other.bytes());
93 }
94 DataSize operator+(const DataSize& other) const {
95 return DataSize::bytes(bytes() + other.bytes());
96 }
Sebastian Jansson30bd4032018-04-13 13:56:17 +020097 DataSize& operator-=(const DataSize& other) {
Sebastian Janssonaf21eab2018-09-04 18:34:45 +020098 *this = *this - other;
Sebastian Jansson30bd4032018-04-13 13:56:17 +020099 return *this;
100 }
101 DataSize& operator+=(const DataSize& other) {
Sebastian Janssonaf21eab2018-09-04 18:34:45 +0200102 *this = *this + other;
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200103 return *this;
104 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +0200105 constexpr double operator/(const DataSize& other) const {
Sebastian Jansson942b3602018-05-30 15:47:44 +0200106 return bytes<double>() / other.bytes<double>();
107 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +0200108 constexpr bool operator==(const DataSize& other) const {
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200109 return bytes_ == other.bytes_;
110 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +0200111 constexpr bool operator!=(const DataSize& other) const {
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200112 return bytes_ != other.bytes_;
113 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +0200114 constexpr bool operator<=(const DataSize& other) const {
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200115 return bytes_ <= other.bytes_;
116 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +0200117 constexpr bool operator>=(const DataSize& other) const {
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200118 return bytes_ >= other.bytes_;
119 }
Sebastian Janssonc1c8b8e2018-08-07 15:29:04 +0200120 constexpr bool operator>(const DataSize& other) const {
121 return bytes_ > other.bytes_;
122 }
123 constexpr bool operator<(const DataSize& other) const {
124 return bytes_ < other.bytes_;
125 }
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200126
127 private:
Sebastian Jansson8e064192018-08-07 12:34:33 +0200128 explicit constexpr DataSize(int64_t bytes) : bytes_(bytes) {}
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200129 int64_t bytes_;
130};
Sebastian Jansson942b3602018-05-30 15:47:44 +0200131
Sebastian Jansson66fa5352018-04-30 16:54:57 +0200132inline DataSize operator*(const DataSize& size, const double& scalar) {
133 return DataSize::bytes(std::round(size.bytes() * scalar));
134}
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200135inline DataSize operator*(const double& scalar, const DataSize& size) {
136 return size * scalar;
137}
Sebastian Jansson66fa5352018-04-30 16:54:57 +0200138inline DataSize operator*(const DataSize& size, const int64_t& scalar) {
139 return DataSize::bytes(size.bytes() * scalar);
140}
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200141inline DataSize operator*(const int64_t& scalar, const DataSize& size) {
142 return size * scalar;
143}
Sebastian Jansson66fa5352018-04-30 16:54:57 +0200144inline DataSize operator*(const DataSize& size, const int32_t& scalar) {
145 return DataSize::bytes(size.bytes() * scalar);
146}
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200147inline DataSize operator*(const int32_t& scalar, const DataSize& size) {
148 return size * scalar;
149}
Sebastian Jansson66fa5352018-04-30 16:54:57 +0200150inline DataSize operator/(const DataSize& size, const int64_t& scalar) {
151 return DataSize::bytes(size.bytes() / scalar);
152}
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200153
154std::string ToString(const DataSize& value);
155
Sebastian Jansson2afd2812018-08-23 14:44:05 +0200156#ifdef UNIT_TEST
157inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982)
158 std::ostream& stream, // no-presubmit-check TODO(webrtc:8982)
159 DataSize value) {
160 return stream << ToString(value);
161}
162#endif // UNIT_TEST
163
Sebastian Jansson30bd4032018-04-13 13:56:17 +0200164} // namespace webrtc
165
Sebastian Jansson6fae6ec2018-05-08 10:43:18 +0200166#endif // API_UNITS_DATA_SIZE_H_