tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

duration.cc (31154B)


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