/src/abseil-cpp/absl/time/duration.cc
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | // Copyright 2017 The Abseil Authors.  | 
2  |  | //  | 
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  |  | //      https://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  |  | // The implementation of the absl::Duration class, which is declared in  | 
16  |  | // //absl/time.h.  This class behaves like a numeric type; it has no public  | 
17  |  | // methods and is used only through the operators defined here.  | 
18  |  | //  | 
19  |  | // Implementation notes:  | 
20  |  | //  | 
21  |  | // An absl::Duration is represented as  | 
22  |  | //  | 
23  |  | //   rep_hi_ : (int64_t)  Whole seconds  | 
24  |  | //   rep_lo_ : (uint32_t) Fractions of a second  | 
25  |  | //  | 
26  |  | // The seconds value (rep_hi_) may be positive or negative as appropriate.  | 
27  |  | // The fractional seconds (rep_lo_) is always a positive offset from rep_hi_.  | 
28  |  | // The API for Duration guarantees at least nanosecond resolution, which  | 
29  |  | // means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds.  | 
30  |  | // However, to utilize more of the available 32 bits of space in rep_lo_,  | 
31  |  | // we instead store quarters of a nanosecond in rep_lo_ resulting in a max  | 
32  |  | // value of 4B - 1.  This allows us to correctly handle calculations like  | 
33  |  | // 0.5 nanos + 0.5 nanos = 1 nano.  The following example shows the actual  | 
34  |  | // Duration rep using quarters of a nanosecond.  | 
35  |  | //  | 
36  |  | //    2.5 sec = {rep_hi_=2,  rep_lo_=2000000000}  // lo = 4 * 500000000 | 
37  |  | //   -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000} | 
38  |  | //  | 
39  |  | // Infinite durations are represented as Durations with the rep_lo_ field set  | 
40  |  | // to all 1s.  | 
41  |  | //  | 
42  |  | //   +InfiniteDuration:  | 
43  |  | //     rep_hi_ : kint64max  | 
44  |  | //     rep_lo_ : ~0U  | 
45  |  | //  | 
46  |  | //   -InfiniteDuration:  | 
47  |  | //     rep_hi_ : kint64min  | 
48  |  | //     rep_lo_ : ~0U  | 
49  |  | //  | 
50  |  | // Arithmetic overflows/underflows to +/- infinity and saturates.  | 
51  |  |  | 
52  |  | #if defined(_MSC_VER)  | 
53  |  | #include <winsock2.h>  // for timeval  | 
54  |  | #endif  | 
55  |  |  | 
56  |  | #include <algorithm>  | 
57  |  | #include <cassert>  | 
58  |  | #include <chrono>  // NOLINT(build/c++11)  | 
59  |  | #include <cmath>  | 
60  |  | #include <cstdint>  | 
61  |  | #include <cstdlib>  | 
62  |  | #include <cstring>  | 
63  |  | #include <ctime>  | 
64  |  | #include <functional>  | 
65  |  | #include <limits>  | 
66  |  | #include <string>  | 
67  |  |  | 
68  |  | #include "absl/base/attributes.h"  | 
69  |  | #include "absl/base/casts.h"  | 
70  |  | #include "absl/base/config.h"  | 
71  |  | #include "absl/numeric/int128.h"  | 
72  |  | #include "absl/strings/string_view.h"  | 
73  |  | #include "absl/strings/strip.h"  | 
74  |  | #include "absl/time/time.h"  | 
75  |  |  | 
76  |  | namespace absl { | 
77  |  | ABSL_NAMESPACE_BEGIN  | 
78  |  |  | 
79  |  | namespace { | 
80  |  |  | 
81  |  | using time_internal::kTicksPerNanosecond;  | 
82  |  | using time_internal::kTicksPerSecond;  | 
83  |  |  | 
84  |  | constexpr int64_t kint64max = std::numeric_limits<int64_t>::max();  | 
85  |  | constexpr int64_t kint64min = std::numeric_limits<int64_t>::min();  | 
86  |  |  | 
87  |  | // Can't use std::isinfinite() because it doesn't exist on windows.  | 
88  | 0  | inline bool IsFinite(double d) { | 
89  | 0  |   if (std::isnan(d)) return false;  | 
90  | 0  |   return d != std::numeric_limits<double>::infinity() &&  | 
91  | 0  |          d != -std::numeric_limits<double>::infinity();  | 
92  | 0  | }  | 
93  |  |  | 
94  | 0  | inline bool IsValidDivisor(double d) { | 
95  | 0  |   if (std::isnan(d)) return false;  | 
96  | 0  |   return d != 0.0;  | 
97  | 0  | }  | 
98  |  |  | 
99  |  | // *sec may be positive or negative.  *ticks must be in the range  | 
100  |  | // -kTicksPerSecond < *ticks < kTicksPerSecond.  If *ticks is negative it  | 
101  |  | // will be normalized to a positive value by adjusting *sec accordingly.  | 
102  | 0  | inline void NormalizeTicks(int64_t* sec, int64_t* ticks) { | 
103  | 0  |   if (*ticks < 0) { | 
104  | 0  |     --*sec;  | 
105  | 0  |     *ticks += kTicksPerSecond;  | 
106  | 0  |   }  | 
107  | 0  | }  | 
108  |  |  | 
109  |  | // Makes a uint128 from the absolute value of the given scalar.  | 
110  | 0  | inline uint128 MakeU128(int64_t a) { | 
111  | 0  |   uint128 u128 = 0;  | 
112  | 0  |   if (a < 0) { | 
113  | 0  |     ++u128;  | 
114  | 0  |     ++a;  // Makes it safe to negate 'a'  | 
115  | 0  |     a = -a;  | 
116  | 0  |   }  | 
117  | 0  |   u128 += static_cast<uint64_t>(a);  | 
118  | 0  |   return u128;  | 
119  | 0  | }  | 
120  |  |  | 
121  |  | // Makes a uint128 count of ticks out of the absolute value of the Duration.  | 
122  | 0  | inline uint128 MakeU128Ticks(Duration d) { | 
123  | 0  |   int64_t rep_hi = time_internal::GetRepHi(d);  | 
124  | 0  |   uint32_t rep_lo = time_internal::GetRepLo(d);  | 
125  | 0  |   if (rep_hi < 0) { | 
126  | 0  |     ++rep_hi;  | 
127  | 0  |     rep_hi = -rep_hi;  | 
128  | 0  |     rep_lo = kTicksPerSecond - rep_lo;  | 
129  | 0  |   }  | 
130  | 0  |   uint128 u128 = static_cast<uint64_t>(rep_hi);  | 
131  | 0  |   u128 *= static_cast<uint64_t>(kTicksPerSecond);  | 
132  | 0  |   u128 += rep_lo;  | 
133  | 0  |   return u128;  | 
134  | 0  | }  | 
135  |  |  | 
136  |  | // Breaks a uint128 of ticks into a Duration.  | 
137  | 0  | inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) { | 
138  | 0  |   int64_t rep_hi;  | 
139  | 0  |   uint32_t rep_lo;  | 
140  | 0  |   const uint64_t h64 = Uint128High64(u128);  | 
141  | 0  |   const uint64_t l64 = Uint128Low64(u128);  | 
142  | 0  |   if (h64 == 0) {  // fastpath | 
143  | 0  |     const uint64_t hi = l64 / kTicksPerSecond;  | 
144  | 0  |     rep_hi = static_cast<int64_t>(hi);  | 
145  | 0  |     rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond);  | 
146  | 0  |   } else { | 
147  |  |     // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond).  | 
148  |  |     // Any positive tick count whose high 64 bits are >= kMaxRepHi64  | 
149  |  |     // is not representable as a Duration.  A negative tick count can  | 
150  |  |     // have its high 64 bits == kMaxRepHi64 but only when the low 64  | 
151  |  |     // bits are all zero, otherwise it is not representable either.  | 
152  | 0  |     const uint64_t kMaxRepHi64 = 0x77359400UL;  | 
153  | 0  |     if (h64 >= kMaxRepHi64) { | 
154  | 0  |       if (is_neg && h64 == kMaxRepHi64 && l64 == 0) { | 
155  |  |         // Avoid trying to represent -kint64min below.  | 
156  | 0  |         return time_internal::MakeDuration(kint64min);  | 
157  | 0  |       }  | 
158  | 0  |       return is_neg ? -InfiniteDuration() : InfiniteDuration();  | 
159  | 0  |     }  | 
160  | 0  |     const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond);  | 
161  | 0  |     const uint128 hi = u128 / kTicksPerSecond128;  | 
162  | 0  |     rep_hi = static_cast<int64_t>(Uint128Low64(hi));  | 
163  | 0  |     rep_lo =  | 
164  | 0  |         static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128));  | 
165  | 0  |   }  | 
166  | 0  |   if (is_neg) { | 
167  | 0  |     rep_hi = -rep_hi;  | 
168  | 0  |     if (rep_lo != 0) { | 
169  | 0  |       --rep_hi;  | 
170  | 0  |       rep_lo = kTicksPerSecond - rep_lo;  | 
171  | 0  |     }  | 
172  | 0  |   }  | 
173  | 0  |   return time_internal::MakeDuration(rep_hi, rep_lo);  | 
174  | 0  | }  | 
175  |  |  | 
176  |  | // Convert between int64_t and uint64_t, preserving representation. This  | 
177  |  | // allows us to do arithmetic in the unsigned domain, where overflow has  | 
178  |  | // well-defined behavior. See operator+=() and operator-=().  | 
179  |  | //  | 
180  |  | // C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef  | 
181  |  | // name intN_t designates a signed integer type with width N, no padding  | 
182  |  | // bits, and a two's complement representation." So, we can convert to  | 
183  |  | // and from the corresponding uint64_t value using a bit cast.  | 
184  | 0  | inline uint64_t EncodeTwosComp(int64_t v) { | 
185  | 0  |   return absl::bit_cast<uint64_t>(v);  | 
186  | 0  | }  | 
187  | 0  | inline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); } | 
188  |  |  | 
189  |  | // Note: The overflow detection in this function is done using greater/less *or  | 
190  |  | // equal* because kint64max/min is too large to be represented exactly in a  | 
191  |  | // double (which only has 53 bits of precision). In order to avoid assigning to  | 
192  |  | // rep->hi a double value that is too large for an int64_t (and therefore is  | 
193  |  | // undefined), we must consider computations that equal kint64max/min as a  | 
194  |  | // double as overflow cases.  | 
195  | 0  | inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) { | 
196  | 0  |   double c = a_hi + b_hi;  | 
197  | 0  |   if (c >= static_cast<double>(kint64max)) { | 
198  | 0  |     *d = InfiniteDuration();  | 
199  | 0  |     return false;  | 
200  | 0  |   }  | 
201  | 0  |   if (c <= static_cast<double>(kint64min)) { | 
202  | 0  |     *d = -InfiniteDuration();  | 
203  | 0  |     return false;  | 
204  | 0  |   }  | 
205  | 0  |   *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d));  | 
206  | 0  |   return true;  | 
207  | 0  | }  | 
208  |  |  | 
209  |  | // A functor that's similar to std::multiplies<T>, except this returns the max  | 
210  |  | // T value instead of overflowing. This is only defined for uint128.  | 
211  |  | template <typename Ignored>  | 
212  |  | struct SafeMultiply { | 
213  | 0  |   uint128 operator()(uint128 a, uint128 b) const { | 
214  |  |     // b hi is always zero because it originated as an int64_t.  | 
215  | 0  |     assert(Uint128High64(b) == 0);  | 
216  |  |     // Fastpath to avoid the expensive overflow check with division.  | 
217  | 0  |     if (Uint128High64(a) == 0) { | 
218  | 0  |       return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0)  | 
219  | 0  |                  ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b))  | 
220  | 0  |                  : a * b;  | 
221  | 0  |     }  | 
222  | 0  |     return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b;  | 
223  | 0  |   }  | 
224  |  | };  | 
225  |  |  | 
226  |  | // Scales (i.e., multiplies or divides, depending on the Operation template)  | 
227  |  | // the Duration d by the int64_t r.  | 
228  |  | template <template <typename> class Operation>  | 
229  | 0  | inline Duration ScaleFixed(Duration d, int64_t r) { | 
230  | 0  |   const uint128 a = MakeU128Ticks(d);  | 
231  | 0  |   const uint128 b = MakeU128(r);  | 
232  | 0  |   const uint128 q = Operation<uint128>()(a, b);  | 
233  | 0  |   const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0);  | 
234  | 0  |   return MakeDurationFromU128(q, is_neg);  | 
235  | 0  | } Unexecuted instantiation: duration.cc:absl::Duration absl::(anonymous namespace)::ScaleFixed<absl::(anonymous namespace)::SafeMultiply>(absl::Duration, long) Unexecuted instantiation: duration.cc:absl::Duration absl::(anonymous namespace)::ScaleFixed<std::__1::divides>(absl::Duration, long)  | 
236  |  |  | 
237  |  | // Scales (i.e., multiplies or divides, depending on the Operation template)  | 
238  |  | // the Duration d by the double r.  | 
239  |  | template <template <typename> class Operation>  | 
240  | 0  | inline Duration ScaleDouble(Duration d, double r) { | 
241  | 0  |   Operation<double> op;  | 
242  | 0  |   double hi_doub = op(time_internal::GetRepHi(d), r);  | 
243  | 0  |   double lo_doub = op(time_internal::GetRepLo(d), r);  | 
244  |  | 
  | 
245  | 0  |   double hi_int = 0;  | 
246  | 0  |   double hi_frac = std::modf(hi_doub, &hi_int);  | 
247  |  |  | 
248  |  |   // Moves hi's fractional bits to lo.  | 
249  | 0  |   lo_doub /= kTicksPerSecond;  | 
250  | 0  |   lo_doub += hi_frac;  | 
251  |  | 
  | 
252  | 0  |   double lo_int = 0;  | 
253  | 0  |   double lo_frac = std::modf(lo_doub, &lo_int);  | 
254  |  |  | 
255  |  |   // Rolls lo into hi if necessary.  | 
256  | 0  |   int64_t lo64 = std::round(lo_frac * kTicksPerSecond);  | 
257  |  | 
  | 
258  | 0  |   Duration ans;  | 
259  | 0  |   if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans;  | 
260  | 0  |   int64_t hi64 = time_internal::GetRepHi(ans);  | 
261  | 0  |   if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans;  | 
262  | 0  |   hi64 = time_internal::GetRepHi(ans);  | 
263  | 0  |   lo64 %= kTicksPerSecond;  | 
264  | 0  |   NormalizeTicks(&hi64, &lo64);  | 
265  | 0  |   return time_internal::MakeDuration(hi64, lo64);  | 
266  | 0  | } Unexecuted instantiation: duration.cc:absl::Duration absl::(anonymous namespace)::ScaleDouble<std::__1::multiplies>(absl::Duration, double) Unexecuted instantiation: duration.cc:absl::Duration absl::(anonymous namespace)::ScaleDouble<std::__1::divides>(absl::Duration, double)  | 
267  |  |  | 
268  |  | // Tries to divide num by den as fast as possible by looking for common, easy  | 
269  |  | // cases. If the division was done, the quotient is in *q and the remainder is  | 
270  |  | // in *rem and true will be returned.  | 
271  |  | inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q,  | 
272  | 0  |                          Duration* rem) { | 
273  |  |   // Bail if num or den is an infinity.  | 
274  | 0  |   if (time_internal::IsInfiniteDuration(num) ||  | 
275  | 0  |       time_internal::IsInfiniteDuration(den))  | 
276  | 0  |     return false;  | 
277  |  |  | 
278  | 0  |   int64_t num_hi = time_internal::GetRepHi(num);  | 
279  | 0  |   uint32_t num_lo = time_internal::GetRepLo(num);  | 
280  | 0  |   int64_t den_hi = time_internal::GetRepHi(den);  | 
281  | 0  |   uint32_t den_lo = time_internal::GetRepLo(den);  | 
282  |  | 
  | 
283  | 0  |   if (den_hi == 0 && den_lo == kTicksPerNanosecond) { | 
284  |  |     // Dividing by 1ns  | 
285  | 0  |     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) { | 
286  | 0  |       *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond;  | 
287  | 0  |       *rem = time_internal::MakeDuration(0, num_lo % den_lo);  | 
288  | 0  |       return true;  | 
289  | 0  |     }  | 
290  | 0  |   } else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) { | 
291  |  |     // Dividing by 100ns (common when converting to Universal time)  | 
292  | 0  |     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) { | 
293  | 0  |       *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond);  | 
294  | 0  |       *rem = time_internal::MakeDuration(0, num_lo % den_lo);  | 
295  | 0  |       return true;  | 
296  | 0  |     }  | 
297  | 0  |   } else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) { | 
298  |  |     // Dividing by 1us  | 
299  | 0  |     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) { | 
300  | 0  |       *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond);  | 
301  | 0  |       *rem = time_internal::MakeDuration(0, num_lo % den_lo);  | 
302  | 0  |       return true;  | 
303  | 0  |     }  | 
304  | 0  |   } else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) { | 
305  |  |     // Dividing by 1ms  | 
306  | 0  |     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) { | 
307  | 0  |       *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond);  | 
308  | 0  |       *rem = time_internal::MakeDuration(0, num_lo % den_lo);  | 
309  | 0  |       return true;  | 
310  | 0  |     }  | 
311  | 0  |   } else if (den_hi > 0 && den_lo == 0) { | 
312  |  |     // Dividing by positive multiple of 1s  | 
313  | 0  |     if (num_hi >= 0) { | 
314  | 0  |       if (den_hi == 1) { | 
315  | 0  |         *q = num_hi;  | 
316  | 0  |         *rem = time_internal::MakeDuration(0, num_lo);  | 
317  | 0  |         return true;  | 
318  | 0  |       }  | 
319  | 0  |       *q = num_hi / den_hi;  | 
320  | 0  |       *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo);  | 
321  | 0  |       return true;  | 
322  | 0  |     }  | 
323  | 0  |     if (num_lo != 0) { | 
324  | 0  |       num_hi += 1;  | 
325  | 0  |     }  | 
326  | 0  |     int64_t quotient = num_hi / den_hi;  | 
327  | 0  |     int64_t rem_sec = num_hi % den_hi;  | 
328  | 0  |     if (rem_sec > 0) { | 
329  | 0  |       rem_sec -= den_hi;  | 
330  | 0  |       quotient += 1;  | 
331  | 0  |     }  | 
332  | 0  |     if (num_lo != 0) { | 
333  | 0  |       rem_sec -= 1;  | 
334  | 0  |     }  | 
335  | 0  |     *q = quotient;  | 
336  | 0  |     *rem = time_internal::MakeDuration(rem_sec, num_lo);  | 
337  | 0  |     return true;  | 
338  | 0  |   }  | 
339  |  |  | 
340  | 0  |   return false;  | 
341  | 0  | }  | 
342  |  |  | 
343  |  | }  // namespace  | 
344  |  |  | 
345  |  | namespace time_internal { | 
346  |  |  | 
347  |  | // The 'satq' argument indicates whether the quotient should saturate at the  | 
348  |  | // bounds of int64_t.  If it does saturate, the difference will spill over to  | 
349  |  | // the remainder.  If it does not saturate, the remainder remain accurate,  | 
350  |  | // but the returned quotient will over/underflow int64_t and should not be used.  | 
351  |  | int64_t IDivDuration(bool satq, const Duration num, const Duration den,  | 
352  | 0  |                      Duration* rem) { | 
353  | 0  |   int64_t q = 0;  | 
354  | 0  |   if (IDivFastPath(num, den, &q, rem)) { | 
355  | 0  |     return q;  | 
356  | 0  |   }  | 
357  |  |  | 
358  | 0  |   const bool num_neg = num < ZeroDuration();  | 
359  | 0  |   const bool den_neg = den < ZeroDuration();  | 
360  | 0  |   const bool quotient_neg = num_neg != den_neg;  | 
361  |  | 
  | 
362  | 0  |   if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { | 
363  | 0  |     *rem = num_neg ? -InfiniteDuration() : InfiniteDuration();  | 
364  | 0  |     return quotient_neg ? kint64min : kint64max;  | 
365  | 0  |   }  | 
366  | 0  |   if (time_internal::IsInfiniteDuration(den)) { | 
367  | 0  |     *rem = num;  | 
368  | 0  |     return 0;  | 
369  | 0  |   }  | 
370  |  |  | 
371  | 0  |   const uint128 a = MakeU128Ticks(num);  | 
372  | 0  |   const uint128 b = MakeU128Ticks(den);  | 
373  | 0  |   uint128 quotient128 = a / b;  | 
374  |  | 
  | 
375  | 0  |   if (satq) { | 
376  |  |     // Limits the quotient to the range of int64_t.  | 
377  | 0  |     if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) { | 
378  | 0  |       quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min))  | 
379  | 0  |                                  : uint128(static_cast<uint64_t>(kint64max));  | 
380  | 0  |     }  | 
381  | 0  |   }  | 
382  |  | 
  | 
