1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef META_BASE_TIMESPAN_H 17 #define META_BASE_TIMESPAN_H 18 19 #include <stdint.h> 20 21 #include <meta/base/meta_types.h> 22 #include <meta/base/namespace.h> 23 META_BEGIN_NAMESPACE()24META_BEGIN_NAMESPACE() 25 26 /** 27 * @brief Microsecond precision time span type. 28 * The int64_t min and max values are used to mark infinities. 29 */ 30 class TimeSpan final { 31 public: 32 constexpr TimeSpan() : value_(0) {} 33 34 ~TimeSpan() = default; 35 36 constexpr TimeSpan(const TimeSpan& rhs) noexcept = default; 37 constexpr TimeSpan(TimeSpan&& rhs) noexcept = default; 38 39 constexpr TimeSpan& operator=(const TimeSpan& rhs) noexcept = default; 40 constexpr TimeSpan& operator=(TimeSpan&& rhs) noexcept = default; 41 42 constexpr int64_t ToSeconds() const noexcept 43 { 44 return value_ / 1000000; 45 } 46 47 constexpr float ToSecondsFloat() const noexcept 48 { 49 return static_cast<float>(value_) / 1000000.0f; 50 } 51 52 constexpr int64_t ToMilliseconds() const noexcept 53 { 54 return Round(static_cast<float>(value_) / 1000.f); 55 } 56 57 constexpr int64_t ToMicroseconds() const noexcept 58 { 59 return value_; 60 } 61 62 constexpr void SetSeconds(float seconds) noexcept 63 { 64 value_ = ToMicroseconds(seconds); 65 } 66 67 constexpr void SetMilliseconds(int64_t milliseconds) noexcept 68 { 69 value_ = milliseconds * 1000; 70 } 71 72 constexpr void SetMicroseconds(int64_t microseconds) noexcept 73 { 74 value_ = microseconds; 75 } 76 77 constexpr bool IsFinite() const 78 { 79 return value_ != INT64_MIN && value_ != INT64_MAX; 80 } 81 82 static constexpr TimeSpan Seconds(float seconds) noexcept 83 { 84 return TimeSpan(ToMicroseconds(seconds)); 85 } 86 87 static constexpr TimeSpan Milliseconds(int64_t milliseconds) noexcept 88 { 89 return TimeSpan(milliseconds * 1000); 90 } 91 92 static constexpr TimeSpan Microseconds(int64_t microseconds) noexcept 93 { 94 return TimeSpan(microseconds); 95 } 96 97 static constexpr TimeSpan Max() noexcept 98 { 99 return TimeSpan(INT64_MAX); 100 } 101 102 static constexpr TimeSpan Zero() noexcept 103 { 104 return TimeSpan(0); 105 } 106 107 static constexpr TimeSpan Infinite() noexcept 108 { 109 return TimeSpan(INT64_MAX); 110 } 111 112 constexpr bool operator==(const TimeSpan& rhs) const noexcept 113 { 114 return value_ == rhs.value_; 115 } 116 117 constexpr bool operator!=(const TimeSpan& rhs) const noexcept 118 { 119 return value_ != rhs.value_; 120 } 121 122 constexpr bool operator<(const TimeSpan& rhs) const noexcept 123 { 124 return value_ < rhs.value_; 125 } 126 127 constexpr bool operator>(const TimeSpan& rhs) const noexcept 128 { 129 return value_ > rhs.value_; 130 } 131 132 constexpr bool operator>=(const TimeSpan& rhs) const noexcept 133 { 134 return value_ >= rhs.value_; 135 } 136 137 constexpr bool operator<=(const TimeSpan& rhs) const noexcept 138 { 139 return value_ <= rhs.value_; 140 } 141 142 constexpr TimeSpan operator-() const noexcept 143 { 144 TimeSpan result; 145 146 if (*this == Infinite()) { 147 result = TimeSpan(INT64_MIN); 148 } else if (value_ == INT64_MIN) { 149 result = TimeSpan::Infinite(); 150 } else { 151 result = TimeSpan(-value_); 152 } 153 154 return result; 155 } 156 157 constexpr TimeSpan operator+(const TimeSpan& rhs) const noexcept 158 { 159 TimeSpan result; 160 161 if (value_ == INT64_MAX || rhs.value_ == INT64_MAX) { 162 result = Infinite(); 163 } else if (value_ == INT64_MIN || rhs.value_ == INT64_MIN) { 164 result = -Infinite(); 165 } else { 166 result = TimeSpan(value_ + rhs.value_); 167 } 168 169 return result; 170 } 171 172 constexpr TimeSpan operator*(const TimeSpan& rhs) const noexcept 173 { 174 TimeSpan result; 175 176 if (value_ == INT64_MAX || rhs.value_ == INT64_MAX) { 177 result = Infinite(); 178 } else if (value_ == INT64_MIN || rhs.value_ == INT64_MIN) { 179 result = -Infinite(); 180 } else { 181 result = TimeSpan(value_ * rhs.value_); 182 } 183 184 return result; 185 } 186 187 constexpr TimeSpan operator/(const TimeSpan& rhs) const noexcept 188 { 189 TimeSpan result; 190 191 if (value_ == INT64_MAX || rhs.value_ == INT64_MAX || rhs.value_ == 0) { 192 result = Infinite(); 193 } else if (value_ == INT64_MIN || rhs.value_ == INT64_MIN) { 194 result = -Infinite(); 195 } else { 196 result = TimeSpan(value_ / rhs.value_); 197 } 198 199 return result; 200 } 201 202 constexpr TimeSpan operator-(const TimeSpan& rhs) const noexcept 203 { 204 return *this + -rhs; 205 } 206 207 constexpr TimeSpan& operator+=(const TimeSpan& rhs) noexcept 208 { 209 *this = *this + rhs; 210 return *this; 211 } 212 213 constexpr TimeSpan& operator-=(const TimeSpan& rhs) noexcept 214 { 215 *this = *this - rhs; 216 return *this; 217 } 218 219 constexpr TimeSpan& operator*=(const TimeSpan& rhs) noexcept 220 { 221 *this = *this * rhs; 222 return *this; 223 } 224 225 constexpr TimeSpan& operator/=(const TimeSpan& rhs) noexcept 226 { 227 *this = *this / rhs; 228 return *this; 229 } 230 231 constexpr TimeSpan operator*(int n) const noexcept 232 { 233 TimeSpan result; 234 235 if (IsFinite()) { 236 result = TimeSpan(n * value_); 237 } else if (n == 0) { 238 result = Zero(); 239 } else if (n > 0) { 240 result = *this; 241 } else { 242 result = -*this; 243 } 244 245 return result; 246 } 247 248 constexpr TimeSpan operator*(float n) const noexcept 249 { 250 TimeSpan result; 251 252 if (IsFinite()) { 253 result = TimeSpan(Round(n * static_cast<float>(value_))); 254 } else if (n == 0) { 255 result = Zero(); 256 } else if (n > 0) { 257 result = *this; 258 } else { 259 result = -*this; 260 } 261 262 return result; 263 } 264 265 constexpr TimeSpan operator/(float n) const noexcept 266 { 267 TimeSpan result; 268 269 if (n == 0) { 270 result = Infinite(); 271 } else if (IsFinite()) { 272 result = TimeSpan(Round(static_cast<float>(value_) / n)); 273 } else if (n > 0) { 274 result = *this; 275 } else { 276 result = -*this; 277 } 278 279 return result; 280 } 281 282 friend constexpr TimeSpan operator*(int n, const TimeSpan& rhs) 283 { 284 return rhs * n; 285 } 286 friend constexpr TimeSpan operator*(float n, const TimeSpan& rhs) 287 { 288 return rhs * n; 289 } 290 friend constexpr TimeSpan operator/(float n, const TimeSpan& rhs) 291 { 292 return rhs / n; 293 } 294 295 private: 296 explicit constexpr TimeSpan(int64_t microseconds) : value_(microseconds) {} 297 298 static constexpr int64_t Round(float in) noexcept 299 { 300 in = in < 0 ? in - 0.5f : in + 0.5f; 301 return static_cast<int64_t>(in); 302 } 303 304 static constexpr int64_t ToMicroseconds(float seconds) noexcept 305 { 306 return Round(seconds * 1000000.0f); 307 } 308 309 private: 310 // Value stored in microseconds 311 int64_t value_ = 0; 312 }; 313 314 namespace TimeSpanLiterals { 315 constexpr TimeSpan operator"" _s(unsigned long long seconds) 316 { 317 return TimeSpan::Seconds(static_cast<float>(seconds)); 318 } 319 320 constexpr TimeSpan operator"" _ms(unsigned long long milliseconds) 321 { 322 return TimeSpan::Milliseconds(static_cast<int64_t>(milliseconds)); 323 } 324 325 constexpr TimeSpan operator"" _us(unsigned long long microseconds) 326 { 327 return TimeSpan::Microseconds(static_cast<int64_t>(microseconds)); 328 } 329 } // namespace TimeSpanLiterals 330 331 META_END_NAMESPACE() 332 333 META_TYPE(META_NS::TimeSpan) 334 335 #endif 336