/work/obj-fuzz/dist/include/TimeUnits.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef TIME_UNITS_H |
8 | | #define TIME_UNITS_H |
9 | | |
10 | | #include "Intervals.h" |
11 | | #include "mozilla/CheckedInt.h" |
12 | | #include "mozilla/FloatingPoint.h" |
13 | | #include "mozilla/Maybe.h" |
14 | | #include "mozilla/TimeStamp.h" |
15 | | |
16 | | namespace mozilla { |
17 | | namespace media { |
18 | | class TimeIntervals; |
19 | | } // namespace media |
20 | | } // namespace mozilla |
21 | | // CopyChooser specialization for nsTArray |
22 | | template<> |
23 | | struct nsTArray_CopyChooser<mozilla::media::TimeIntervals> |
24 | | { |
25 | | typedef nsTArray_CopyWithConstructors<mozilla::media::TimeIntervals> Type; |
26 | | }; |
27 | | |
28 | | namespace mozilla { |
29 | | |
30 | | // Number of microseconds per second. 1e6. |
31 | | static const int64_t USECS_PER_S = 1000000; |
32 | | |
33 | | // Number of microseconds per millisecond. |
34 | | static const int64_t USECS_PER_MS = 1000; |
35 | | |
36 | | namespace media { |
37 | | |
38 | | // Number of nanoseconds per second. 1e9. |
39 | | static const int64_t NSECS_PER_S = 1000000000; |
40 | | |
41 | | // TimeUnit at present uses a CheckedInt64 as storage. |
42 | | // INT64_MAX has the special meaning of being +oo. |
43 | | class TimeUnit final |
44 | | { |
45 | | public: |
46 | | static TimeUnit FromSeconds(double aValue) |
47 | | { |
48 | | MOZ_ASSERT(!IsNaN(aValue)); |
49 | | |
50 | | if (mozilla::IsInfinite<double>(aValue)) { |
51 | | return FromInfinity(); |
52 | | } |
53 | | // Due to internal double representation, this |
54 | | // operation is not commutative, do not attempt to simplify. |
55 | | double halfUsec = .0000005; |
56 | | double val = |
57 | | (aValue <= 0 ? aValue - halfUsec : aValue + halfUsec) * USECS_PER_S; |
58 | | if (val >= double(INT64_MAX)) { |
59 | | return FromMicroseconds(INT64_MAX); |
60 | | } else if (val <= double(INT64_MIN)) { |
61 | | return FromMicroseconds(INT64_MIN); |
62 | | } else { |
63 | | return FromMicroseconds(int64_t(val)); |
64 | | } |
65 | | } |
66 | | |
67 | | static constexpr TimeUnit FromMicroseconds(int64_t aValue) |
68 | 0 | { |
69 | 0 | return TimeUnit(aValue); |
70 | 0 | } |
71 | | |
72 | | static constexpr TimeUnit FromNanoseconds(int64_t aValue) |
73 | 0 | { |
74 | 0 | return TimeUnit(aValue / 1000); |
75 | 0 | } |
76 | | |
77 | | static constexpr TimeUnit FromInfinity() { return TimeUnit(INT64_MAX); } |
78 | | |
79 | | static TimeUnit FromTimeDuration(const TimeDuration& aDuration) |
80 | 0 | { |
81 | 0 | return FromSeconds(aDuration.ToSeconds()); |
82 | 0 | } |
83 | | |
84 | | static constexpr TimeUnit Zero() { return TimeUnit(0); } |
85 | | |
86 | | static TimeUnit Invalid() |
87 | | { |
88 | | TimeUnit ret; |
89 | | ret.mValue = CheckedInt64(INT64_MAX); |
90 | | // Force an overflow to render the CheckedInt invalid. |
91 | | ret.mValue += 1; |
92 | | return ret; |
93 | | } |
94 | | |
95 | 0 | int64_t ToMicroseconds() const { return mValue.value(); } |
96 | | |
97 | 0 | int64_t ToNanoseconds() const { return mValue.value() * 1000; } |
98 | | |
99 | | double ToSeconds() const |
100 | | { |
101 | | if (IsInfinite()) { |
102 | | return PositiveInfinity<double>(); |
103 | | } |
104 | | return double(mValue.value()) / USECS_PER_S; |
105 | | } |
106 | | |
107 | | TimeDuration ToTimeDuration() const |
108 | | { |
109 | | return TimeDuration::FromMicroseconds(mValue.value()); |
110 | | } |
111 | | |
112 | | bool IsInfinite() const { return mValue.value() == INT64_MAX; } |
113 | | |
114 | | bool IsPositive() const { return mValue.value() > 0; } |
115 | | |
116 | | bool IsNegative() const { return mValue.value() < 0; } |
117 | | |
118 | | bool operator==(const TimeUnit& aOther) const |
119 | | { |
120 | | MOZ_ASSERT(IsValid() && aOther.IsValid()); |
121 | | return mValue.value() == aOther.mValue.value(); |
122 | | } |
123 | | bool operator!=(const TimeUnit& aOther) const |
124 | | { |
125 | | MOZ_ASSERT(IsValid() && aOther.IsValid()); |
126 | | return mValue.value() != aOther.mValue.value(); |
127 | | } |
128 | | bool operator>=(const TimeUnit& aOther) const |
129 | | { |
130 | | MOZ_ASSERT(IsValid() && aOther.IsValid()); |
131 | | return mValue.value() >= aOther.mValue.value(); |
132 | | } |
133 | | bool operator>(const TimeUnit& aOther) const { return !(*this <= aOther); } |
134 | | bool operator<=(const TimeUnit& aOther) const |
135 | | { |
136 | | MOZ_ASSERT(IsValid() && aOther.IsValid()); |
137 | | return mValue.value() <= aOther.mValue.value(); |
138 | | } |
139 | | bool operator<(const TimeUnit& aOther) const { return !(*this >= aOther); } |
140 | | TimeUnit operator+(const TimeUnit& aOther) const |
141 | | { |
142 | | if (IsInfinite() || aOther.IsInfinite()) { |
143 | | return FromInfinity(); |
144 | | } |
145 | | return TimeUnit(mValue + aOther.mValue); |
146 | | } |
147 | | TimeUnit operator-(const TimeUnit& aOther) const |
148 | | { |
149 | | if (IsInfinite() && !aOther.IsInfinite()) { |
150 | | return FromInfinity(); |
151 | | } |
152 | | MOZ_ASSERT(!IsInfinite() && !aOther.IsInfinite()); |
153 | | return TimeUnit(mValue - aOther.mValue); |
154 | | } |
155 | | TimeUnit& operator+=(const TimeUnit& aOther) |
156 | 0 | { |
157 | 0 | *this = *this + aOther; |
158 | 0 | return *this; |
159 | 0 | } |
160 | | TimeUnit& operator-=(const TimeUnit& aOther) |
161 | 0 | { |
162 | 0 | *this = *this - aOther; |
163 | 0 | return *this; |
164 | 0 | } |
165 | | |
166 | | template<typename T> |
167 | | TimeUnit operator*(T aVal) const |
168 | 0 | { |
169 | 0 | // See bug 853398 for the reason to block double multiplier. |
170 | 0 | // If required, use MultDouble below and with caution. |
171 | 0 | static_assert(mozilla::IsIntegral<T>::value, "Must be an integral type"); |
172 | 0 | return TimeUnit(mValue * aVal); |
173 | 0 | } |
174 | | TimeUnit MultDouble(double aVal) const |
175 | | { |
176 | | return TimeUnit::FromSeconds(ToSeconds() * aVal); |
177 | | } |
178 | | friend TimeUnit operator/(const TimeUnit& aUnit, int aVal) |
179 | | { |
180 | | return TimeUnit(aUnit.mValue / aVal); |
181 | | } |
182 | | friend TimeUnit operator%(const TimeUnit& aUnit, int aVal) |
183 | | { |
184 | | return TimeUnit(aUnit.mValue % aVal); |
185 | | } |
186 | | |
187 | | bool IsValid() const { return mValue.isValid(); } |
188 | | |
189 | | constexpr TimeUnit() |
190 | | : mValue(CheckedInt64(0)) |
191 | 0 | { |
192 | 0 | } |
193 | | |
194 | | TimeUnit(const TimeUnit&) = default; |
195 | | |
196 | | TimeUnit& operator=(const TimeUnit&) = default; |
197 | | |
198 | | private: |
199 | | explicit constexpr TimeUnit(CheckedInt64 aMicroseconds) |
200 | | : mValue(aMicroseconds) |
201 | 0 | { |
202 | 0 | } |
203 | | |
204 | | // Our internal representation is in microseconds. |
205 | | CheckedInt64 mValue; |
206 | | }; |
207 | | |
208 | | typedef Maybe<TimeUnit> NullableTimeUnit; |
209 | | |
210 | | typedef Interval<TimeUnit> TimeInterval; |
211 | | |
212 | | class TimeIntervals : public IntervalSet<TimeUnit> |
213 | | { |
214 | | public: |
215 | | typedef IntervalSet<TimeUnit> BaseType; |
216 | | |
217 | | // We can't use inherited constructors yet. So we have to duplicate all the |
218 | | // constructors found in IntervalSet base class. |
219 | | // all this could be later replaced with: |
220 | | // using IntervalSet<TimeUnit>::IntervalSet; |
221 | | |
222 | | // MOZ_IMPLICIT as we want to enable initialization in the form: |
223 | | // TimeIntervals i = ... like we would do with IntervalSet<T> i = ... |
224 | | MOZ_IMPLICIT TimeIntervals(const BaseType& aOther) |
225 | | : BaseType(aOther) |
226 | | { |
227 | | } |
228 | | MOZ_IMPLICIT TimeIntervals(BaseType&& aOther) |
229 | | : BaseType(std::move(aOther)) |
230 | | { |
231 | | } |
232 | | explicit TimeIntervals(const BaseType::ElemType& aOther) |
233 | | : BaseType(aOther) |
234 | | { |
235 | | } |
236 | | explicit TimeIntervals(BaseType::ElemType&& aOther) |
237 | | : BaseType(std::move(aOther)) |
238 | | { |
239 | | } |
240 | | |
241 | | static TimeIntervals Invalid() |
242 | 0 | { |
243 | 0 | return TimeIntervals(TimeInterval(TimeUnit::FromMicroseconds(INT64_MIN), |
244 | 0 | TimeUnit::FromMicroseconds(INT64_MIN))); |
245 | 0 | } |
246 | | bool IsInvalid() const |
247 | | { |
248 | | return Length() == 1 && Start(0).ToMicroseconds() == INT64_MIN && |
249 | | End(0).ToMicroseconds() == INT64_MIN; |
250 | | } |
251 | | |
252 | | TimeIntervals() = default; |
253 | | }; |
254 | | |
255 | | } // namespace media |
256 | | } // namespace mozilla |
257 | | |
258 | | #endif // TIME_UNITS_H |