duration.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 // The implementation of the absl::Duration class, which is declared in
00016 // //absl/time.h.  This class behaves like a numeric type; it has no public
00017 // methods and is used only through the operators defined here.
00018 //
00019 // Implementation notes:
00020 //
00021 // An absl::Duration is represented as
00022 //
00023 //   rep_hi_ : (int64_t)  Whole seconds
00024 //   rep_lo_ : (uint32_t) Fractions of a second
00025 //
00026 // The seconds value (rep_hi_) may be positive or negative as appropriate.
00027 // The fractional seconds (rep_lo_) is always a positive offset from rep_hi_.
00028 // The API for Duration guarantees at least nanosecond resolution, which
00029 // means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds.
00030 // However, to utilize more of the available 32 bits of space in rep_lo_,
00031 // we instead store quarters of a nanosecond in rep_lo_ resulting in a max
00032 // value of 4B - 1.  This allows us to correctly handle calculations like
00033 // 0.5 nanos + 0.5 nanos = 1 nano.  The following example shows the actual
00034 // Duration rep using quarters of a nanosecond.
00035 //
00036 //    2.5 sec = {rep_hi_=2,  rep_lo_=2000000000}  // lo = 4 * 500000000
00037 //   -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000}
00038 //
00039 // Infinite durations are represented as Durations with the rep_lo_ field set
00040 // to all 1s.
00041 //
00042 //   +InfiniteDuration:
00043 //     rep_hi_ : kint64max
00044 //     rep_lo_ : ~0U
00045 //
00046 //   -InfiniteDuration:
00047 //     rep_hi_ : kint64min
00048 //     rep_lo_ : ~0U
00049 //
00050 // Arithmetic overflows/underflows to +/- infinity and saturates.
00051 
00052 #include <algorithm>
00053 #include <cassert>
00054 #include <cctype>
00055 #include <cerrno>
00056 #include <cmath>
00057 #include <cstdint>
00058 #include <cstdlib>
00059 #include <cstring>
00060 #include <ctime>
00061 #include <functional>
00062 #include <limits>
00063 #include <string>
00064 
00065 #include "absl/base/casts.h"
00066 #include "absl/numeric/int128.h"
00067 #include "absl/time/time.h"
00068 
00069 namespace absl {
00070 
00071 namespace {
00072 
00073 using time_internal::kTicksPerNanosecond;
00074 using time_internal::kTicksPerSecond;
00075 
00076 constexpr int64_t kint64max = std::numeric_limits<int64_t>::max();
00077 constexpr int64_t kint64min = std::numeric_limits<int64_t>::min();
00078 
00079 // Can't use std::isinfinite() because it doesn't exist on windows.
00080 inline bool IsFinite(double d) {
00081   if (std::isnan(d)) return false;
00082   return d != std::numeric_limits<double>::infinity() &&
00083          d != -std::numeric_limits<double>::infinity();
00084 }
00085 
00086 inline bool IsValidDivisor(double d) {
00087   if (std::isnan(d)) return false;
00088   return d != 0.0;
00089 }
00090 
00091 // Can't use std::round() because it is only available in C++11.
00092 // Note that we ignore the possibility of floating-point over/underflow.
00093 template <typename Double>
00094 inline double Round(Double d) {
00095   return d < 0 ? std::ceil(d - 0.5) : std::floor(d + 0.5);
00096 }
00097 
00098 // *sec may be positive or negative.  *ticks must be in the range
00099 // -kTicksPerSecond < *ticks < kTicksPerSecond.  If *ticks is negative it
00100 // will be normalized to a positive value by adjusting *sec accordingly.
00101 inline void NormalizeTicks(int64_t* sec, int64_t* ticks) {
00102   if (*ticks < 0) {
00103     --*sec;
00104     *ticks += kTicksPerSecond;
00105   }
00106 }
00107 
00108 // Makes a uint128 from the absolute value of the given scalar.
00109 inline uint128 MakeU128(int64_t a) {
00110   uint128 u128 = 0;
00111   if (a < 0) {
00112     ++u128;
00113     ++a;  // Makes it safe to negate 'a'
00114     a = -a;
00115   }
00116   u128 += static_cast<uint64_t>(a);
00117   return u128;
00118 }
00119 
00120 // Makes a uint128 count of ticks out of the absolute value of the Duration.
00121 inline uint128 MakeU128Ticks(Duration d) {
00122   int64_t rep_hi = time_internal::GetRepHi(d);
00123   uint32_t rep_lo = time_internal::GetRepLo(d);
00124   if (rep_hi < 0) {
00125     ++rep_hi;
00126     rep_hi = -rep_hi;
00127     rep_lo = kTicksPerSecond - rep_lo;
00128   }
00129   uint128 u128 = static_cast<uint64_t>(rep_hi);
00130   u128 *= static_cast<uint64_t>(kTicksPerSecond);
00131   u128 += rep_lo;
00132   return u128;
00133 }
00134 
00135 // Breaks a uint128 of ticks into a Duration.
00136 inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) {
00137   int64_t rep_hi;
00138   uint32_t rep_lo;
00139   const uint64_t h64 = Uint128High64(u128);
00140   const uint64_t l64 = Uint128Low64(u128);
00141   if (h64 == 0) {  // fastpath
00142     const uint64_t hi = l64 / kTicksPerSecond;
00143     rep_hi = static_cast<int64_t>(hi);
00144     rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond);
00145   } else {
00146     // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond).
00147     // Any positive tick count whose high 64 bits are >= kMaxRepHi64
00148     // is not representable as a Duration.  A negative tick count can
00149     // have its high 64 bits == kMaxRepHi64 but only when the low 64
00150     // bits are all zero, otherwise it is not representable either.
00151     const uint64_t kMaxRepHi64 = 0x77359400UL;
00152     if (h64 >= kMaxRepHi64) {
00153       if (is_neg && h64 == kMaxRepHi64 && l64 == 0) {
00154         // Avoid trying to represent -kint64min below.
00155         return time_internal::MakeDuration(kint64min);
00156       }
00157       return is_neg ? -InfiniteDuration() : InfiniteDuration();
00158     }
00159     const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond);
00160     const uint128 hi = u128 / kTicksPerSecond128;
00161     rep_hi = static_cast<int64_t>(Uint128Low64(hi));
00162     rep_lo =
00163         static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128));
00164   }
00165   if (is_neg) {
00166     rep_hi = -rep_hi;
00167     if (rep_lo != 0) {
00168       --rep_hi;
00169       rep_lo = kTicksPerSecond - rep_lo;
00170     }
00171   }
00172   return time_internal::MakeDuration(rep_hi, rep_lo);
00173 }
00174 
00175 // Convert between int64_t and uint64_t, preserving representation. This
00176 // allows us to do arithmetic in the unsigned domain, where overflow has
00177 // well-defined behavior. See operator+=() and operator-=().
00178 //
00179 // C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef
00180 // name intN_t designates a signed integer type with width N, no padding
00181 // bits, and a two's complement representation." So, we can convert to
00182 // and from the corresponding uint64_t value using a bit cast.
00183 inline uint64_t EncodeTwosComp(int64_t v) {
00184   return absl::bit_cast<uint64_t>(v);
00185 }
00186 inline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); }
00187 
00188 // Note: The overflow detection in this function is done using greater/less *or
00189 // equal* because kint64max/min is too large to be represented exactly in a
00190 // double (which only has 53 bits of precision). In order to avoid assigning to
00191 // rep->hi a double value that is too large for an int64_t (and therefore is
00192 // undefined), we must consider computations that equal kint64max/min as a
00193 // double as overflow cases.
00194 inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) {
00195   double c = a_hi + b_hi;
00196   if (c >= kint64max) {
00197     *d = InfiniteDuration();
00198     return false;
00199   }
00200   if (c <= kint64min) {
00201     *d = -InfiniteDuration();
00202     return false;
00203   }
00204   *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d));
00205   return true;
00206 }
00207 
00208 // A functor that's similar to std::multiplies<T>, except this returns the max
00209 // T value instead of overflowing. This is only defined for uint128.
00210 template <typename Ignored>
00211 struct SafeMultiply {
00212   uint128 operator()(uint128 a, uint128 b) const {
00213     // b hi is always zero because it originated as an int64_t.
00214     assert(Uint128High64(b) == 0);
00215     // Fastpath to avoid the expensive overflow check with division.
00216     if (Uint128High64(a) == 0) {
00217       return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0)
00218                  ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b))
00219                  : a * b;
00220     }
00221     return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b;
00222   }
00223 };
00224 
00225 // Scales (i.e., multiplies or divides, depending on the Operation template)
00226 // the Duration d by the int64_t r.
00227 template <template <typename> class Operation>
00228 inline Duration ScaleFixed(Duration d, int64_t r) {
00229   const uint128 a = MakeU128Ticks(d);
00230   const uint128 b = MakeU128(r);
00231   const uint128 q = Operation<uint128>()(a, b);
00232   const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0);
00233   return MakeDurationFromU128(q, is_neg);
00234 }
00235 
00236 // Scales (i.e., multiplies or divides, depending on the Operation template)
00237 // the Duration d by the double r.
00238 template <template <typename> class Operation>
00239 inline Duration ScaleDouble(Duration d, double r) {
00240   Operation<double> op;
00241   double hi_doub = op(time_internal::GetRepHi(d), r);
00242   double lo_doub = op(time_internal::GetRepLo(d), r);
00243 
00244   double hi_int = 0;
00245   double hi_frac = std::modf(hi_doub, &hi_int);
00246 
00247   // Moves hi's fractional bits to lo.
00248   lo_doub /= kTicksPerSecond;
00249   lo_doub += hi_frac;
00250 
00251   double lo_int = 0;
00252   double lo_frac = std::modf(lo_doub, &lo_int);
00253 
00254   // Rolls lo into hi if necessary.
00255   int64_t lo64 = Round(lo_frac * kTicksPerSecond);
00256 
00257   Duration ans;
00258   if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans;
00259   int64_t hi64 = time_internal::GetRepHi(ans);
00260   if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans;
00261   hi64 = time_internal::GetRepHi(ans);
00262   lo64 %= kTicksPerSecond;
00263   NormalizeTicks(&hi64, &lo64);
00264   return time_internal::MakeDuration(hi64, lo64);
00265 }
00266 
00267 // Tries to divide num by den as fast as possible by looking for common, easy
00268 // cases. If the division was done, the quotient is in *q and the remainder is
00269 // in *rem and true will be returned.
00270 inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q,
00271                          Duration* rem) {
00272   // Bail if num or den is an infinity.
00273   if (time_internal::IsInfiniteDuration(num) ||
00274       time_internal::IsInfiniteDuration(den))
00275     return false;
00276 
00277   int64_t num_hi = time_internal::GetRepHi(num);
00278   uint32_t num_lo = time_internal::GetRepLo(num);
00279   int64_t den_hi = time_internal::GetRepHi(den);
00280   uint32_t den_lo = time_internal::GetRepLo(den);
00281 
00282   if (den_hi == 0 && den_lo == kTicksPerNanosecond) {
00283     // Dividing by 1ns
00284     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) {
00285       *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond;
00286       *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00287       return true;
00288     }
00289   } else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) {
00290     // Dividing by 100ns (common when converting to Universal time)
00291     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) {
00292       *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond);
00293       *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00294       return true;
00295     }
00296   } else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) {
00297     // Dividing by 1us
00298     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) {
00299       *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond);
00300       *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00301       return true;
00302     }
00303   } else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) {
00304     // Dividing by 1ms
00305     if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) {
00306       *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond);
00307       *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00308       return true;
00309     }
00310   } else if (den_hi > 0 && den_lo == 0) {
00311     // Dividing by positive multiple of 1s
00312     if (num_hi >= 0) {
00313       if (den_hi == 1) {
00314         *q = num_hi;
00315         *rem = time_internal::MakeDuration(0, num_lo);
00316         return true;
00317       }
00318       *q = num_hi / den_hi;
00319       *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo);
00320       return true;
00321     }
00322     if (num_lo != 0) {
00323       num_hi += 1;
00324     }
00325     int64_t quotient = num_hi / den_hi;
00326     int64_t rem_sec = num_hi % den_hi;
00327     if (rem_sec > 0) {
00328       rem_sec -= den_hi;
00329       quotient += 1;
00330     }
00331     if (num_lo != 0) {
00332       rem_sec -= 1;
00333     }
00334     *q = quotient;
00335     *rem = time_internal::MakeDuration(rem_sec, num_lo);
00336     return true;
00337   }
00338 
00339   return false;
00340 }
00341 
00342 }  // namespace
00343 
00344 namespace time_internal {
00345 
00346 // The 'satq' argument indicates whether the quotient should saturate at the
00347 // bounds of int64_t.  If it does saturate, the difference will spill over to
00348 // the remainder.  If it does not saturate, the remainder remain accurate,
00349 // but the returned quotient will over/underflow int64_t and should not be used.
00350 int64_t IDivDuration(bool satq, const Duration num, const Duration den,
00351                    Duration* rem) {
00352   int64_t q = 0;
00353   if (IDivFastPath(num, den, &q, rem)) {
00354     return q;
00355   }
00356 
00357   const bool num_neg = num < ZeroDuration();
00358   const bool den_neg = den < ZeroDuration();
00359   const bool quotient_neg = num_neg != den_neg;
00360 
00361   if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {
00362     *rem = num_neg ? -InfiniteDuration() : InfiniteDuration();
00363     return quotient_neg ? kint64min : kint64max;
00364   }
00365   if (time_internal::IsInfiniteDuration(den)) {
00366     *rem = num;
00367     return 0;
00368   }
00369 
00370   const uint128 a = MakeU128Ticks(num);
00371   const uint128 b = MakeU128Ticks(den);
00372   uint128 quotient128 = a / b;
00373 
00374   if (satq) {
00375     // Limits the quotient to the range of int64_t.
00376     if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) {
00377       quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min))
00378                                  : uint128(static_cast<uint64_t>(kint64max));
00379     }
00380   }
00381 
00382   const uint128 remainder128 = a - quotient128 * b;
00383   *rem = MakeDurationFromU128(remainder128, num_neg);
00384 
00385   if (!quotient_neg || quotient128 == 0) {
00386     return Uint128Low64(quotient128) & kint64max;
00387   }
00388   // The quotient needs to be negated, but we need to carefully handle
00389   // quotient128s with the top bit on.
00390   return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1;
00391 }
00392 
00393 }  // namespace time_internal
00394 
00395 //
00396 // Additive operators.
00397 //
00398 
00399 Duration& Duration::operator+=(Duration rhs) {
00400   if (time_internal::IsInfiniteDuration(*this)) return *this;
00401   if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs;
00402   const int64_t orig_rep_hi = rep_hi_;
00403   rep_hi_ =
00404       DecodeTwosComp(EncodeTwosComp(rep_hi_) + EncodeTwosComp(rhs.rep_hi_));
00405   if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) {
00406     rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) + 1);
00407     rep_lo_ -= kTicksPerSecond;
00408   }
00409   rep_lo_ += rhs.rep_lo_;
00410   if (rhs.rep_hi_ < 0 ? rep_hi_ > orig_rep_hi : rep_hi_ < orig_rep_hi) {
00411     return *this = rhs.rep_hi_ < 0 ? -InfiniteDuration() : InfiniteDuration();
00412   }
00413   return *this;
00414 }
00415 
00416 Duration& Duration::operator-=(Duration rhs) {
00417   if (time_internal::IsInfiniteDuration(*this)) return *this;
00418   if (time_internal::IsInfiniteDuration(rhs)) {
00419     return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration();
00420   }
00421   const int64_t orig_rep_hi = rep_hi_;
00422   rep_hi_ =
00423       DecodeTwosComp(EncodeTwosComp(rep_hi_) - EncodeTwosComp(rhs.rep_hi_));
00424   if (rep_lo_ < rhs.rep_lo_) {
00425     rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) - 1);
00426     rep_lo_ += kTicksPerSecond;
00427   }
00428   rep_lo_ -= rhs.rep_lo_;
00429   if (rhs.rep_hi_ < 0 ? rep_hi_ < orig_rep_hi : rep_hi_ > orig_rep_hi) {
00430     return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration();
00431   }
00432   return *this;
00433 }
00434 
00435 //
00436 // Multiplicative operators.
00437 //
00438 
00439 Duration& Duration::operator*=(int64_t r) {
00440   if (time_internal::IsInfiniteDuration(*this)) {
00441     const bool is_neg = (r < 0) != (rep_hi_ < 0);
00442     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00443   }
00444   return *this = ScaleFixed<SafeMultiply>(*this, r);
00445 }
00446 
00447 Duration& Duration::operator*=(double r) {
00448   if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) {
00449     const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
00450     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00451   }
00452   return *this = ScaleDouble<std::multiplies>(*this, r);
00453 }
00454 
00455 Duration& Duration::operator/=(int64_t r) {
00456   if (time_internal::IsInfiniteDuration(*this) || r == 0) {
00457     const bool is_neg = (r < 0) != (rep_hi_ < 0);
00458     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00459   }
00460   return *this = ScaleFixed<std::divides>(*this, r);
00461 }
00462 
00463 Duration& Duration::operator/=(double r) {
00464   if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) {
00465     const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
00466     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00467   }
00468   return *this = ScaleDouble<std::divides>(*this, r);
00469 }
00470 
00471 Duration& Duration::operator%=(Duration rhs) {
00472   time_internal::IDivDuration(false, *this, rhs, this);
00473   return *this;
00474 }
00475 
00476 double FDivDuration(Duration num, Duration den) {
00477   // Arithmetic with infinity is sticky.
00478   if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {
00479     return (num < ZeroDuration()) == (den < ZeroDuration())
00480                ? std::numeric_limits<double>::infinity()
00481                : -std::numeric_limits<double>::infinity();
00482   }
00483   if (time_internal::IsInfiniteDuration(den)) return 0.0;
00484 
00485   double a =
00486       static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond +
00487       time_internal::GetRepLo(num);
00488   double b =
00489       static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond +
00490       time_internal::GetRepLo(den);
00491   return a / b;
00492 }
00493 
00494 //
00495 // Trunc/Floor/Ceil.
00496 //
00497 
00498 Duration Trunc(Duration d, Duration unit) {
00499   return d - (d % unit);
00500 }
00501 
00502 Duration Floor(const Duration d, const Duration unit) {
00503   const absl::Duration td = Trunc(d, unit);
00504   return td <= d ? td : td - AbsDuration(unit);
00505 }
00506 
00507 Duration Ceil(const Duration d, const Duration unit) {
00508   const absl::Duration td = Trunc(d, unit);
00509   return td >= d ? td : td + AbsDuration(unit);
00510 }
00511 
00512 //
00513 // Factory functions.
00514 //
00515 
00516 Duration DurationFromTimespec(timespec ts) {
00517   if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) {
00518     int64_t ticks = ts.tv_nsec * kTicksPerNanosecond;
00519     return time_internal::MakeDuration(ts.tv_sec, ticks);
00520   }
00521   return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec);
00522 }
00523 
00524 Duration DurationFromTimeval(timeval tv) {
00525   if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) {
00526     int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond;
00527     return time_internal::MakeDuration(tv.tv_sec, ticks);
00528   }
00529   return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec);
00530 }
00531 
00532 //
00533 // Conversion to other duration types.
00534 //
00535 
00536 int64_t ToInt64Nanoseconds(Duration d) {
00537   if (time_internal::GetRepHi(d) >= 0 &&
00538       time_internal::GetRepHi(d) >> 33 == 0) {
00539     return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +
00540            (time_internal::GetRepLo(d) / kTicksPerNanosecond);
00541   }
00542   return d / Nanoseconds(1);
00543 }
00544 int64_t ToInt64Microseconds(Duration d) {
00545   if (time_internal::GetRepHi(d) >= 0 &&
00546       time_internal::GetRepHi(d) >> 43 == 0) {
00547     return (time_internal::GetRepHi(d) * 1000 * 1000) +
00548            (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000));
00549   }
00550   return d / Microseconds(1);
00551 }
00552 int64_t ToInt64Milliseconds(Duration d) {
00553   if (time_internal::GetRepHi(d) >= 0 &&
00554       time_internal::GetRepHi(d) >> 53 == 0) {
00555     return (time_internal::GetRepHi(d) * 1000) +
00556            (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000));
00557   }
00558   return d / Milliseconds(1);
00559 }
00560 int64_t ToInt64Seconds(Duration d) {
00561   int64_t hi = time_internal::GetRepHi(d);
00562   if (time_internal::IsInfiniteDuration(d)) return hi;
00563   if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
00564   return hi;
00565 }
00566 int64_t ToInt64Minutes(Duration d) {
00567   int64_t hi = time_internal::GetRepHi(d);
00568   if (time_internal::IsInfiniteDuration(d)) return hi;
00569   if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
00570   return hi / 60;
00571 }
00572 int64_t ToInt64Hours(Duration d) {
00573   int64_t hi = time_internal::GetRepHi(d);
00574   if (time_internal::IsInfiniteDuration(d)) return hi;
00575   if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
00576   return hi / (60 * 60);
00577 }
00578 
00579 double ToDoubleNanoseconds(Duration d) {
00580   return FDivDuration(d, Nanoseconds(1));
00581 }
00582 double ToDoubleMicroseconds(Duration d) {
00583   return FDivDuration(d, Microseconds(1));
00584 }
00585 double ToDoubleMilliseconds(Duration d) {
00586   return FDivDuration(d, Milliseconds(1));
00587 }
00588 double ToDoubleSeconds(Duration d) {
00589   return FDivDuration(d, Seconds(1));
00590 }
00591 double ToDoubleMinutes(Duration d) {
00592   return FDivDuration(d, Minutes(1));
00593 }
00594 double ToDoubleHours(Duration d) {
00595   return FDivDuration(d, Hours(1));
00596 }
00597 
00598 timespec ToTimespec(Duration d) {
00599   timespec ts;
00600   if (!time_internal::IsInfiniteDuration(d)) {
00601     int64_t rep_hi = time_internal::GetRepHi(d);
00602     uint32_t rep_lo = time_internal::GetRepLo(d);
00603     if (rep_hi < 0) {
00604       // Tweak the fields so that unsigned division of rep_lo
00605       // maps to truncation (towards zero) for the timespec.
00606       rep_lo += kTicksPerNanosecond - 1;
00607       if (rep_lo >= kTicksPerSecond) {
00608         rep_hi += 1;
00609         rep_lo -= kTicksPerSecond;
00610       }
00611     }
00612     ts.tv_sec = rep_hi;
00613     if (ts.tv_sec == rep_hi) {  // no time_t narrowing
00614       ts.tv_nsec = rep_lo / kTicksPerNanosecond;
00615       return ts;
00616     }
00617   }
00618   if (d >= ZeroDuration()) {
00619     ts.tv_sec = std::numeric_limits<time_t>::max();
00620     ts.tv_nsec = 1000 * 1000 * 1000 - 1;
00621   } else {
00622     ts.tv_sec = std::numeric_limits<time_t>::min();
00623     ts.tv_nsec = 0;
00624   }
00625   return ts;
00626 }
00627 
00628 timeval ToTimeval(Duration d) {
00629   timeval tv;
00630   timespec ts = ToTimespec(d);
00631   if (ts.tv_sec < 0) {
00632     // Tweak the fields so that positive division of tv_nsec
00633     // maps to truncation (towards zero) for the timeval.
00634     ts.tv_nsec += 1000 - 1;
00635     if (ts.tv_nsec >= 1000 * 1000 * 1000) {
00636       ts.tv_sec += 1;
00637       ts.tv_nsec -= 1000 * 1000 * 1000;
00638     }
00639   }
00640   tv.tv_sec = ts.tv_sec;
00641   if (tv.tv_sec != ts.tv_sec) {  // narrowing
00642     if (ts.tv_sec < 0) {
00643       tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
00644       tv.tv_usec = 0;
00645     } else {
00646       tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
00647       tv.tv_usec = 1000 * 1000 - 1;
00648     }
00649     return tv;
00650   }
00651   tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);  // suseconds_t
00652   return tv;
00653 }
00654 
00655 std::chrono::nanoseconds ToChronoNanoseconds(Duration d) {
00656   return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d);
00657 }
00658 std::chrono::microseconds ToChronoMicroseconds(Duration d) {
00659   return time_internal::ToChronoDuration<std::chrono::microseconds>(d);
00660 }
00661 std::chrono::milliseconds ToChronoMilliseconds(Duration d) {
00662   return time_internal::ToChronoDuration<std::chrono::milliseconds>(d);
00663 }
00664 std::chrono::seconds ToChronoSeconds(Duration d) {
00665   return time_internal::ToChronoDuration<std::chrono::seconds>(d);
00666 }
00667 std::chrono::minutes ToChronoMinutes(Duration d) {
00668   return time_internal::ToChronoDuration<std::chrono::minutes>(d);
00669 }
00670 std::chrono::hours ToChronoHours(Duration d) {
00671   return time_internal::ToChronoDuration<std::chrono::hours>(d);
00672 }
00673 
00674 //
00675 // To/From string formatting.
00676 //
00677 
00678 namespace {
00679 
00680 // Formats a positive 64-bit integer in the given field width.  Note that
00681 // it is up to the caller of Format64() to ensure that there is sufficient
00682 // space before ep to hold the conversion.
00683 char* Format64(char* ep, int width, int64_t v) {
00684   do {
00685     --width;
00686     *--ep = '0' + (v % 10);  // contiguous digits
00687   } while (v /= 10);
00688   while (--width >= 0) *--ep = '0';  // zero pad
00689   return ep;
00690 }
00691 
00692 // Helpers for FormatDuration() that format 'n' and append it to 'out'
00693 // followed by the given 'unit'.  If 'n' formats to "0", nothing is
00694 // appended (not even the unit).
00695 
00696 // A type that encapsulates how to display a value of a particular unit. For
00697 // values that are displayed with fractional parts, the precision indicates
00698 // where to round the value. The precision varies with the display unit because
00699 // a Duration can hold only quarters of a nanosecond, so displaying information
00700 // beyond that is just noise.
00701 //
00702 // For example, a microsecond value of 42.00025xxxxx should not display beyond 5
00703 // fractional digits, because it is in the noise of what a Duration can
00704 // represent.
00705 struct DisplayUnit {
00706   const char* abbr;
00707   int prec;
00708   double pow10;
00709 };
00710 const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
00711 const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
00712 const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
00713 const DisplayUnit kDisplaySec = {"s", 11, 1e11};
00714 const DisplayUnit kDisplayMin = {"m", -1, 0.0};   // prec ignored
00715 const DisplayUnit kDisplayHour = {"h", -1, 0.0};  // prec ignored
00716 
00717 void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
00718   char buf[sizeof("2562047788015216")];  // hours in max duration
00719   char* const ep = buf + sizeof(buf);
00720   char* bp = Format64(ep, 0, n);
00721   if (*bp != '0' || bp + 1 != ep) {
00722     out->append(bp, ep - bp);
00723     out->append(unit.abbr);
00724   }
00725 }
00726 
00727 // Note: unit.prec is limited to double's digits10 value (typically 15) so it
00728 // always fits in buf[].
00729 void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
00730   const int buf_size = std::numeric_limits<double>::digits10;
00731   const int prec = std::min(buf_size, unit.prec);
00732   char buf[buf_size];  // also large enough to hold integer part
00733   char* ep = buf + sizeof(buf);
00734   double d = 0;
00735   int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);
00736   int64_t int_part = d;
00737   if (int_part != 0 || frac_part != 0) {
00738     char* bp = Format64(ep, 0, int_part);  // always < 1000
00739     out->append(bp, ep - bp);
00740     if (frac_part != 0) {
00741       out->push_back('.');
00742       bp = Format64(ep, prec, frac_part);
00743       while (ep[-1] == '0') --ep;
00744       out->append(bp, ep - bp);
00745     }
00746     out->append(unit.abbr);
00747   }
00748 }
00749 
00750 }  // namespace
00751 
00752 // From Go's doc at https://golang.org/pkg/time/#Duration.String
00753 //   [FormatDuration] returns a string representing the duration in the
00754 //   form "72h3m0.5s". Leading zero units are omitted.  As a special
00755 //   case, durations less than one second format use a smaller unit
00756 //   (milli-, micro-, or nanoseconds) to ensure that the leading digit
00757 //   is non-zero.  The zero duration formats as 0, with no unit.
00758 std::string FormatDuration(Duration d) {
00759   const Duration min_duration = Seconds(kint64min);
00760   if (d == min_duration) {
00761     // Avoid needing to negate kint64min by directly returning what the
00762     // following code should produce in that case.
00763     return "-2562047788015215h30m8s";
00764   }
00765   std::string s;
00766   if (d < ZeroDuration()) {
00767     s.append("-");
00768     d = -d;
00769   }
00770   if (d == InfiniteDuration()) {
00771     s.append("inf");
00772   } else if (d < Seconds(1)) {
00773     // Special case for durations with a magnitude < 1 second.  The duration
00774     // is printed as a fraction of a single unit, e.g., "1.2ms".
00775     if (d < Microseconds(1)) {
00776       AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano);
00777     } else if (d < Milliseconds(1)) {
00778       AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro);
00779     } else {
00780       AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli);
00781     }
00782   } else {
00783     AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour);
00784     AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin);
00785     AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec);
00786   }
00787   if (s.empty() || s == "-") {
00788     s = "0";
00789   }
00790   return s;
00791 }
00792 
00793 namespace {
00794 
00795 // A helper for ParseDuration() that parses a leading number from the given
00796 // string and stores the result in *int_part/*frac_part/*frac_scale.  The
00797 // given string pointer is modified to point to the first unconsumed char.
00798 bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
00799                            int64_t* frac_part, int64_t* frac_scale) {
00800   *int_part = 0;
00801   *frac_part = 0;
00802   *frac_scale = 1;  // invariant: *frac_part < *frac_scale
00803   const char* start = *dpp;
00804   for (; std::isdigit(**dpp); *dpp += 1) {
00805     const int d = **dpp - '0';  // contiguous digits
00806     if (*int_part > kint64max / 10) return false;
00807     *int_part *= 10;
00808     if (*int_part > kint64max - d) return false;
00809     *int_part += d;
00810   }
00811   const bool int_part_empty = (*dpp == start);
00812   if (**dpp != '.') return !int_part_empty;
00813   for (*dpp += 1; std::isdigit(**dpp); *dpp += 1) {
00814     const int d = **dpp - '0';  // contiguous digits
00815     if (*frac_scale <= kint64max / 10) {
00816       *frac_part *= 10;
00817       *frac_part += d;
00818       *frac_scale *= 10;
00819     }
00820   }
00821   return !int_part_empty || *frac_scale != 1;
00822 }
00823 
00824 // A helper for ParseDuration() that parses a leading unit designator (e.g.,
00825 // ns, us, ms, s, m, h) from the given string and stores the resulting unit
00826 // in "*unit".  The given string pointer is modified to point to the first
00827 // unconsumed char.
00828 bool ConsumeDurationUnit(const char** start, Duration* unit) {
00829   const char *s = *start;
00830   bool ok = true;
00831   if (strncmp(s, "ns", 2) == 0) {
00832     s += 2;
00833     *unit = Nanoseconds(1);
00834   } else if (strncmp(s, "us", 2) == 0) {
00835     s += 2;
00836     *unit = Microseconds(1);
00837   } else if (strncmp(s, "ms", 2) == 0) {
00838     s += 2;
00839     *unit = Milliseconds(1);
00840   } else if (strncmp(s, "s", 1) == 0) {
00841     s += 1;
00842     *unit = Seconds(1);
00843   } else if (strncmp(s, "m", 1) == 0) {
00844     s += 1;
00845     *unit = Minutes(1);
00846   } else if (strncmp(s, "h", 1) == 0) {
00847     s += 1;
00848     *unit = Hours(1);
00849   } else {
00850     ok = false;
00851   }
00852   *start = s;
00853   return ok;
00854 }
00855 
00856 }  // namespace
00857 
00858 // From Go's doc at https://golang.org/pkg/time/#ParseDuration
00859 //   [ParseDuration] parses a duration string. A duration string is
00860 //   a possibly signed sequence of decimal numbers, each with optional
00861 //   fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
00862 //   Valid time units are "ns", "us" "ms", "s", "m", "h".
00863 bool ParseDuration(const std::string& dur_string, Duration* d) {
00864   const char* start = dur_string.c_str();
00865   int sign = 1;
00866 
00867   if (*start == '-' || *start == '+') {
00868     sign = *start == '-' ? -1 : 1;
00869     ++start;
00870   }
00871 
00872   // Can't parse a duration from an empty std::string.
00873   if (*start == '\0') {
00874     return false;
00875   }
00876 
00877   // Special case for a std::string of "0".
00878   if (*start == '0' && *(start + 1) == '\0') {
00879     *d = ZeroDuration();
00880     return true;
00881   }
00882 
00883   if (strcmp(start, "inf") == 0) {
00884     *d = sign * InfiniteDuration();
00885     return true;
00886   }
00887 
00888   Duration dur;
00889   while (*start != '\0') {
00890     int64_t int_part;
00891     int64_t frac_part;
00892     int64_t frac_scale;
00893     Duration unit;
00894     if (!ConsumeDurationNumber(&start, &int_part, &frac_part, &frac_scale) ||
00895         !ConsumeDurationUnit(&start, &unit)) {
00896       return false;
00897     }
00898     if (int_part != 0) dur += sign * int_part * unit;
00899     if (frac_part != 0) dur += sign * frac_part * unit / frac_scale;
00900   }
00901   *d = dur;
00902   return true;
00903 }
00904 
00905 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
00906   return ParseDuration(text, dst);
00907 }
00908 
00909 std::string UnparseFlag(Duration d) { return FormatDuration(d); }
00910 
00911 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14