e43ec4cf98f51b4f3568d74965a32b841706c88c
[WebKit-https.git] / Source / WTF / wtf / Seconds.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef WTF_Seconds_h
27 #define WTF_Seconds_h
28
29 #include <wtf/MathExtras.h>
30 #include <wtf/Optional.h>
31
32 namespace WTF {
33
34 class MonotonicTime;
35 class PrintStream;
36 class TimeWithDynamicClockType;
37 class WallTime;
38
39 class Seconds {
40 public:
41     constexpr Seconds() { }
42     
43     explicit constexpr Seconds(double value)
44         : m_value(value)
45     {
46     }
47     
48     constexpr double value() const { return m_value; }
49     
50     constexpr double minutes() const { return m_value / 60; }
51     constexpr double seconds() const { return m_value; }
52     constexpr double milliseconds() const { return seconds() * 1000; }
53     constexpr double microseconds() const { return milliseconds() * 1000; }
54     constexpr double nanoseconds() const { return microseconds() * 1000; }
55
56     // Keep in mind that Seconds is held in double. If the value is not in range of 53bit integer, the result may not be precise.
57     template<typename T> T minutesAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(minutes()); }
58     template<typename T> T secondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(seconds()); }
59     template<typename T> T millisecondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(milliseconds()); }
60     template<typename T> T microsecondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(microseconds()); }
61     template<typename T> T nanosecondsAs() const { static_assert(std::is_integral<T>::value, ""); return clampToAccepting64<T>(nanoseconds()); }
62     
63     static constexpr Seconds fromMinutes(double minutes)
64     {
65         return Seconds(minutes * 60);
66     }
67
68     static constexpr Seconds fromHours(double hours)
69     {
70         return Seconds(hours * 3600);
71     }
72
73     static constexpr Seconds fromMilliseconds(double milliseconds)
74     {
75         return Seconds(milliseconds / 1000);
76     }
77     
78     static constexpr Seconds fromMicroseconds(double microseconds)
79     {
80         return fromMilliseconds(microseconds / 1000);
81     }
82     
83     static constexpr Seconds fromNanoseconds(double nanoseconds)
84     {
85         return fromMicroseconds(nanoseconds / 1000);
86     }
87     
88     static constexpr Seconds infinity()
89     {
90         return Seconds(std::numeric_limits<double>::infinity());
91     }
92
93     static constexpr Seconds nan()
94     {
95         return Seconds(std::numeric_limits<double>::quiet_NaN());
96     }
97     
98     explicit constexpr operator bool() const { return !!m_value; }
99     
100     constexpr Seconds operator+(Seconds other) const
101     {
102         return Seconds(value() + other.value());
103     }
104     
105     constexpr Seconds operator-(Seconds other) const
106     {
107         return Seconds(value() - other.value());
108     }
109     
110     constexpr Seconds operator-() const
111     {
112         return Seconds(-value());
113     }
114     
115     // It makes sense to consider scaling a duration, like, "I want to wait 5 times as long as
116     // last time!".
117     constexpr Seconds operator*(double scalar) const
118     {
119         return Seconds(value() * scalar);
120     }
121     
122     constexpr Seconds operator/(double scalar) const
123     {
124         return Seconds(value() / scalar);
125     }
126     
127     // It's reasonable to think about ratios between Seconds.
128     constexpr double operator/(Seconds other) const
129     {
130         return value() / other.value();
131     }
132     
133     Seconds operator%(double scalar) const
134     {
135         return Seconds(fmod(value(), scalar));
136     }
137     
138     // This solves for r, where:
139     //
140     //     floor(this / other) + r / other = this / other
141     //
142     // Therefore, if this is Seconds then r is Seconds.
143     Seconds operator%(Seconds other) const
144     {
145         return Seconds(fmod(value(), other.value()));
146     }
147     
148     Seconds& operator+=(Seconds other)
149     {
150         return *this = *this + other;
151     }
152     
153     Seconds& operator-=(Seconds other)
154     {
155         return *this = *this - other;
156     }
157     
158     Seconds& operator*=(double scalar)
159     {
160         return *this = *this * scalar;
161     }
162     
163     Seconds& operator/=(double scalar)
164     {
165         return *this = *this / scalar;
166     }
167     
168     Seconds& operator%=(double scalar)
169     {
170         return *this = *this % scalar;
171     }
172     
173     Seconds& operator%=(Seconds other)
174     {
175         return *this = *this % other;
176     }
177     
178     WTF_EXPORT_PRIVATE WallTime operator+(WallTime) const;
179     WTF_EXPORT_PRIVATE MonotonicTime operator+(MonotonicTime) const;
180     WTF_EXPORT_PRIVATE TimeWithDynamicClockType operator+(const TimeWithDynamicClockType&) const;
181     
182     WTF_EXPORT_PRIVATE WallTime operator-(WallTime) const;
183     WTF_EXPORT_PRIVATE MonotonicTime operator-(MonotonicTime) const;
184     WTF_EXPORT_PRIVATE TimeWithDynamicClockType operator-(const TimeWithDynamicClockType&) const;
185     
186     constexpr bool operator==(Seconds other) const
187     {
188         return m_value == other.m_value;
189     }
190     
191     constexpr bool operator!=(Seconds other) const
192     {
193         return m_value != other.m_value;
194     }
195     
196     constexpr bool operator<(Seconds other) const
197     {
198         return m_value < other.m_value;
199     }
200     
201     constexpr bool operator>(Seconds other) const
202     {
203         return m_value > other.m_value;
204     }
205     
206     constexpr bool operator<=(Seconds other) const
207     {
208         return m_value <= other.m_value;
209     }
210     
211     constexpr bool operator>=(Seconds other) const
212     {
213         return m_value >= other.m_value;
214     }
215     
216     WTF_EXPORT_PRIVATE void dump(PrintStream&) const;
217     
218     Seconds isolatedCopy() const
219     {
220         return *this;
221     }
222
223     template<class Encoder>
224     void encode(Encoder& encoder) const
225     {
226         encoder << m_value;
227     }
228
229     template<class Decoder>
230     static std::optional<Seconds> decode(Decoder& decoder)
231     {
232         std::optional<double> seconds;
233         decoder >> seconds;
234         if (!seconds)
235             return std::nullopt;
236         return Seconds(*seconds);
237     }
238
239     template<class Decoder>
240     static bool decode(Decoder& decoder, Seconds& seconds)
241     {
242         double value;
243         if (!decoder.decode(value))
244             return false;
245
246         seconds = Seconds(value);
247         return true;
248     }
249
250 private:
251     double m_value { 0 };
252 };
253
254 inline namespace seconds_literals {
255
256 constexpr Seconds operator"" _min(long double minutes)
257 {
258     return Seconds::fromMinutes(minutes);
259 }
260
261 constexpr Seconds operator"" _h(long double hours)
262 {
263     return Seconds::fromHours(hours);
264 }
265
266 constexpr Seconds operator"" _s(long double seconds)
267 {
268     return Seconds(seconds);
269 }
270
271 constexpr Seconds operator"" _ms(long double milliseconds)
272 {
273     return Seconds::fromMilliseconds(milliseconds);
274 }
275
276 constexpr Seconds operator"" _us(long double microseconds)
277 {
278     return Seconds::fromMicroseconds(microseconds);
279 }
280
281 constexpr Seconds operator"" _ns(long double nanoseconds)
282 {
283     return Seconds::fromNanoseconds(nanoseconds);
284 }
285
286 constexpr Seconds operator"" _min(unsigned long long minutes)
287 {
288     return Seconds::fromMinutes(minutes);
289 }
290
291 constexpr Seconds operator"" _h(unsigned long long hours)
292 {
293     return Seconds::fromHours(hours);
294 }
295
296 constexpr Seconds operator"" _s(unsigned long long seconds)
297 {
298     return Seconds(seconds);
299 }
300
301 constexpr Seconds operator"" _ms(unsigned long long milliseconds)
302 {
303     return Seconds::fromMilliseconds(milliseconds);
304 }
305
306 constexpr Seconds operator"" _us(unsigned long long microseconds)
307 {
308     return Seconds::fromMicroseconds(microseconds);
309 }
310
311 constexpr Seconds operator"" _ns(unsigned long long nanoseconds)
312 {
313     return Seconds::fromNanoseconds(nanoseconds);
314 }
315
316 } // inline seconds_literals
317
318 } // namespace WTF
319
320 namespace std {
321
322 inline bool isnan(WTF::Seconds seconds)
323 {
324     return std::isnan(seconds.value());
325 }
326
327 inline bool isinf(WTF::Seconds seconds)
328 {
329     return std::isinf(seconds.value());
330 }
331
332 inline bool isfinite(WTF::Seconds seconds)
333 {
334     return std::isfinite(seconds.value());
335 }
336
337 } // namespace std
338
339 using namespace WTF::seconds_literals;
340 using WTF::Seconds;
341
342 #endif // WTF_Seconds_h