libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
framecount.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cmath>
14#include <cstdint>
15#include <limits>
16#include <promeki/namespace.h>
17#include <promeki/string.h>
18#include <promeki/error.h>
19#include <promeki/result.h>
20#include <promeki/framenumber.h>
21#include <promeki/datatype.h>
22
23PROMEKI_NAMESPACE_BEGIN
24
25class DataStream;
26
80class FrameCount {
81 public:
82 PROMEKI_DATATYPE(FrameCount, DataTypeFrameCount, 1)
83
84
85 Error writeToStream(DataStream &s) const;
87 template <uint32_t V> static Result<FrameCount> readFromStream(DataStream &s);
88
90 static constexpr int64_t UnknownValue = -1;
92 static constexpr int64_t InfinityValue = -2;
93
95 static constexpr FrameCount unknown() {
96 FrameCount c;
97 c._value = UnknownValue;
98 return c;
99 }
101 static constexpr FrameCount infinity() {
102 FrameCount c;
103 c._value = InfinityValue;
104 return c;
105 }
107 static constexpr FrameCount empty() {
108 FrameCount c;
109 c._value = 0;
110 return c;
111 }
112
130 static Result<FrameCount> fromString(const String &str);
131
133 constexpr FrameCount() = default;
134
145 constexpr FrameCount(int64_t v) : _value(v < 0 ? UnknownValue : v) {}
146
148 constexpr bool isValid() const { return _value != UnknownValue; }
149
151 constexpr bool isUnknown() const { return _value == UnknownValue; }
152
154 constexpr bool isInfinite() const { return _value == InfinityValue; }
155
157 constexpr bool isFinite() const { return _value >= 0; }
158
160 constexpr bool isEmpty() const { return _value == 0; }
161
163 constexpr int64_t value() const { return _value; }
164
172 double toDouble() const {
173 if (isUnknown()) return std::numeric_limits<double>::quiet_NaN();
174 if (isInfinite()) return std::numeric_limits<double>::infinity();
175 return static_cast<double>(_value);
176 }
177
186 static Result<FrameCount> fromDouble(double v) {
187 if (std::isnan(v)) return makeResult(FrameCount::unknown());
188 if (std::isinf(v)) return makeResult(FrameCount::infinity());
189 if (v < 0.0) return makeResult(FrameCount::unknown());
190 return makeResult(FrameCount(static_cast<int64_t>(v)));
191 }
192
194 FrameCount &operator+=(int64_t n);
195
197 FrameCount &operator-=(int64_t n);
198
200 FrameCount &operator+=(const FrameCount &other);
201
203 FrameCount &operator-=(const FrameCount &other);
204
206 FrameCount &operator++() {
207 *this += 1;
208 return *this;
209 }
211 FrameCount operator++(int) {
212 FrameCount o = *this;
213 *this += 1;
214 return o;
215 }
217 FrameCount &operator--() {
218 *this -= 1;
219 return *this;
220 }
222 FrameCount operator--(int) {
223 FrameCount o = *this;
224 *this -= 1;
225 return o;
226 }
227
229 constexpr bool operator==(const FrameCount &other) const { return _value == other._value; }
231 constexpr bool operator!=(const FrameCount &other) const { return _value != other._value; }
232
240 bool operator<(const FrameCount &other) const;
242 bool operator>(const FrameCount &other) const { return other < *this; }
252 bool operator<=(const FrameCount &other) const {
253 if (isUnknown() || other.isUnknown()) return false;
254 return !(other < *this);
255 }
257 bool operator>=(const FrameCount &other) const {
258 if (isUnknown() || other.isUnknown()) return false;
259 return !(*this < other);
260 }
261
268 String toString() const;
269
271 operator String() const { return toString(); }
272
273 private:
274 int64_t _value = UnknownValue;
275};
276
288inline FrameNumber toFrameNumber(const FrameCount &c) {
289 return c.isFinite() ? FrameNumber(c.value()) : FrameNumber::unknown();
290}
291
303inline FrameCount toFrameCount(const FrameNumber &n) {
304 return n.isValid() ? FrameCount(n.value()) : FrameCount::unknown();
305}
306
308inline FrameCount operator+(FrameCount a, const FrameCount &b) {
309 a += b;
310 return a;
311}
313inline FrameCount operator-(FrameCount a, const FrameCount &b) {
314 a -= b;
315 return a;
316}
318inline FrameCount operator+(FrameCount a, int64_t n) {
319 a += n;
320 return a;
321}
323inline FrameCount operator-(FrameCount a, int64_t n) {
324 a -= n;
325 return a;
326}
328inline FrameCount operator+(int64_t n, FrameCount a) {
329 a += n;
330 return a;
331}
332
333// ----------------------------------------------------------------------
334// FrameNumber / FrameCount cross-type arithmetic.
335//
336// Defined here because framenumber.h cannot see the full FrameCount
337// definition (it forward-declares FrameCount), but framecount.h knows
338// both types. Inline so the compiler can still optimise them away.
339// ----------------------------------------------------------------------
340
342inline FrameNumber operator+(FrameNumber a, const FrameCount &c) {
343 if (a.isUnknown() || c.isUnknown() || c.isInfinite()) return FrameNumber::unknown();
344 return FrameNumber(a.value() + c.value());
345}
346
348inline FrameNumber operator-(FrameNumber a, const FrameCount &c) {
349 if (a.isUnknown() || c.isUnknown() || c.isInfinite()) return FrameNumber::unknown();
350 int64_t nv = a.value() - c.value();
351 return nv < 0 ? FrameNumber::unknown() : FrameNumber(nv);
352}
353
360inline FrameCount operator-(const FrameNumber &a, const FrameNumber &b) {
361 if (a.isUnknown() || b.isUnknown()) return FrameCount::unknown();
362 int64_t d = a.value() - b.value();
363 return d < 0 ? FrameCount::unknown() : FrameCount(d);
364}
365
366inline FrameNumber &FrameNumber::operator+=(const FrameCount &c) {
367 *this = *this + c;
368 return *this;
369}
370inline FrameNumber &FrameNumber::operator-=(const FrameCount &c) {
371 *this = *this - c;
372 return *this;
373}
374
375PROMEKI_NAMESPACE_END
376
377PROMEKI_FORMAT_VIA_TOSTRING(promeki::FrameCount);
378
387template <> struct std::hash<promeki::FrameCount> {
388 size_t operator()(const promeki::FrameCount &v) const noexcept {
389 return std::hash<int64_t>()(v.value());
390 }
391};
392
393#endif // PROMEKI_ENABLE_CORE