383  | 0  |   const uint128 remainder128 = a - quotient128 * b;  | 
384  | 0  |   *rem = MakeDurationFromU128(remainder128, num_neg);  | 
385  |  | 
  | 
386  | 0  |   if (!quotient_neg || quotient128 == 0) { | 
387  | 0  |     return Uint128Low64(quotient128) & kint64max;  | 
388  | 0  |   }  | 
389  |  |   // The quotient needs to be negated, but we need to carefully handle  | 
390  |  |   // quotient128s with the top bit on.  | 
391  | 0  |   return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1;  | 
392  | 0  | }  | 
393  |  |  | 
394  |  | }  // namespace time_internal  | 
395  |  |  | 
396  |  | //  | 
397  |  | // Additive operators.  | 
398  |  | //  | 
399  |  |  | 
400  | 0  | Duration& Duration::operator+=(Duration rhs) { | 
401  | 0  |   if (time_internal::IsInfiniteDuration(*this)) return *this;  | 
402  | 0  |   if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs;  | 
403  | 0  |   const int64_t orig_rep_hi = rep_hi_.Get();  | 
404  | 0  |   rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) +  | 
405  | 0  |                            EncodeTwosComp(rhs.rep_hi_.Get()));  | 
406  | 0  |   if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) { | 
407  | 0  |     rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) + 1);  | 
408  | 0  |     rep_lo_ -= kTicksPerSecond;  | 
409  | 0  |   }  | 
410  | 0  |   rep_lo_ += rhs.rep_lo_;  | 
411  | 0  |   if (rhs.rep_hi_.Get() < 0 ? rep_hi_.Get() > orig_rep_hi  | 
412  | 0  |                             : rep_hi_.Get() < orig_rep_hi) { | 
413  | 0  |     return *this =  | 
414  | 0  |                rhs.rep_hi_.Get() < 0 ? -InfiniteDuration() : InfiniteDuration();  | 
415  | 0  |   }  | 
416  | 0  |   return *this;  | 
417  | 0  | }  | 
418  |  |  | 
419  | 0  | Duration& Duration::operator-=(Duration rhs) { | 
420  | 0  |   if (time_internal::IsInfiniteDuration(*this)) return *this;  | 
421  | 0  |   if (time_internal::IsInfiniteDuration(rhs)) { | 
422  | 0  |     return *this = rhs.rep_hi_.Get() >= 0 ? -InfiniteDuration()  | 
423  | 0  |                                           : InfiniteDuration();  | 
424  | 0  |   }  | 
425  | 0  |   const int64_t orig_rep_hi = rep_hi_.Get();  | 
426  | 0  |   rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) -  | 
427  | 0  |                            EncodeTwosComp(rhs.rep_hi_.Get()));  | 
428  | 0  |   if (rep_lo_ < rhs.rep_lo_) { | 
429  | 0  |     rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) - 1);  | 
430  | 0  |     rep_lo_ += kTicksPerSecond;  | 
431  | 0  |   }  | 
432  | 0  |   rep_lo_ -= rhs.rep_lo_;  | 
433  | 0  |   if (rhs.rep_hi_.Get() < 0 ? rep_hi_.Get() < orig_rep_hi  | 
434  | 0  |                             : rep_hi_.Get() > orig_rep_hi) { | 
435  | 0  |     return *this = rhs.rep_hi_.Get() >= 0 ? -InfiniteDuration()  | 
436  | 0  |                                           : InfiniteDuration();  | 
437  | 0  |   }  | 
438  | 0  |   return *this;  | 
439  | 0  | }  | 
440  |  |  | 
441  |  | //  | 
442  |  | // Multiplicative operators.  | 
443  |  | //  | 
444  |  |  | 
445  | 0  | Duration& Duration::operator*=(int64_t r) { | 
446  | 0  |   if (time_internal::IsInfiniteDuration(*this)) { | 
447  | 0  |     const bool is_neg = (r < 0) != (rep_hi_.Get() < 0);  | 
448  | 0  |     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();  | 
449  | 0  |   }  | 
450  | 0  |   return *this = ScaleFixed<SafeMultiply>(*this, r);  | 
451  | 0  | }  | 
452  |  |  | 
453  | 0  | Duration& Duration::operator*=(double r) { | 
454  | 0  |   if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) { | 
455  | 0  |     const bool is_neg = std::signbit(r) != (rep_hi_.Get() < 0);  | 
456  | 0  |     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();  | 
457  | 0  |   }  | 
458  | 0  |   return *this = ScaleDouble<std::multiplies>(*this, r);  | 
459  | 0  | }  | 
460  |  |  | 
461  | 0  | Duration& Duration::operator/=(int64_t r) { | 
462  | 0  |   if (time_internal::IsInfiniteDuration(*this) || r == 0) { | 
463  | 0  |     const bool is_neg = (r < 0) != (rep_hi_.Get() < 0);  | 
464  | 0  |     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();  | 
465  | 0  |   }  | 
466  | 0  |   return *this = ScaleFixed<std::divides>(*this, r);  | 
467  | 0  | }  | 
468  |  |  | 
469  | 0  | Duration& Duration::operator/=(double r) { | 
470  | 0  |   if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) { | 
471  | 0  |     const bool is_neg = std::signbit(r) != (rep_hi_.Get() < 0);  | 
472  | 0  |     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();  | 
473  | 0  |   }  | 
474  | 0  |   return *this = ScaleDouble<std::divides>(*this, r);  | 
475  | 0  | }  | 
476  |  |  | 
477  | 0  | Duration& Duration::operator%=(Duration rhs) { | 
478  | 0  |   time_internal::IDivDuration(false, *this, rhs, this);  | 
479  | 0  |   return *this;  | 
480  | 0  | }  | 
481  |  |  | 
482  | 0  | double FDivDuration(Duration num, Duration den) { | 
483  |  |   // Arithmetic with infinity is sticky.  | 
484  | 0  |   if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { | 
485  | 0  |     return (num < ZeroDuration()) == (den < ZeroDuration())  | 
486  | 0  |                ? std::numeric_limits<double>::infinity()  | 
487  | 0  |                : -std::numeric_limits<double>::infinity();  | 
488  | 0  |   }  | 
489  | 0  |   if (time_internal::IsInfiniteDuration(den)) return 0.0;  | 
490  |  |  | 
491  | 0  |   double a =  | 
492  | 0  |       static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond +  | 
493  | 0  |       time_internal::GetRepLo(num);  | 
494  | 0  |   double b =  | 
495  | 0  |       static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond +  | 
496  | 0  |       time_internal::GetRepLo(den);  | 
497  | 0  |   return a / b;  | 
498  | 0  | }  | 
499  |  |  | 
500  |  | //  | 
501  |  | // Trunc/Floor/Ceil.  | 
502  |  | //  | 
503  |  |  | 
504  | 0  | Duration Trunc(Duration d, Duration unit) { | 
505  | 0  |   return d - (d % unit);  | 
506  | 0  | }  | 
507  |  |  | 
508  | 0  | Duration Floor(const Duration d, const Duration unit) { | 
509  | 0  |   const absl::Duration td = Trunc(d, unit);  | 
510  | 0  |   return td <= d ? td : td - AbsDuration(unit);  | 
511  | 0  | }  | 
512  |  |  | 
513  | 0  | Duration Ceil(const Duration d, const Duration unit) { | 
514  | 0  |   const absl::Duration td = Trunc(d, unit);  | 
515  | 0  |   return td >= d ? td : td + AbsDuration(unit);  | 
516  | 0  | }  | 
517  |  |  | 
518  |  | //  | 
519  |  | // Factory functions.  | 
520  |  | //  | 
521  |  |  | 
522  | 0  | Duration DurationFromTimespec(timespec ts) { | 
523  | 0  |   if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) { | 
524  | 0  |     int64_t ticks = ts.tv_nsec * kTicksPerNanosecond;  | 
525  | 0  |     return time_internal::MakeDuration(ts.tv_sec, ticks);  | 
526  | 0  |   }  | 
527  | 0  |   return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec);  | 
528  | 0  | }  | 
529  |  |  | 
530  | 0  | Duration DurationFromTimeval(timeval tv) { | 
531  | 0  |   if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) { | 
532  | 0  |     int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond;  | 
533  | 0  |     return time_internal::MakeDuration(tv.tv_sec, ticks);  | 
534  | 0  |   }  | 
535  | 0  |   return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec);  | 
536  | 0  | }  | 
537  |  |  | 
538  |  | //  | 
539  |  | // Conversion to other duration types.  | 
540  |  | //  | 
541  |  |  | 
542  | 0  | int64_t ToInt64Nanoseconds(Duration d) { | 
543  | 0  |   if (time_internal::GetRepHi(d) >= 0 &&  | 
544  | 0  |       time_internal::GetRepHi(d) >> 33 == 0) { | 
545  | 0  |     return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +  | 
546  | 0  |            (time_internal::GetRepLo(d) / kTicksPerNanosecond);  | 
547  | 0  |   }  | 
548  | 0  |   return d / Nanoseconds(1);  | 
549  | 0  | }  | 
550  | 0  | int64_t ToInt64Microseconds(Duration d) { | 
551  | 0  |   if (time_internal::GetRepHi(d) >= 0 &&  | 
552  | 0  |       time_internal::GetRepHi(d) >> 43 == 0) { | 
553  | 0  |     return (time_internal::GetRepHi(d) * 1000 * 1000) +  | 
554  | 0  |            (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000));  | 
555  | 0  |   }  | 
556  | 0  |   return d / Microseconds(1);  | 
557  | 0  | }  | 
558  | 0  | int64_t ToInt64Milliseconds(Duration d) { | 
559  | 0  |   if (time_internal::GetRepHi(d) >= 0 &&  | 
560  | 0  |       time_internal::GetRepHi(d) >> 53 == 0) { | 
561  | 0  |     return (time_internal::GetRepHi(d) * 1000) +  | 
562  | 0  |            (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000));  | 
563  | 0  |   }  | 
564  | 0  |   return d / Milliseconds(1);  | 
565  | 0  | }  | 
566  | 0  | int64_t ToInt64Seconds(Duration d) { | 
567  | 0  |   int64_t hi = time_internal::GetRepHi(d);  | 
568  | 0  |   if (time_internal::IsInfiniteDuration(d)) return hi;  | 
569  | 0  |   if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;  | 
570  | 0  |   return hi;  | 
571  | 0  | }  | 
572  | 0  | int64_t ToInt64Minutes(Duration d) { | 
573  | 0  |   int64_t hi = time_internal::GetRepHi(d);  | 
574  | 0  |   if (time_internal::IsInfiniteDuration(d)) return hi;  | 
575  | 0  |   if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;  | 
576  | 0  |   return hi / 60;  | 
577  | 0  | }  | 
578  | 0  | int64_t ToInt64Hours(Duration d) { | 
579  | 0  |   int64_t hi = time_internal::GetRepHi(d);  | 
580  | 0  |   if (time_internal::IsInfiniteDuration(d)) return hi;  | 
581  | 0  |   if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;  | 
582  | 0  |   return hi / (60 * 60);  | 
583  | 0  | }  | 
584  |  |  | 
585  | 0  | double ToDoubleNanoseconds(Duration d) { | 
586  | 0  |   return FDivDuration(d, Nanoseconds(1));  | 
587  | 0  | }  | 
588  | 0  | double ToDoubleMicroseconds(Duration d) { | 
589  | 0  |   return FDivDuration(d, Microseconds(1));  | 
590  | 0  | }  | 
591  | 0  | double ToDoubleMilliseconds(Duration d) { | 
592  | 0  |   return FDivDuration(d, Milliseconds(1));  | 
593  | 0  | }  | 
594  | 0  | double ToDoubleSeconds(Duration d) { | 
595  | 0  |   return FDivDuration(d, Seconds(1));  | 
596  | 0  | }  | 
597  | 0  | double ToDoubleMinutes(Duration d) { | 
598  | 0  |   return FDivDuration(d, Minutes(1));  | 
599  | 0  | }  | 
600  | 0  | double ToDoubleHours(Duration d) { | 
601  | 0  |   return FDivDuration(d, Hours(1));  | 
602  | 0  | }  | 
603  |  |  | 
604  | 0  | timespec ToTimespec(Duration d) { | 
605  | 0  |   timespec ts;  | 
606  | 0  |   if (!time_internal::IsInfiniteDuration(d)) { | 
607  | 0  |     int64_t rep_hi = time_internal::GetRepHi(d);  | 
608  | 0  |     uint32_t rep_lo = time_internal::GetRepLo(d);  | 
609  | 0  |     if (rep_hi < 0) { | 
610  |  |       // Tweak the fields so that unsigned division of rep_lo  | 
611  |  |       // maps to truncation (towards zero) for the timespec.  | 
612  | 0  |       rep_lo += kTicksPerNanosecond - 1;  | 
613  | 0  |       if (rep_lo >= kTicksPerSecond) { | 
614  | 0  |         rep_hi += 1;  | 
615  | 0  |         rep_lo -= kTicksPerSecond;  | 
616  | 0  |       }  | 
617  | 0  |     }  | 
618  | 0  |     ts.tv_sec = static_cast<decltype(ts.tv_sec)>(rep_hi);  | 
619  | 0  |     if (ts.tv_sec == rep_hi) {  // no time_t narrowing | 
620  | 0  |       ts.tv_nsec = rep_lo / kTicksPerNanosecond;  | 
621  | 0  |       return ts;  | 
622  | 0  |     }  | 
623  | 0  |   }  | 
624  | 0  |   if (d >= ZeroDuration()) { | 
625  | 0  |     ts.tv_sec = std::numeric_limits<time_t>::max();  | 
626  | 0  |     ts.tv_nsec = 1000 * 1000 * 1000 - 1;  | 
627  | 0  |   } else { | 
628  | 0  |     ts.tv_sec = std::numeric_limits<time_t>::min();  | 
629  | 0  |     ts.tv_nsec = 0;  | 
630  | 0  |   }  | 
631  | 0  |   return ts;  | 
632  | 0  | }  | 
633  |  |  | 
634  | 0  | timeval ToTimeval(Duration d) { | 
635  | 0  |   timeval tv;  | 
636  | 0  |   timespec ts = ToTimespec(d);  | 
637  | 0  |   if (ts.tv_sec < 0) { | 
638  |  |     // Tweak the fields so that positive division of tv_nsec  | 
639  |  |     // maps to truncation (towards zero) for the timeval.  | 
640  | 0  |     ts.tv_nsec += 1000 - 1;  | 
641  | 0  |     if (ts.tv_nsec >= 1000 * 1000 * 1000) { | 
642  | 0  |       ts.tv_sec += 1;  | 
643  | 0  |       ts.tv_nsec -= 1000 * 1000 * 1000;  | 
644  | 0  |     }  | 
645  | 0  |   }  | 
646  | 0  |   tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);  | 
647  | 0  |   if (tv.tv_sec != ts.tv_sec) {  // narrowing | 
648  | 0  |     if (ts.tv_sec < 0) { | 
649  | 0  |       tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();  | 
650  | 0  |       tv.tv_usec = 0;  | 
651  | 0  |     } else { | 
652  | 0  |       tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();  | 
653  | 0  |       tv.tv_usec = 1000 * 1000 - 1;  | 
654  | 0  |     }  | 
655  | 0  |     return tv;  | 
656  | 0  |   }  | 
657  | 0  |   tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);  // suseconds_t  | 
658  | 0  |   return tv;  | 
659  | 0  | }  | 
660  |  |  | 
661  | 0  | std::chrono::nanoseconds ToChronoNanoseconds(Duration d) { | 
662  | 0  |   return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d);  | 
663  | 0  | }  | 
664  | 0  | std::chrono::microseconds ToChronoMicroseconds(Duration d) { | 
665  | 0  |   return time_internal::ToChronoDuration<std::chrono::microseconds>(d);  | 
666  | 0  | }  | 
667  | 0  | std::chrono::milliseconds ToChronoMilliseconds(Duration d) { | 
668  | 0  |   return time_internal::ToChronoDuration<std::chrono::milliseconds>(d);  | 
669  | 0  | }  | 
670  | 0  | std::chrono::seconds ToChronoSeconds(Duration d) { | 
671  | 0  |   return time_internal::ToChronoDuration<std::chrono::seconds>(d);  | 
672  | 0  | }  | 
673  | 0  | std::chrono::minutes ToChronoMinutes(Duration d) { | 
674  | 0  |   return time_internal::ToChronoDuration<std::chrono::minutes>(d);  | 
675  | 0  | }  | 
676  | 0  | std::chrono::hours ToChronoHours(Duration d) { | 
677  | 0  |   return time_internal::ToChronoDuration<std::chrono::hours>(d);  | 
678  | 0  | }  | 
679  |  |  | 
680  |  | //  | 
681  |  | // To/From string formatting.  | 
682  |  | //  | 
683  |  |  | 
684  |  | namespace { | 
685  |  |  | 
686  |  | // Formats a positive 64-bit integer in the given field width.  Note that  | 
687  |  | // it is up to the caller of Format64() to ensure that there is sufficient  | 
688  |  | // space before ep to hold the conversion.  | 
689  | 0  | char* Format64(char* ep, int width, int64_t v) { | 
690  | 0  |   do { | 
691  | 0  |     --width;  | 
692  | 0  |     *--ep = static_cast<char>('0' + (v % 10));  // contiguous digits | 
693  | 0  |   } while (v /= 10);  | 
694  | 0  |   while (--width >= 0) *--ep = '0';  // zero pad  | 
695  | 0  |   return ep;  | 
696  | 0  | }  | 
697  |  |  | 
698  |  | // Helpers for FormatDuration() that format 'n' and append it to 'out'  | 
699  |  | // followed by the given 'unit'.  If 'n' formats to "0", nothing is  | 
700  |  | // appended (not even the unit).  | 
701  |  |  | 
702  |  | // A type that encapsulates how to display a value of a particular unit. For  | 
703  |  | // values that are displayed with fractional parts, the precision indicates  | 
704  |  | // where to round the value. The precision varies with the display unit because  | 
705  |  | // a Duration can hold only quarters of a nanosecond, so displaying information  | 
706  |  | // beyond that is just noise.  | 
707  |  | //  | 
708  |  | // For example, a microsecond value of 42.00025xxxxx should not display beyond 5  | 
709  |  | // fractional digits, because it is in the noise of what a Duration can  | 
710  |  | // represent.  | 
711  |  | struct DisplayUnit { | 
712  |  |   absl::string_view abbr;  | 
713  |  |   int prec;  | 
714  |  |   double pow10;  | 
715  |  | };  | 
716  |  | ABSL_CONST_INIT const DisplayUnit kDisplayNano = {"ns", 2, 1e2}; | 
717  |  | ABSL_CONST_INIT const DisplayUnit kDisplayMicro = {"us", 5, 1e5}; | 
718  |  | ABSL_CONST_INIT const DisplayUnit kDisplayMilli = {"ms", 8, 1e8}; | 
719  |  | ABSL_CONST_INIT const DisplayUnit kDisplaySec = {"s", 11, 1e11}; | 
720  |  | ABSL_CONST_INIT const DisplayUnit kDisplayMin = {"m", -1, 0.0};  // prec ignored | 
721  |  | ABSL_CONST_INIT const DisplayUnit kDisplayHour = {"h", -1, | 
722  |  |                                                   0.0};  // prec ignored  | 
723  |  |  | 
724  | 0  | void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) { | 
725  | 0  |   char buf[sizeof("2562047788015216")];  // hours in max duration | 
726  | 0  |   char* const ep = buf + sizeof(buf);  | 
727  | 0  |   char* bp = Format64(ep, 0, n);  | 
728  | 0  |   if (*bp != '0' || bp + 1 != ep) { | 
729  | 0  |     out->append(bp, static_cast<size_t>(ep - bp));  | 
730  | 0  |     out->append(unit.abbr.data(), unit.abbr.size());  | 
731  | 0  |   }  | 
732  | 0  | }  | 
733  |  |  | 
734  |  | // Note: unit.prec is limited to double's digits10 value (typically 15) so it  | 
735  |  | // always fits in buf[].  | 
736  | 0  | void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) { | 
737  | 0  |   constexpr int kBufferSize = std::numeric_limits<double>::digits10;  | 
738  | 0  |   const int prec = std::min(kBufferSize, unit.prec);  | 
739  | 0  |   char buf[kBufferSize];  // also large enough to hold integer part  | 
740  | 0  |   char* ep = buf + sizeof(buf);  | 
741  | 0  |   double d = 0;  | 
742  | 0  |   int64_t frac_part = std::round(std::modf(n, &d) * unit.pow10);  | 
743  | 0  |   int64_t int_part = d;  | 
744  | 0  |   if (int_part != 0 || frac_part != 0) { | 
745  | 0  |     char* bp = Format64(ep, 0, int_part);  // always < 1000  | 
746  | 0  |     out->append(bp, static_cast<size_t>(ep - bp));  | 
747  | 0  |     if (frac_part != 0) { | 
748  | 0  |       out->push_back('.'); | 
749  | 0  |       bp = Format64(ep, prec, frac_part);  | 
750  | 0  |       while (ep[-1] == '0') --ep;  | 
751  | 0  |       out->append(bp, static_cast<size_t>(ep - bp));  | 
752  | 0  |     }  | 
753  | 0  |     out->append(unit.abbr.data(), unit.abbr.size());  | 
754  | 0  |   }  | 
755  | 0  | }  | 
756  |  |  | 
757  |  | }  // namespace  | 
758  |  |  | 
759  |  | // From Go's doc at https://golang.org/pkg/time/#Duration.String  | 
760  |  | //   [FormatDuration] returns a string representing the duration in the  | 
761  |  | //   form "72h3m0.5s". Leading zero units are omitted.  As a special  | 
762  |  | //   case, durations less than one second format use a smaller unit  | 
763  |  | //   (milli-, micro-, or nanoseconds) to ensure that the leading digit  | 
764  |  | //   is non-zero.  | 
765  |  | // Unlike Go, we format the zero duration as 0, with no unit.  | 
766  | 0  | std::string FormatDuration(Duration d) { | 
767  | 0  |   constexpr Duration kMinDuration = Seconds(kint64min);  | 
768  | 0  |   std::string s;  | 
769  | 0  |   if (d == kMinDuration) { | 
770  |  |     // Avoid needing to negate kint64min by directly returning what the  | 
771  |  |     // following code should produce in that case.  | 
772  | 0  |     s = "-2562047788015215h30m8s";  | 
773  | 0  |     return s;  | 
774  | 0  |   }  | 
775  | 0  |   if (d < ZeroDuration()) { | 
776  | 0  |     s.append("-"); | 
777  | 0  |     d = -d;  | 
778  | 0  |   }  | 
779  | 0  |   if (d == InfiniteDuration()) { | 
780  | 0  |     s.append("inf"); | 
781  | 0  |   } else if (d < Seconds(1)) { | 
782  |  |     // Special case for durations with a magnitude < 1 second.  The duration  | 
783  |  |     // is printed as a fraction of a single unit, e.g., "1.2ms".  | 
784  | 0  |     if (d < Microseconds(1)) { | 
785  | 0  |       AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano);  | 
786  | 0  |     } else if (d < Milliseconds(1)) { | 
787  | 0  |       AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro);  | 
788  | 0  |     } else { | 
789  | 0  |       AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli);  | 
790  | 0  |     }  | 
791  | 0  |   } else { | 
792  | 0  |     AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour);  | 
793  | 0  |     AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin);  | 
794  | 0  |     AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec);  | 
795  | 0  |   }  | 
796  | 0  |   if (s.empty() || s == "-") { | 
797  | 0  |     s = "0";  | 
798  | 0  |   }  | 
799  | 0  |   return s;  | 
800  | 0  | }  | 
801  |  |  | 
802  |  | namespace { | 
803  |  |  | 
804  |  | // A helper for ParseDuration() that parses a leading number from the given  | 
805  |  | // string and stores the result in *int_part/*frac_part/*frac_scale.  The  | 
806  |  | // given string pointer is modified to point to the first unconsumed char.  | 
807  |  | bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part,  | 
808  | 0  |                            int64_t* frac_part, int64_t* frac_scale) { | 
809  | 0  |   *int_part = 0;  | 
810  | 0  |   *frac_part = 0;  | 
811  | 0  |   *frac_scale = 1;  // invariant: *frac_part < *frac_scale  | 
812  | 0  |   const char* start = *dpp;  | 
813  | 0  |   for (; *dpp != ep; *dpp += 1) { | 
814  | 0  |     const int d = **dpp - '0';  // contiguous digits  | 
815  | 0  |     if (d < 0 || 10 <= d) break;  | 
816  |  |  | 
817  | 0  |     if (*int_part > kint64max / 10) return false;  | 
818  | 0  |     *int_part *= 10;  | 
819  | 0  |     if (*int_part > kint64max - d) return false;  | 
820  | 0  |     *int_part += d;  | 
821  | 0  |   }  | 
822  | 0  |   const bool int_part_empty = (*dpp == start);  | 
823  | 0  |   if (*dpp == ep || **dpp != '.') return !int_part_empty;  | 
824  |  |  | 
825  | 0  |   for (*dpp += 1; *dpp != ep; *dpp += 1) { | 
826  | 0  |     const int d = **dpp - '0';  // contiguous digits  | 
827  | 0  |     if (d < 0 || 10 <= d) break;  | 
828  | 0  |     if (*frac_scale <= kint64max / 10) { | 
829  | 0  |       *frac_part *= 10;  | 
830  | 0  |       *frac_part += d;  | 
831  | 0  |       *frac_scale *= 10;  | 
832  | 0  |     }  | 
833  | 0  |   }  | 
834  | 0  |   return !int_part_empty || *frac_scale != 1;  | 
835  | 0  | }  | 
836  |  |  | 
837  |  | // A helper for ParseDuration() that parses a leading unit designator (e.g.,  | 
838  |  | // ns, us, ms, s, m, h) from the given string and stores the resulting unit  | 
839  |  | // in "*unit".  The given string pointer is modified to point to the first  | 
840  |  | // unconsumed char.  | 
841  | 0  | bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) { | 
842  | 0  |   size_t size = static_cast<size_t>(end - *start);  | 
843  | 0  |   switch (size) { | 
844  | 0  |     case 0:  | 
845  | 0  |       return false;  | 
846  | 0  |     default:  | 
847  | 0  |       switch (**start) { | 
848  | 0  |         case 'n':  | 
849  | 0  |           if (*(*start + 1) == 's') { | 
850  | 0  |             *start += 2;  | 
851  | 0  |             *unit = Nanoseconds(1);  | 
852  | 0  |             return true;  | 
853  | 0  |           }  | 
854  | 0  |           break;  | 
855  | 0  |         case 'u':  | 
856  | 0  |           if (*(*start + 1) == 's') { | 
857  | 0  |             *start += 2;  | 
858  | 0  |             *unit = Microseconds(1);  | 
859  | 0  |             return true;  | 
860  | 0  |           }  | 
861  | 0  |           break;  | 
862  | 0  |         case 'm':  | 
863  | 0  |           if (*(*start + 1) == 's') { | 
864  | 0  |             *start += 2;  | 
865  | 0  |             *unit = Milliseconds(1);  | 
866  | 0  |             return true;  | 
867  | 0  |           }  | 
868  | 0  |           break;  | 
869  | 0  |         default:  | 
870  | 0  |           break;  | 
871  | 0  |       }  | 
872  | 0  |       ABSL_FALLTHROUGH_INTENDED;  | 
873  | 0  |     case 1:  | 
874  | 0  |       switch (**start) { | 
875  | 0  |         case 's':  | 
876  | 0  |           *unit = Seconds(1);  | 
877  | 0  |           *start += 1;  | 
878  | 0  |           return true;  | 
879  | 0  |         case 'm':  | 
880  | 0  |           *unit = Minutes(1);  | 
881  | 0  |           *start += 1;  | 
882  | 0  |           return true;  | 
883  | 0  |         case 'h':  | 
884  | 0  |           *unit = Hours(1);  | 
885  | 0  |           *start += 1;  | 
886  | 0  |           return true;  | 
887  | 0  |         default:  | 
888  | 0  |           return false;  | 
889  | 0  |       }  | 
890  | 0  |   }  | 
891  | 0  | }  | 
892  |  |  | 
893  |  | }  // namespace  | 
894  |  |  | 
895  |  | // From Go's doc at https://golang.org/pkg/time/#ParseDuration  | 
896  |  | //   [ParseDuration] parses a duration string. A duration string is  | 
897  |  | //   a possibly signed sequence of decimal numbers, each with optional  | 
898  |  | //   fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".  | 
899  |  | //   Valid time units are "ns", "us" "ms", "s", "m", "h".  | 
900  | 0  | bool ParseDuration(absl::string_view dur_sv, Duration* d) { | 
901  | 0  |   int sign = 1;  | 
902  | 0  |   if (absl::ConsumePrefix(&dur_sv, "-")) { | 
903  | 0  |     sign = -1;  | 
904  | 0  |   } else { | 
905  | 0  |     absl::ConsumePrefix(&dur_sv, "+");  | 
906  | 0  |   }  | 
907  | 0  |   if (dur_sv.empty()) return false;  | 
908  |  |  | 
909  |  |   // Special case for a string of "0".  | 
910  | 0  |   if (dur_sv == "0") { | 
911  | 0  |     *d = ZeroDuration();  | 
912  | 0  |     return true;  | 
913  | 0  |   }  | 
914  |  |  | 
915  | 0  |   if (dur_sv == "inf") { | 
916  | 0  |     *d = sign * InfiniteDuration();  | 
917  | 0  |     return true;  | 
918  | 0  |   }  | 
919  |  |  | 
920  | 0  |   const char* start = dur_sv.data();  | 
921  | 0  |   const char* end = start + dur_sv.size();  | 
922  |  | 
  | 
923  | 0  |   Duration dur;  | 
924  | 0  |   while (start != end) { | 
925  | 0  |     int64_t int_part;  | 
926  | 0  |     int64_t frac_part;  | 
927  | 0  |     int64_t frac_scale;  | 
928  | 0  |     Duration unit;  | 
929  | 0  |     if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part,  | 
930  | 0  |                                &frac_scale) ||  | 
931  | 0  |         !ConsumeDurationUnit(&start, end, &unit)) { | 
932  | 0  |       return false;  | 
933  | 0  |     }  | 
934  | 0  |     if (int_part != 0) dur += sign * int_part * unit;  | 
935  | 0  |     if (frac_part != 0) dur += sign * frac_part * unit / frac_scale;  | 
936  | 0  |   }  | 
937  | 0  |   *d = dur;  | 
938  | 0  |   return true;  | 
939  | 0  | }  | 
940  |  |  | 
941  | 0  | bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) { | 
942  | 0  |   return ParseDuration(text, dst);  | 
943  | 0  | }  | 
944  |  |  | 
945  | 0  | std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); } | 
946  | 0  | bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { | 
947  | 0  |   return ParseDuration(text, dst);  | 
948  | 0  | }  | 
949  |  |  | 
950  | 0  | std::string UnparseFlag(Duration d) { return FormatDuration(d); } | 
951  |  |  | 
952  |  | ABSL_NAMESPACE_END  | 
953  |  | }  // namespace absl  |