LLVMFuzzerTestOneInput:
   24|  9.83k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   25|  9.83k|	FuzzedDataProvider fuzzed_data(data, size);
   26|       |
   27|  9.83k|	cctz::time_zone lax;
   28|  9.83k|	std::string tz = fuzzed_data.ConsumeRandomLengthString();
   29|  9.83k|	if (load_time_zone(tz, &lax)) {
  ------------------
  |  Branch (29:6): [True: 9.12k, False: 711]
  ------------------
   30|  9.12k|		std::chrono::system_clock::time_point tp;
   31|  9.12k|		std::string date_format = fuzzed_data.ConsumeRandomLengthString();
   32|  9.12k|		std::string parse_format = fuzzed_data.ConsumeRandomLengthString();
   33|  9.12k|		cctz::parse(parse_format, date_format, lax, &tp);
   34|       |
   35|  9.12k|		const auto t1 = cctz::convert(cctz::civil_second(
   36|  9.12k|				fuzzed_data.ConsumeIntegral<uint32_t>(),
   37|  9.12k|				fuzzed_data.ConsumeIntegral<uint32_t>(),
   38|  9.12k|				fuzzed_data.ConsumeIntegral<uint32_t>(),
   39|  9.12k|				fuzzed_data.ConsumeIntegral<uint32_t>(),
   40|  9.12k|				fuzzed_data.ConsumeIntegral<uint32_t>(),
   41|  9.12k|				fuzzed_data.ConsumeIntegral<uint32_t>()), lax);
   42|  9.12k|		std::string format = fuzzed_data.ConsumeRandomLengthString();
   43|  9.12k|		cctz::format(format, t1, lax);
   44|  9.12k|	}
   45|       |
   46|  9.83k|	return 0;
   47|  9.83k|}

_ZN4cctz6detail10civil_timeINS0_10second_tagEEC2Ellllll:
  359|  20.4k|      : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {}
_ZN4cctz6detail4impl5n_secEllllll:
  213|   670k|                         diff_t ss) noexcept {
  214|       |  // Optimization for when (non-constexpr) fields are already normalized.
  215|   670k|  if (0 <= ss && ss < 60) {
  ------------------
  |  Branch (215:7): [True: 544k, False: 125k]
  |  Branch (215:18): [True: 537k, False: 6.63k]
  ------------------
  216|   537k|    const second_t nss = static_cast<second_t>(ss);
  217|   537k|    if (0 <= mm && mm < 60) {
  ------------------
  |  Branch (217:9): [True: 528k, False: 9.42k]
  |  Branch (217:20): [True: 96.2k, False: 432k]
  ------------------
  218|  96.2k|      const minute_t nmm = static_cast<minute_t>(mm);
  219|  96.2k|      if (0 <= hh && hh < 24) {
  ------------------
  |  Branch (219:11): [True: 96.2k, False: 0]
  |  Branch (219:22): [True: 96.1k, False: 102]
  ------------------
  220|  96.1k|        const hour_t nhh = static_cast<hour_t>(hh);
  221|  96.1k|        if (1 <= d && d <= 28 && 1 <= m && m <= 12) {
  ------------------
  |  Branch (221:13): [True: 89.5k, False: 6.60k]
  |  Branch (221:23): [True: 57.8k, False: 31.6k]
  |  Branch (221:34): [True: 57.8k, False: 5]
  |  Branch (221:44): [True: 57.7k, False: 130]
  ------------------
  222|  57.7k|          const day_t nd = static_cast<day_t>(d);
  223|  57.7k|          const month_t nm = static_cast<month_t>(m);
  224|  57.7k|          return fields(y, nm, nd, nhh, nmm, nss);
  225|  57.7k|        }
  226|  38.4k|        return n_mon(y, m, d, 0, nhh, nmm, nss);
  227|  96.1k|      }
  228|    102|      return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss);
  229|  96.2k|    }
  230|   441k|    return n_min(y, m, d, hh, mm / 60, mm % 60, nss);
  231|   537k|  }
  232|   132k|  diff_t cm = ss / 60;
  233|   132k|  ss %= 60;
  234|   132k|  if (ss < 0) {
  ------------------
  |  Branch (234:7): [True: 125k, False: 6.63k]
  ------------------
  235|   125k|    cm -= 1;
  236|   125k|    ss += 60;
  237|   125k|  }
  238|   132k|  return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60,
  239|   132k|               static_cast<second_t>(ss));
  240|   670k|}
_ZN4cctz6detail6fieldsC2Elaaaaa:
   56|  1.02M|      : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {}
_ZN4cctz6detail4impl5n_monEllllaaa:
  180|   612k|                         hour_t hh, minute_t mm, second_t ss) noexcept {
  181|   612k|  if (m != 12) {
  ------------------
  |  Branch (181:7): [True: 608k, False: 4.03k]
  ------------------
  182|   608k|    y += m / 12;
  183|   608k|    m %= 12;
  184|   608k|    if (m <= 0) {
  ------------------
  |  Branch (184:9): [True: 6.91k, False: 601k]
  ------------------
  185|  6.91k|      y -= 1;
  186|  6.91k|      m += 12;
  187|  6.91k|    }
  188|   608k|  }
  189|   612k|  return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss);
  190|   612k|}
_ZN4cctz6detail4impl5n_dayElallaaa:
  114|   621k|                         hour_t hh, minute_t mm, second_t ss) noexcept {
  115|   621k|  year_t ey = y % 400;
  116|   621k|  const year_t oey = ey;
  117|   621k|  ey += (cd / 146097) * 400;
  118|   621k|  cd %= 146097;
  119|   621k|  if (cd < 0) {
  ------------------
  |  Branch (119:7): [True: 15.7k, False: 605k]
  ------------------
  120|  15.7k|    ey -= 400;
  121|  15.7k|    cd += 146097;
  122|  15.7k|  }
  123|   621k|  ey += (d / 146097) * 400;
  124|   621k|  d = d % 146097 + cd;
  125|   621k|  if (d > 0) {
  ------------------
  |  Branch (125:7): [True: 615k, False: 6.63k]
  ------------------
  126|   615k|    if (d > 146097) {
  ------------------
  |  Branch (126:9): [True: 1.48k, False: 613k]
  ------------------
  127|  1.48k|      ey += 400;
  128|  1.48k|      d -= 146097;
  129|  1.48k|    }
  130|   615k|  } else {
  131|  6.63k|    if (d > -365) {
  ------------------
  |  Branch (131:9): [True: 6.63k, False: 0]
  ------------------
  132|       |      // We often hit the previous year when stepping a civil time backwards,
  133|       |      // so special case it to avoid counting up by 100/4/1-year chunks.
  134|  6.63k|      ey -= 1;
  135|  6.63k|      d += days_per_year(ey, m);
  136|  6.63k|    } else {
  137|      0|      ey -= 400;
  138|      0|      d += 146097;
  139|      0|    }
  140|  6.63k|  }
  141|   621k|  if (d > 365) {
  ------------------
  |  Branch (141:7): [True: 268k, False: 353k]
  ------------------
  142|   268k|    int yi = year_index(ey, m);  // Index into Gregorian 400 year cycle.
  143|   627k|    for (;;) {
  144|   627k|      int n = days_per_century(yi);
  145|   627k|      if (d <= n) break;
  ------------------
  |  Branch (145:11): [True: 268k, False: 359k]
  ------------------
  146|   359k|      d -= n;
  147|   359k|      ey += 100;
  148|   359k|      yi += 100;
  149|   359k|      if (yi >= 400) yi -= 400;
  ------------------
  |  Branch (149:11): [True: 168k, False: 190k]
  ------------------
  150|   359k|    }
  151|  3.54M|    for (;;) {
  152|  3.54M|      int n = days_per_4years(yi);
  153|  3.54M|      if (d <= n) break;
  ------------------
  |  Branch (153:11): [True: 268k, False: 3.27M]
  ------------------
  154|  3.27M|      d -= n;
  155|  3.27M|      ey += 4;
  156|  3.27M|      yi += 4;
  157|  3.27M|      if (yi >= 400) yi -= 400;
  ------------------
  |  Branch (157:11): [True: 62.1k, False: 3.20M]
  ------------------
  158|  3.27M|    }
  159|   684k|    for (;;) {
  160|   684k|      int n = days_per_year(ey, m);
  161|   684k|      if (d <= n) break;
  ------------------
  |  Branch (161:11): [True: 268k, False: 415k]
  ------------------
  162|   415k|      d -= n;
  163|   415k|      ++ey;
  164|   415k|    }
  165|   268k|  }
  166|   621k|  if (d > 28) {
  ------------------
  |  Branch (166:7): [True: 430k, False: 191k]
  ------------------
  167|  2.01M|    for (;;) {
  168|  2.01M|      int n = days_per_month(ey, m);
  169|  2.01M|      if (d <= n) break;
  ------------------
  |  Branch (169:11): [True: 430k, False: 1.58M]
  ------------------
  170|  1.58M|      d -= n;
  171|  1.58M|      if (++m > 12) {
  ------------------
  |  Branch (171:11): [True: 8.42k, False: 1.57M]
  ------------------
  172|  8.42k|        ++ey;
  173|  8.42k|        m = 1;
  174|  8.42k|      }
  175|  1.58M|    }
  176|   430k|  }
  177|   621k|  return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss);
  178|   621k|}
_ZN4cctz6detail4impl13days_per_yearEla:
   91|   690k|CONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept {
   92|   690k|  return is_leap_year(y + (m > 2)) ? 366 : 365;
  ------------------
  |  Branch (92:10): [True: 138k, False: 552k]
  ------------------
   93|   690k|}
_ZN4cctz6detail4impl12is_leap_yearEl:
   78|   965k|CONSTEXPR_F bool is_leap_year(year_t y) noexcept {
   79|   965k|  return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
  ------------------
  |  Branch (79:10): [True: 206k, False: 758k]
  |  Branch (79:25): [True: 193k, False: 13.1k]
  |  Branch (79:41): [True: 7.72k, False: 5.43k]
  ------------------
   80|   965k|}
_ZN4cctz6detail4impl10year_indexEla:
   81|   268k|CONSTEXPR_F int year_index(year_t y, month_t m) noexcept {
   82|   268k|  const int yi = static_cast<int>((y + (m > 2)) % 400);
   83|   268k|  return yi < 0 ? yi + 400 : yi;
  ------------------
  |  Branch (83:10): [True: 14.7k, False: 253k]
  ------------------
   84|   268k|}
_ZN4cctz6detail4impl16days_per_centuryEi:
   85|   627k|CONSTEXPR_F int days_per_century(int yi) noexcept {
   86|   627k|  return 36524 + (yi == 0 || yi > 300);
  ------------------
  |  Branch (86:19): [True: 649, False: 626k]
  |  Branch (86:30): [True: 265k, False: 361k]
  ------------------
   87|   627k|}
_ZN4cctz6detail4impl15days_per_4yearsEi:
   88|  3.54M|CONSTEXPR_F int days_per_4years(int yi) noexcept {
   89|  3.54M|  return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96);
  ------------------
  |  Branch (89:18): [True: 1.12k, False: 3.53M]
  |  Branch (89:29): [True: 1.18M, False: 2.35M]
  |  Branch (89:41): [True: 2.22M, False: 124k]
  ------------------
   90|  3.54M|}
_ZN4cctz6detail4impl14days_per_monthEla:
  106|  2.01M|CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept {
  107|  2.01M|  CONSTEXPR_D int k_days_per_month[1 + 12] = {
  ------------------
  |  |   25|  2.01M|#define CONSTEXPR_D constexpr  // data
  ------------------
  108|  2.01M|      -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  // non leap year
  109|  2.01M|  };
  110|  2.01M|  return k_days_per_month[m] + (m == 2 && is_leap_year(y));
  ------------------
  |  Branch (110:33): [True: 265k, False: 1.74M]
  |  Branch (110:43): [True: 62.3k, False: 203k]
  ------------------
  111|  2.01M|}
_ZN4cctz6detail4impl6n_hourElllllaa:
  192|   573k|                          diff_t hh, minute_t mm, second_t ss) noexcept {
  193|   573k|  cd += hh / 24;
  194|   573k|  hh %= 24;
  195|   573k|  if (hh < 0) {
  ------------------
  |  Branch (195:7): [True: 6.96k, False: 566k]
  ------------------
  196|  6.96k|    cd -= 1;
  197|  6.96k|    hh += 24;
  198|  6.96k|  }
  199|   573k|  return n_mon(y, m, d, cd, static_cast<hour_t>(hh), mm, ss);
  200|   573k|}
_ZN4cctz6detail4impl5n_minElllllla:
  202|   573k|                         diff_t mm, second_t ss) noexcept {
  203|   573k|  ch += mm / 60;
  204|   573k|  mm %= 60;
  205|   573k|  if (mm < 0) {
  ------------------
  |  Branch (205:7): [True: 125k, False: 447k]
  ------------------
  206|   125k|    ch -= 1;
  207|   125k|    mm += 60;
  208|   125k|  }
  209|   573k|  return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24,
  210|   573k|                static_cast<minute_t>(mm), ss);
  211|   573k|}
_ZN4cctz6detail10civil_timeINS0_10second_tagEEC2ENS0_6fieldsE:
  446|   670k|  explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {}
_ZN4cctz6detail5alignENS0_10second_tagENS0_6fieldsE:
  332|   670k|CONSTEXPR_F fields align(second_tag, fields f) noexcept {
  333|   670k|  return f;
  334|   670k|}
_ZNK4cctz6detail10civil_timeINS0_10second_tagEE4yearEv:
  392|   782k|  CONSTEXPR_M year_t year() const noexcept { return f_.y; }
_ZNK4cctz6detail10civil_timeINS0_10second_tagEE5monthEv:
  393|   216k|  CONSTEXPR_M int month() const noexcept { return f_.m; }
_ZNK4cctz6detail10civil_timeINS0_10second_tagEE3dayEv:
  394|  53.5k|  CONSTEXPR_M int day() const noexcept { return f_.d; }
_ZN4cctz6detailplENS0_10civil_timeINS0_7day_tagEEEl:
  424|    672|  friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
  425|    672|    return civil_time(step(T{}, a.f_, n));
  426|    672|  }
_ZN4cctz6detailmiENS0_10civil_timeINS0_7day_tagEEEl:
  430|  8.62k|  friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
  431|  8.62k|    return n != (std::numeric_limits<diff_t>::min)()
  ------------------
  |  Branch (431:12): [True: 8.62k, False: 0]
  ------------------
  432|  8.62k|               ? civil_time(step(T{}, a.f_, -n))
  433|  8.62k|               : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
  434|  8.62k|  }
_ZN4cctz6detail4stepENS0_10second_tagENS0_6fieldsEl:
  247|   641k|CONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept {
  248|   641k|  return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60);
  249|   641k|}
_ZN4cctz6detail4stepENS0_7day_tagENS0_6fieldsEl:
  256|  9.29k|CONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept {
  257|  9.29k|  return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss);
  258|  9.29k|}
_ZN4cctz6detail4impl9scale_addElll:
  271|  43.1k|CONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept {
  272|  43.1k|  return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f;
  ------------------
  |  Branch (272:10): [True: 6.93k, False: 36.2k]
  ------------------
  273|  43.1k|}
_ZN4cctz6detail4impl7ymd_ordElaa:
  277|  44.6k|CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept {
  278|  44.6k|  const diff_t eyear = (m <= 2) ? y - 1 : y;
  ------------------
  |  Branch (278:24): [True: 12.7k, False: 31.9k]
  ------------------
  279|  44.6k|  const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400;
  ------------------
  |  Branch (279:23): [True: 30.5k, False: 14.0k]
  ------------------
  280|  44.6k|  const diff_t yoe = eyear - era * 400;
  281|  44.6k|  const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
  ------------------
  |  Branch (281:35): [True: 31.9k, False: 12.7k]
  ------------------
  282|  44.6k|  const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
  283|  44.6k|  return era * 146097 + doe - 719468;
  284|  44.6k|}
_ZN4cctz6detail4impl14day_differenceElaalaa:
  292|  22.3k|                                  year_t y2, month_t m2, day_t d2) noexcept {
  293|  22.3k|  const diff_t a_c4_off = y1 % 400;
  294|  22.3k|  const diff_t b_c4_off = y2 % 400;
  295|  22.3k|  diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off);
  296|  22.3k|  diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2);
  297|  22.3k|  if (c4_diff > 0 && delta < 0) {
  ------------------
  |  Branch (297:7): [True: 8.58k, False: 13.7k]
  |  Branch (297:22): [True: 645, False: 7.93k]
  ------------------
  298|    645|    delta += 2 * 146097;
  299|    645|    c4_diff -= 2 * 400;
  300|  21.6k|  } else if (c4_diff < 0 && delta > 0) {
  ------------------
  |  Branch (300:14): [True: 2.25k, False: 19.4k]
  |  Branch (300:29): [True: 13, False: 2.24k]
  ------------------
  301|     13|    delta -= 2 * 146097;
  302|     13|    c4_diff += 2 * 400;
  303|     13|  }
  304|  22.3k|  return (c4_diff / 400 * 146097) + delta;
  305|  22.3k|}
_ZN4cctz6detail10differenceENS0_7day_tagENS0_6fieldsES2_:
  316|  22.3k|CONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept {
  317|  22.3k|  return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d);
  318|  22.3k|}
_ZN4cctz6detail10differenceENS0_8hour_tagENS0_6fieldsES2_:
  319|  14.3k|CONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept {
  320|  14.3k|  return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh));
  321|  14.3k|}
_ZN4cctz6detail10differenceENS0_10minute_tagENS0_6fieldsES2_:
  322|  14.3k|CONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept {
  323|  14.3k|  return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm));
  324|  14.3k|}
_ZN4cctz6detail10differenceENS0_10second_tagENS0_6fieldsES2_:
  325|  14.3k|CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept {
  326|  14.3k|  return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss);
  327|  14.3k|}
_ZN4cctz6detail5alignENS0_7day_tagENS0_6fieldsE:
  341|  33.5k|CONSTEXPR_F fields align(day_tag, fields f) noexcept {
  342|  33.5k|  return fields{f.y, f.m, f.d, 0, 0, 0};
  343|  33.5k|}
_ZN4cctz6detail5alignENS0_8year_tagENS0_6fieldsE:
  347|  8.29k|CONSTEXPR_F fields align(year_tag, fields f) noexcept {
  348|  8.29k|  return fields{f.y, 1, 1, 0, 0, 0};
  349|  8.29k|}
_ZN4cctz6detail11get_weekdayERKNS0_10civil_timeINS0_10second_tagEEE:
  522|  17.8k|CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept {
  523|  17.8k|  CONSTEXPR_D weekday k_weekday_by_mon_off[13] = {
  ------------------
  |  |   25|  17.8k|#define CONSTEXPR_D constexpr  // data
  ------------------
  524|  17.8k|      weekday::monday,    weekday::tuesday,  weekday::wednesday,
  525|  17.8k|      weekday::thursday,  weekday::friday,   weekday::saturday,
  526|  17.8k|      weekday::sunday,    weekday::monday,   weekday::tuesday,
  527|  17.8k|      weekday::wednesday, weekday::thursday, weekday::friday,
  528|  17.8k|      weekday::saturday,
  529|  17.8k|  };
  530|  17.8k|  CONSTEXPR_D int k_weekday_offsets[1 + 12] = {
  ------------------
  |  |   25|  17.8k|#define CONSTEXPR_D constexpr  // data
  ------------------
  531|  17.8k|      -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4,
  532|  17.8k|  };
  533|  17.8k|  year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3);
  534|  17.8k|  wd += wd / 4 - wd / 100 + wd / 400;
  535|  17.8k|  wd += k_weekday_offsets[cs.month()] + cs.day();
  536|  17.8k|  return k_weekday_by_mon_off[wd % 7 + 6];
  537|  17.8k|}
_ZN4cctz6detail12next_weekdayENS0_10civil_timeINS0_7day_tagEEENS0_7weekdayE:
  541|    336|CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept {
  542|    336|  CONSTEXPR_D weekday k_weekdays_forw[14] = {
  ------------------
  |  |   25|    336|#define CONSTEXPR_D constexpr  // data
  ------------------
  543|    336|      weekday::monday,    weekday::tuesday,  weekday::wednesday,
  544|    336|      weekday::thursday,  weekday::friday,   weekday::saturday,
  545|    336|      weekday::sunday,    weekday::monday,   weekday::tuesday,
  546|    336|      weekday::wednesday, weekday::thursday, weekday::friday,
  547|    336|      weekday::saturday,  weekday::sunday,
  548|    336|  };
  549|    336|  weekday base = get_weekday(cd);
  550|  2.16k|  for (int i = 0;; ++i) {
  551|  2.16k|    if (base == k_weekdays_forw[i]) {
  ------------------
  |  Branch (551:9): [True: 336, False: 1.82k]
  ------------------
  552|  1.49k|      for (int j = i + 1;; ++j) {
  553|  1.49k|        if (wd == k_weekdays_forw[j]) {
  ------------------
  |  Branch (553:13): [True: 336, False: 1.15k]
  ------------------
  554|    336|          return cd + (j - i);
  555|    336|        }
  556|  1.49k|      }
  557|    336|    }
  558|  2.16k|  }
  559|    336|}
_ZN4cctz6detail12prev_weekdayENS0_10civil_timeINS0_7day_tagEEENS0_7weekdayE:
  561|  8.29k|CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept {
  562|  8.29k|  CONSTEXPR_D weekday k_weekdays_back[14] = {
  ------------------
  |  |   25|  8.29k|#define CONSTEXPR_D constexpr  // data
  ------------------
  563|  8.29k|      weekday::sunday,   weekday::saturday,  weekday::friday,
  564|  8.29k|      weekday::thursday, weekday::wednesday, weekday::tuesday,
  565|  8.29k|      weekday::monday,   weekday::sunday,    weekday::saturday,
  566|  8.29k|      weekday::friday,   weekday::thursday,  weekday::wednesday,
  567|  8.29k|      weekday::tuesday,  weekday::monday,
  568|  8.29k|  };
  569|  8.29k|  weekday base = get_weekday(cd);
  570|  35.3k|  for (int i = 0;; ++i) {
  571|  35.3k|    if (base == k_weekdays_back[i]) {
  ------------------
  |  Branch (571:9): [True: 8.29k, False: 27.0k]
  ------------------
  572|  29.4k|      for (int j = i + 1;; ++j) {
  573|  29.4k|        if (wd == k_weekdays_back[j]) {
  ------------------
  |  Branch (573:13): [True: 8.29k, False: 21.1k]
  ------------------
  574|  8.29k|          return cd - (j - i);
  575|  8.29k|        }
  576|  29.4k|      }
  577|  8.29k|    }
  578|  35.3k|  }
  579|  8.29k|}
_ZN4cctz6detail11get_yeardayERKNS0_10civil_timeINS0_10second_tagEEE:
  581|  9.12k|CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept {
  582|  9.12k|  CONSTEXPR_D int k_month_offsets[1 + 12] = {
  ------------------
  |  |   25|  9.12k|#define CONSTEXPR_D constexpr  // data
  ------------------
  583|  9.12k|      -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
  584|  9.12k|  };
  585|  9.12k|  const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year()));
  ------------------
  |  Branch (585:22): [True: 8.63k, False: 497]
  |  Branch (585:40): [True: 744, False: 7.88k]
  ------------------
  586|  9.12k|  return k_month_offsets[cs.month()] + feb29 + cs.day();
  587|  9.12k|}
_ZNK4cctz6detail10civil_timeINS0_7day_tagEE4yearEv:
  392|  8.29k|  CONSTEXPR_M year_t year() const noexcept { return f_.y; }
_ZNK4cctz6detail10civil_timeINS0_7day_tagEE5monthEv:
  393|  8.28k|  CONSTEXPR_M int month() const noexcept { return f_.m; }
_ZNK4cctz6detail10civil_timeINS0_7day_tagEE3dayEv:
  394|  8.28k|  CONSTEXPR_M int day() const noexcept { return f_.d; }
_ZN4cctz6detail10civil_timeINS0_7day_tagEEC2Ellllll:
  359|  7.95k|      : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {}
_ZN4cctz6detail10civil_timeINS0_7day_tagEEC2ENS0_6fieldsE:
  446|  33.5k|  explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {}
_ZN4cctz6detailmiENS0_10civil_timeINS0_7day_tagEEES3_:
  435|  7.95k|  friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
  436|  7.95k|    return difference(T{}, lhs.f_, rhs.f_);
  437|  7.95k|  }
_ZN4cctz6detail10civil_timeINS0_10second_tagEEC2INS0_7day_tagEEERKNS1_IT_EEPNSt3__19enable_ifIXsr3std10is_base_ofIS2_S6_EE5valueEvE4typeE:
  375|  8.62k|      : civil_time(ct.f_) {}
_ZN4cctz6detail10civil_timeINS0_8year_tagEEC2INS0_7day_tagEEERKNS1_IT_EEPNSt3__19enable_ifIXsr3std10is_base_ofIS6_S2_EE5valueEvE4typeE:
  379|  7.95k|      : civil_time(ct.f_) {}
_ZN4cctz6detail10civil_timeINS0_8year_tagEEC2ENS0_6fieldsE:
  446|  8.29k|  explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {}
_ZN4cctz6detail10civil_timeINS0_7day_tagEEC2INS0_8year_tagEEERKNS1_IT_EEPNSt3__19enable_ifIXsr3std10is_base_ofIS2_S6_EE5valueEvE4typeE:
  375|  8.29k|      : civil_time(ct.f_) {}
_ZN4cctz6detail10civil_timeINS0_7day_tagEEC2INS0_10second_tagEEERKNS1_IT_EEPNSt3__19enable_ifIXsr3std10is_base_ofIS6_S2_EE5valueEvE4typeE:
  379|  7.95k|      : civil_time(ct.f_) {}
_ZNK4cctz6detail10civil_timeINS0_10second_tagEE4hourEv:
  395|  16.2k|  CONSTEXPR_M int hour() const noexcept { return f_.hh; }
_ZNK4cctz6detail10civil_timeINS0_10second_tagEE6minuteEv:
  396|  15.6k|  CONSTEXPR_M int minute() const noexcept { return f_.mm; }
_ZNK4cctz6detail10civil_timeINS0_10second_tagEE6secondEv:
  397|  37.6k|  CONSTEXPR_M int second() const noexcept { return f_.ss; }
_ZN4cctz6detail10civil_timeINS0_8year_tagEEC2Ellllll:
  359|    336|      : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {}
_ZNK4cctz6detail10civil_timeINS0_8year_tagEE4yearEv:
  392|    336|  CONSTEXPR_M year_t year() const noexcept { return f_.y; }
_ZN4cctz6detailgtINS0_10second_tagES2_EEbRKNS0_10civil_timeIT_EERKNS3_IT0_EE:
  494|  6.55k|                           const civil_time<T2>& rhs) noexcept {
  495|  6.55k|  return rhs < lhs;
  496|  6.55k|}
_ZN4cctz6detailplENS0_10civil_timeINS0_10second_tagEEEl:
  424|   509k|  friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
  425|   509k|    return civil_time(step(T{}, a.f_, n));
  426|   509k|  }
_ZN4cctz6detail10civil_timeINS0_10second_tagEE3maxEv:
  382|    369|  static CONSTEXPR_F auto (max)() -> civil_time {
  383|    369|    const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
  384|    369|    return civil_time(max_year, 12, 31, 23, 59, 59);
  385|    369|  }
_ZN4cctz6detailltINS0_10second_tagES2_EEbRKNS0_10civil_timeIT_EERKNS3_IT0_EE:
  469|   232k|                           const civil_time<T2>& rhs) noexcept {
  470|   232k|  return (lhs.year() < rhs.year() ||
  ------------------
  |  Branch (470:11): [True: 113k, False: 119k]
  ------------------
  471|   119k|          (lhs.year() == rhs.year() &&
  ------------------
  |  Branch (471:12): [True: 66.7k, False: 52.8k]
  ------------------
  472|  66.7k|           (lhs.month() < rhs.month() ||
  ------------------
  |  Branch (472:13): [True: 63.1k, False: 3.67k]
  ------------------
  473|  3.67k|            (lhs.month() == rhs.month() &&
  ------------------
  |  Branch (473:14): [True: 1.19k, False: 2.47k]
  ------------------
  474|  1.19k|             (lhs.day() < rhs.day() ||
  ------------------
  |  Branch (474:15): [True: 248, False: 951]
  ------------------
  475|    951|              (lhs.day() == rhs.day() &&
  ------------------
  |  Branch (475:16): [True: 642, False: 309]
  ------------------
  476|    642|               (lhs.hour() < rhs.hour() ||
  ------------------
  |  Branch (476:17): [True: 100, False: 542]
  ------------------
  477|    542|                (lhs.hour() == rhs.hour() &&
  ------------------
  |  Branch (477:18): [True: 413, False: 129]
  ------------------
  478|    413|                 (lhs.minute() < rhs.minute() ||
  ------------------
  |  Branch (478:19): [True: 60, False: 353]
  ------------------
  479|    353|                  (lhs.minute() == rhs.minute() &&
  ------------------
  |  Branch (479:20): [True: 157, False: 196]
  ------------------
  480|    157|                   (lhs.second() < rhs.second())))))))))));
  ------------------
  |  Branch (480:20): [True: 46, False: 111]
  ------------------
  481|   232k|}
_ZN4cctz6detail10civil_timeINS0_10second_tagEE3minEv:
  386|    302|  static CONSTEXPR_F auto (min)() -> civil_time {
  387|    302|    const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
  388|    302|    return civil_time(min_year, 1, 1, 0, 0, 0);
  389|    302|  }
_ZN4cctz6detail10civil_timeINS0_10second_tagEEmIEl:
  403|  6.16k|  CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
  404|  6.16k|    return *this = *this - n;
  405|  6.16k|  }
_ZN4cctz6detailmiENS0_10civil_timeINS0_10second_tagEEEl:
  430|   131k|  friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
  431|   131k|    return n != (std::numeric_limits<diff_t>::min)()
  ------------------
  |  Branch (431:12): [True: 131k, False: 0]
  ------------------
  432|   131k|               ? civil_time(step(T{}, a.f_, -n))
  433|   131k|               : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
  434|   131k|  }
_ZN4cctz6detailmiENS0_10civil_timeINS0_10second_tagEEES3_:
  435|  14.3k|  friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
  436|  14.3k|    return difference(T{}, lhs.f_, rhs.f_);
  437|  14.3k|  }
_ZN4cctz6detail10civil_timeINS0_10second_tagEEC2Ev:
  361|   308k|  CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {}
_ZN4cctz6detailgeINS0_10second_tagES2_EEbRKNS0_10civil_timeIT_EERKNS3_IT0_EE:
  489|  14.6k|                            const civil_time<T2>& rhs) noexcept {
  490|  14.6k|  return !(lhs < rhs);
  491|  14.6k|}
_ZN4cctz6detailleINS0_10second_tagES2_EEbRKNS0_10civil_timeIT_EERKNS3_IT0_EE:
  484|  19.3k|                            const civil_time<T2>& rhs) noexcept {
  485|  19.3k|  return !(rhs < lhs);
  486|  19.3k|}

_ZN4cctz9time_zoneC2Ev:
   68|  9.83k|  time_zone() : time_zone(nullptr) {}  // Equivalent to UTC
_ZN4cctz9time_zoneC2EPKNS0_4ImplE:
  220|  19.8k|  explicit time_zone(const Impl* impl) : impl_(impl) {}
_ZN4cctz7convertERKNS_6detail10civil_timeINS0_10second_tagEEERKNS_9time_zoneE:
  257|  9.12k|                                   const time_zone& tz) {
  258|  9.12k|  const time_zone::civil_lookup cl = tz.lookup(cs);
  259|  9.12k|  if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans;
  ------------------
  |  Branch (259:7): [True: 11, False: 9.11k]
  ------------------
  260|  9.11k|  return cl.pre;
  261|  9.12k|}
_ZN4cctz5parseIxNSt3__15ratioILl1ELl1000000EEEEEbRKNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEESB_RKNS_9time_zoneEPNS1_6chrono10time_pointINSF_12system_clockENSF_8durationIT_T0_EEEE:
  379|  9.12k|           time_point<std::chrono::duration<Rep, Period>>* tpp) {
  380|  9.12k|  time_point<seconds> sec;
  381|  9.12k|  detail::femtoseconds fs;
  382|  9.12k|  if (!detail::parse(fmt, input, tz, &sec, &fs)) return false;
  ------------------
  |  Branch (382:7): [True: 3.06k, False: 6.06k]
  ------------------
  383|       |
  384|  6.06k|  time_point<std::chrono::duration<Rep, typename Period::type>> tp;
  385|  6.06k|  if (!detail::join_seconds(sec, fs, &tp)) return false;
  ------------------
  |  Branch (385:7): [True: 1.12k, False: 4.93k]
  ------------------
  386|       |
  387|  4.93k|  *tpp = tp;
  388|  4.93k|  return true;
  389|  6.06k|}
_ZN4cctz6detail12join_secondsIxLl1000000EEENSt3__19enable_ifIXsr3std11is_integralIT_EE5valueEbE4typeERKNS2_6chrono10time_pointINS7_12system_clockENS7_8durationIlNS2_5ratioILl1ELl1EEEEEEERKNSA_IlNSB_ILl1ELl1000000000000000EEEEEPNS8_IS9_NSA_IS4_NSB_ILl1EXT0_EEEEEEE:
  427|  6.06k|    time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp) {
  428|  6.06k|  using D = std::chrono::duration<Rep, std::ratio<1, Denom>>;
  429|  6.06k|  using D_check = std::chrono::duration<std::intmax_t, std::ratio<1, Denom>>;
  430|  6.06k|  const std::intmax_t count = sec.time_since_epoch().count();
  431|  6.06k|  const auto sub =
  432|  6.06k|      std::chrono::duration_cast<D_check>(fs).count();  // [0, Denom)
  433|       |
  434|       |  // Check for overflow.
  435|  6.06k|  if (sub > (std::numeric_limits<Rep>::max)()) {
  ------------------
  |  Branch (435:7): [True: 0, False: 6.06k]
  ------------------
  436|       |    // If subseconds alone exceed the max representable value, any non-negative
  437|       |    // seconds count will cause overflow. Negative seconds might bring it back
  438|       |    // into range, which is handled by the underflow check below.
  439|      0|    if (count >= 0) return false;
  ------------------
  |  Branch (439:9): [True: 0, False: 0]
  ------------------
  440|  6.06k|  } else {
  441|       |    // Equivalent to: count * Denom + sub > max, but safe from overflow.
  442|  6.06k|    if (count > ((std::numeric_limits<Rep>::max)() - sub) / Denom) return false;
  ------------------
  |  Branch (442:9): [True: 462, False: 5.60k]
  ------------------
  443|  6.06k|  }
  444|       |
  445|       |  // Check for underflow.
  446|       |  // Equivalent to: count * Denom + sub < lowest, but safe from underflow.
  447|       |  // We cannot use "lowest - sub" directly as it would underflow.
  448|  5.60k|  const auto min_div = (std::numeric_limits<Rep>::lowest)() / Denom;
  449|  5.60k|  if (count < min_div) {
  ------------------
  |  Branch (449:7): [True: 665, False: 4.93k]
  ------------------
  450|       |    // If count is less than min_div - 1, it's definitely underflow.
  451|    665|    if (count < min_div - 1) return false;
  ------------------
  |  Branch (451:9): [True: 665, False: 0]
  ------------------
  452|       |    // If count is exactly min_div - 1, we must check if subseconds are
  453|       |    // sufficient to bring the total value back above lowest.
  454|      0|    const auto min_mod = (std::numeric_limits<Rep>::lowest)() % Denom;
  455|      0|    if (sub < Denom + min_mod) return false;
  ------------------
  |  Branch (455:9): [True: 0, False: 0]
  ------------------
  456|      0|    *tpp =
  457|      0|        time_point<D>() + D{static_cast<Rep>(min_div * Denom + (sub - Denom))};
  458|      0|    return true;
  459|      0|  }
  460|  4.93k|  *tpp = time_point<D>() + D{static_cast<Rep>(count * Denom + sub)};
  461|  4.93k|  return true;
  462|  5.60k|}
_ZN4cctz6formatINSt3__16chrono8durationIlNS1_5ratioILl1ELl1EEEEEEENS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKSC_RKNS2_10time_pointINS2_12system_clockET_EERKNS_9time_zoneE:
  324|  9.12k|                          const time_zone& tz) {
  325|  9.12k|  const auto p = detail::split_seconds(tp);
  326|  9.12k|  const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second);
  327|  9.12k|  return detail::format(fmt, p.first, n, tz);
  328|  9.12k|}
_ZN4cctz6detail13split_secondsERKNSt3__16chrono10time_pointINS2_12system_clockENS2_8durationIlNS1_5ratioILl1ELl1EEEEEEE:
  416|  9.12k|    const time_point<seconds>& tp) {
  417|  9.12k|  return {tp, seconds::zero()};
  418|  9.12k|}

_ZN4cctz19FixedOffsetFromNameERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPNS0_6chrono8durationIlNS0_5ratioILl1ELl1EEEEE:
   57|  11.1k|bool FixedOffsetFromName(const std::string& name, seconds* offset) {
   58|  11.1k|  if (name == "UTC" || name == "UTC0") {
  ------------------
  |  Branch (58:7): [True: 1.65k, False: 9.47k]
  |  Branch (58:24): [True: 1, False: 9.47k]
  ------------------
   59|  1.65k|    *offset = seconds::zero();
   60|  1.65k|    return true;
   61|  1.65k|  }
   62|       |
   63|  9.47k|  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
   64|  9.47k|  const char* const ep = kFixedZonePrefix + prefix_len;
   65|  9.47k|  if (name.size() != prefix_len + 9)  // <prefix>+99:99:99
  ------------------
  |  Branch (65:7): [True: 8.60k, False: 866]
  ------------------
   66|  8.60k|    return false;
   67|    866|  if (!std::equal(kFixedZonePrefix, ep, name.begin()))
  ------------------
  |  Branch (67:7): [True: 34, False: 832]
  ------------------
   68|     34|    return false;
   69|    832|  const char* np = name.data() + prefix_len;
   70|    832|  if (np[0] != '+' && np[0] != '-')
  ------------------
  |  Branch (70:7): [True: 464, False: 368]
  |  Branch (70:23): [True: 28, False: 436]
  ------------------
   71|     28|    return false;
   72|    804|  if (np[3] != ':' || np[6] != ':')  // see note below about large offsets
  ------------------
  |  Branch (72:7): [True: 2, False: 802]
  |  Branch (72:23): [True: 18, False: 784]
  ------------------
   73|     20|    return false;
   74|       |
   75|    784|  int hours = Parse02d(np + 1);
   76|    784|  if (hours == -1) return false;
  ------------------
  |  Branch (76:7): [True: 6, False: 778]
  ------------------
   77|    778|  int mins = Parse02d(np + 4);
   78|    778|  if (mins == -1) return false;
  ------------------
  |  Branch (78:7): [True: 2, False: 776]
  ------------------
   79|    776|  int secs = Parse02d(np + 7);
   80|    776|  if (secs == -1) return false;
  ------------------
  |  Branch (80:7): [True: 8, False: 768]
  ------------------
   81|       |
   82|    768|  secs += ((hours * 60) + mins) * 60;
   83|    768|  if (secs > 24 * 60 * 60) return false;  // outside supported offset range
  ------------------
  |  Branch (83:7): [True: 16, False: 752]
  ------------------
   84|    752|  *offset = seconds(secs * (np[0] == '-' ? -1 : 1));  // "-" means west
  ------------------
  |  Branch (84:29): [True: 414, False: 338]
  ------------------
   85|    752|  return true;
   86|    768|}
_ZN4cctz17FixedOffsetToNameERKNSt3__16chrono8durationIlNS0_5ratioILl1ELl1EEEEE:
   88|    334|std::string FixedOffsetToName(const seconds& offset) {
   89|    334|  if (offset == seconds::zero()) return "UTC";
  ------------------
  |  Branch (89:7): [True: 1, False: 333]
  ------------------
   90|    333|  if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) {
  ------------------
  |  Branch (90:7): [True: 0, False: 333]
  |  Branch (90:7): [True: 0, False: 333]
  |  Branch (90:43): [True: 0, False: 333]
  ------------------
   91|       |    // We don't support fixed-offset zones more than 24 hours
   92|       |    // away from UTC to avoid complications in rendering such
   93|       |    // offsets and to (somewhat) limit the total number of zones.
   94|      0|    return "UTC";
   95|      0|  }
   96|    333|  int offset_seconds = static_cast<int>(offset.count());
   97|    333|  const char sign = (offset_seconds < 0 ? '-' : '+');
  ------------------
  |  Branch (97:22): [True: 188, False: 145]
  ------------------
   98|    333|  int offset_minutes = offset_seconds / 60;
   99|    333|  offset_seconds %= 60;
  100|    333|  if (sign == '-') {
  ------------------
  |  Branch (100:7): [True: 188, False: 145]
  ------------------
  101|    188|    if (offset_seconds > 0) {
  ------------------
  |  Branch (101:9): [True: 0, False: 188]
  ------------------
  102|      0|      offset_seconds -= 60;
  103|      0|      offset_minutes += 1;
  104|      0|    }
  105|    188|    offset_seconds = -offset_seconds;
  106|    188|    offset_minutes = -offset_minutes;
  107|    188|  }
  108|    333|  int offset_hours = offset_minutes / 60;
  109|    333|  offset_minutes %= 60;
  110|    333|  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
  111|    333|  char buf[prefix_len + sizeof("-24:00:00")];
  112|    333|  char* ep = std::copy_n(kFixedZonePrefix, prefix_len, buf);
  113|    333|  *ep++ = sign;
  114|    333|  ep = Format02d(ep, offset_hours);
  115|    333|  *ep++ = ':';
  116|    333|  ep = Format02d(ep, offset_minutes);
  117|    333|  *ep++ = ':';
  118|    333|  ep = Format02d(ep, offset_seconds);
  119|    333|  *ep++ = '\0';
  120|    333|  assert(ep == buf + sizeof(buf));
  ------------------
  |  Branch (120:3): [True: 333, False: 0]
  ------------------
  121|    333|  return buf;
  122|    333|}
_ZN4cctz17FixedOffsetToAbbrERKNSt3__16chrono8durationIlNS0_5ratioILl1ELl1EEEEE:
  124|    334|std::string FixedOffsetToAbbr(const seconds& offset) {
  125|    334|  std::string abbr = FixedOffsetToName(offset);
  126|    334|  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
  127|    334|  if (abbr.size() == prefix_len + 9) {         // <prefix>+99:99:99
  ------------------
  |  Branch (127:7): [True: 333, False: 1]
  ------------------
  128|    333|    abbr.erase(0, prefix_len);                 // +99:99:99
  129|    333|    abbr.erase(6, 1);                          // +99:9999
  130|    333|    abbr.erase(3, 1);                          // +999999
  131|    333|    if (abbr[5] == '0' && abbr[6] == '0') {    // +999900
  ------------------
  |  Branch (131:9): [True: 121, False: 212]
  |  Branch (131:27): [True: 51, False: 70]
  ------------------
  132|     51|      abbr.erase(5, 2);                        // +9999
  133|     51|      if (abbr[3] == '0' && abbr[4] == '0') {  // +9900
  ------------------
  |  Branch (133:11): [True: 25, False: 26]
  |  Branch (133:29): [True: 2, False: 23]
  ------------------
  134|      2|        abbr.erase(3, 2);                      // +99
  135|      2|      }
  136|     51|    }
  137|    333|  }
  138|    334|  return abbr;
  139|    334|}
time_zone_fixed.cc:_ZN4cctz12_GLOBAL__N_18Parse02dEPKc:
   46|  2.33k|int Parse02d(const char* p) {
   47|  2.33k|  const int hi = ParseDigit(p[0]);
   48|  2.33k|  if (hi >= 0) {
  ------------------
  |  Branch (48:7): [True: 2.32k, False: 10]
  ------------------
   49|  2.32k|    const int lo = ParseDigit(p[1]);
   50|  2.32k|    if (lo >= 0) return (hi * 10) + lo;
  ------------------
  |  Branch (50:9): [True: 2.32k, False: 6]
  ------------------
   51|  2.32k|  }
   52|     16|  return -1;
   53|  2.33k|}
time_zone_fixed.cc:_ZN4cctz12_GLOBAL__N_110ParseDigitEc:
   41|  4.66k|int ParseDigit(char ch) {
   42|  4.66k|  const char* const dp = std::strchr(kDigits, ch);
   43|  4.66k|  return (dp == nullptr || *dp == '\0') ? -1 : static_cast<int>(dp - kDigits);
  ------------------
  |  Branch (43:11): [True: 10, False: 4.65k]
  |  Branch (43:28): [True: 6, False: 4.65k]
  ------------------
   44|  4.66k|}
time_zone_fixed.cc:_ZN4cctz12_GLOBAL__N_19Format02dEPci:
   32|    999|char* Format02d(char* p, int v) {
   33|    999|  *p++ = kDigits[(v / 10) % 10];
   34|    999|  *p++ = kDigits[v % 10];
   35|    999|  return p;
   36|    999|}

_ZN4cctz6detail6formatERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKNS1_6chrono10time_pointINSA_12system_clockENSA_8durationIlNS1_5ratioILl1ELl1EEEEEEERKNSD_IlNSE_ILl1ELl1000000000000000EEEEERKNS_9time_zoneE:
  339|  9.12k|                   const detail::femtoseconds& fs, const time_zone& tz) {
  340|  9.12k|  std::string result;
  341|  9.12k|  result.reserve(2 * format.size());  // A guess for the result size.
  342|  9.12k|  const time_zone::absolute_lookup al = tz.lookup(tp);
  343|  9.12k|  const std::tm tm = ToTM(al);
  344|       |
  345|       |  // Scratch buffer for internal conversions.
  346|  9.12k|  char buf[6 + (kDigits10_64 + 2)];  // enough for longest conversion (%F)
  347|  9.12k|  char* const ep = buf + sizeof(buf);
  348|  9.12k|  char* bp;  // works back from ep
  349|       |
  350|       |  // Maintain three, disjoint subsequences that span format.
  351|       |  //   [format.begin() ... pending) : already formatted into result
  352|       |  //   [pending ... cur) : formatting pending, but no special cases
  353|       |  //   [cur ... format.end()) : unexamined
  354|       |  // Initially, everything is in the unexamined part.
  355|  9.12k|  const char* pending = format.data();
  356|  9.12k|  const char* cur = pending;
  357|  9.12k|  const char* const end = pending + format.size();
  358|       |
  359|   205k|  while (cur != end) {  // while something is unexamined
  ------------------
  |  Branch (359:10): [True: 196k, False: 9.12k]
  ------------------
  360|       |    // Moves cur to the next percent sign.
  361|   196k|    const char* start = cur;
  362|  30.4M|    while (cur != end && *cur != '%') {
  ------------------
  |  Branch (362:12): [True: 30.4M, False: 737]
  |  Branch (362:26): [True: 30.2M, False: 195k]
  ------------------
  363|  30.2M|      if (*cur == '\0' && pending != start) {
  ------------------
  |  Branch (363:11): [True: 2.21M, False: 28.0M]
  |  Branch (363:27): [True: 13.9k, False: 2.19M]
  ------------------
  364|  13.9k|        FormatTM(&result, std::string(pending, cur), tm);
  365|  13.9k|        pending = start = cur;
  366|  13.9k|      }
  367|  30.2M|      ++cur;
  368|  30.2M|    }
  369|       |
  370|       |    // If the new pending text is all ordinary, copy it out.
  371|   196k|    if (cur != start && pending == start) {
  ------------------
  |  Branch (371:9): [True: 121k, False: 75.2k]
  |  Branch (371:25): [True: 47.3k, False: 73.7k]
  ------------------
  372|  47.3k|      result.append(pending, cur);
  373|  47.3k|      pending = start = cur;
  374|  47.3k|    }
  375|       |
  376|       |    // Span the sequential percent signs.
  377|   196k|    const char* const percent = cur;
  378|   520k|    while (cur != end && *cur == '%') ++cur;
  ------------------
  |  Branch (378:12): [True: 519k, False: 834]
  |  Branch (378:26): [True: 323k, False: 195k]
  ------------------
  379|       |
  380|       |    // If the new pending text is all percents, copy out one
  381|       |    // percent for every matched pair, then skip those pairs.
  382|   196k|    if (cur != start && pending == start) {
  ------------------
  |  Branch (382:9): [True: 196k, False: 294]
  |  Branch (382:25): [True: 115k, False: 80.3k]
  ------------------
  383|   115k|      std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2;
  384|   115k|      result.append(pending, escaped);
  385|   115k|      pending += escaped * 2;
  386|       |      // Also copy out a single trailing percent.
  387|   115k|      if (pending != cur && cur == end) {
  ------------------
  |  Branch (387:11): [True: 112k, False: 2.74k]
  |  Branch (387:29): [True: 36, False: 112k]
  ------------------
  388|     36|        result.push_back(*pending++);
  389|     36|      }
  390|   115k|    }
  391|       |
  392|       |    // Loop unless we have an unescaped percent.
  393|   196k|    if (cur == end || (cur - percent) % 2 == 0) continue;
  ------------------
  |  Branch (393:9): [True: 834, False: 195k]
  |  Branch (393:23): [True: 5.28k, False: 190k]
  ------------------
  394|       |
  395|       |    // Simple specifiers that we handle ourselves.
  396|   190k|    if (*cur == '\0' || strchr("YmdeFUuWwHMSTzZs%", *cur)) {
  ------------------
  |  Branch (396:9): [True: 3.97k, False: 186k]
  |  Branch (396:25): [True: 30.7k, False: 155k]
  ------------------
  397|  34.7k|      FormatTM(&result, std::string(pending, cur - 1), tm);
  398|  34.7k|      switch (*cur) {
  ------------------
  |  Branch (398:15): [True: 34.7k, False: 0]
  ------------------
  399|  3.97k|        case '\0':
  ------------------
  |  Branch (399:9): [True: 3.97k, False: 30.7k]
  ------------------
  400|       |          // Because we allow NULs in the format string, we must give
  401|       |          // some meaning to the "%\0" specifier.  We choose the common
  402|       |          // (but undefined) strftime() behavior of echoing unknown
  403|       |          // specifiers.
  404|  3.97k|          result.push_back('%');
  405|  3.97k|          result.push_back('\0');
  406|  3.97k|          break;
  407|  4.41k|        case 'Y':
  ------------------
  |  Branch (407:9): [True: 4.41k, False: 30.3k]
  ------------------
  408|       |          // This avoids the tm.tm_year overflow problem for %Y, however
  409|       |          // tm.tm_year will still be used by other specifiers like %D.
  410|  4.41k|          bp = Format64(ep, 0, al.cs.year());
  411|  4.41k|          result.append(bp, ep);
  412|  4.41k|          break;
  413|    208|        case 'm':
  ------------------
  |  Branch (413:9): [True: 208, False: 34.5k]
  ------------------
  414|    208|          bp = Format02d(ep, al.cs.month());
  415|    208|          result.append(bp, ep);
  416|    208|          break;
  417|    246|        case 'd':
  ------------------
  |  Branch (417:9): [True: 246, False: 34.5k]
  ------------------
  418|    715|        case 'e':
  ------------------
  |  Branch (418:9): [True: 469, False: 34.2k]
  ------------------
  419|    715|          bp = Format02d(ep, al.cs.day());
  420|    715|          if (*cur == 'e' && *bp == '0') *bp = ' ';  // for Windows
  ------------------
  |  Branch (420:15): [True: 469, False: 246]
  |  Branch (420:30): [True: 238, False: 231]
  ------------------
  421|    715|          result.append(bp, ep);
  422|    715|          break;
  423|  2.07k|        case 'F':
  ------------------
  |  Branch (423:9): [True: 2.07k, False: 32.6k]
  ------------------
  424|  2.07k|          bp = Format02d(ep, al.cs.day());
  425|  2.07k|          *--bp = '-';
  426|  2.07k|          bp = Format02d(bp, al.cs.month());
  427|  2.07k|          *--bp = '-';
  428|  2.07k|          bp = Format64(bp, 0, al.cs.year());
  429|  2.07k|          result.append(bp, ep);
  430|  2.07k|          break;
  431|  5.23k|        case 'U':
  ------------------
  |  Branch (431:9): [True: 5.23k, False: 29.5k]
  ------------------
  432|  5.23k|          bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday));
  433|  5.23k|          result.append(bp, ep);
  434|  5.23k|          break;
  435|    717|        case 'u':
  ------------------
  |  Branch (435:9): [True: 717, False: 34.0k]
  ------------------
  436|    717|          bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7);
  ------------------
  |  Branch (436:32): [True: 522, False: 195]
  ------------------
  437|    717|          result.append(bp, ep);
  438|    717|          break;
  439|  2.72k|        case 'W':
  ------------------
  |  Branch (439:9): [True: 2.72k, False: 32.0k]
  ------------------
  440|  2.72k|          bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday));
  441|  2.72k|          result.append(bp, ep);
  442|  2.72k|          break;
  443|    199|        case 'w':
  ------------------
  |  Branch (443:9): [True: 199, False: 34.5k]
  ------------------
  444|    199|          bp = Format64(ep, 0, tm.tm_wday);
  445|    199|          result.append(bp, ep);
  446|    199|          break;
  447|    215|        case 'H':
  ------------------
  |  Branch (447:9): [True: 215, False: 34.5k]
  ------------------
  448|    215|          bp = Format02d(ep, al.cs.hour());
  449|    215|          result.append(bp, ep);
  450|    215|          break;
  451|    384|        case 'M':
  ------------------
  |  Branch (451:9): [True: 384, False: 34.3k]
  ------------------
  452|    384|          bp = Format02d(ep, al.cs.minute());
  453|    384|          result.append(bp, ep);
  454|    384|          break;
  455|    728|        case 'S':
  ------------------
  |  Branch (455:9): [True: 728, False: 34.0k]
  ------------------
  456|    728|          bp = Format02d(ep, al.cs.second());
  457|    728|          result.append(bp, ep);
  458|    728|          break;
  459|    435|        case 'T':
  ------------------
  |  Branch (459:9): [True: 435, False: 34.3k]
  ------------------
  460|    435|          bp = Format02d(ep, al.cs.second());
  461|    435|          *--bp = ':';
  462|    435|          bp = Format02d(bp, al.cs.minute());
  463|    435|          *--bp = ':';
  464|    435|          bp = Format02d(bp, al.cs.hour());
  465|    435|          result.append(bp, ep);
  466|    435|          break;
  467|  7.62k|        case 'z':
  ------------------
  |  Branch (467:9): [True: 7.62k, False: 27.1k]
  ------------------
  468|  7.62k|          bp = FormatOffset(ep, al.offset, "");
  469|  7.62k|          result.append(bp, ep);
  470|  7.62k|          break;
  471|    365|        case 'Z':
  ------------------
  |  Branch (471:9): [True: 365, False: 34.3k]
  ------------------
  472|    365|          result.append(al.abbr);
  473|    365|          break;
  474|  4.75k|        case 's':
  ------------------
  |  Branch (474:9): [True: 4.75k, False: 30.0k]
  ------------------
  475|  4.75k|          bp = Format64(ep, 0, ToUnixSeconds(tp));
  476|  4.75k|          result.append(bp, ep);
  477|  4.75k|          break;
  478|      0|        case '%':
  ------------------
  |  Branch (478:9): [True: 0, False: 34.7k]
  ------------------
  479|      0|          result.push_back('%');
  480|      0|          break;
  481|  34.7k|      }
  482|  34.7k|      pending = ++cur;
  483|  34.7k|      continue;
  484|  34.7k|    }
  485|       |
  486|       |    // More complex specifiers that we handle ourselves.
  487|   155k|    if (*cur == ':' && cur + 1 != end) {
  ------------------
  |  Branch (487:9): [True: 25.8k, False: 129k]
  |  Branch (487:24): [True: 25.8k, False: 7]
  ------------------
  488|  25.8k|      if (*(cur + 1) == 'z') {
  ------------------
  |  Branch (488:11): [True: 8.63k, False: 17.2k]
  ------------------
  489|       |        // Formats %:z.
  490|  8.63k|        FormatTM(&result, std::string(pending, cur - 1), tm);
  491|  8.63k|        bp = FormatOffset(ep, al.offset, ":");
  492|  8.63k|        result.append(bp, ep);
  493|  8.63k|        pending = cur += 2;
  494|  8.63k|        continue;
  495|  8.63k|      }
  496|  17.2k|      if (*(cur + 1) == ':' && cur + 2 != end) {
  ------------------
  |  Branch (496:11): [True: 7.61k, False: 9.63k]
  |  Branch (496:32): [True: 7.60k, False: 2]
  ------------------
  497|  7.60k|        if (*(cur + 2) == 'z') {
  ------------------
  |  Branch (497:13): [True: 2.59k, False: 5.01k]
  ------------------
  498|       |          // Formats %::z.
  499|  2.59k|          FormatTM(&result, std::string(pending, cur - 1), tm);
  500|  2.59k|          bp = FormatOffset(ep, al.offset, ":*");
  501|  2.59k|          result.append(bp, ep);
  502|  2.59k|          pending = cur += 3;
  503|  2.59k|          continue;
  504|  2.59k|        }
  505|  5.01k|        if (*(cur + 2) == ':' && cur + 3 != end) {
  ------------------
  |  Branch (505:13): [True: 2.08k, False: 2.92k]
  |  Branch (505:34): [True: 2.08k, False: 1]
  ------------------
  506|  2.08k|          if (*(cur + 3) == 'z') {
  ------------------
  |  Branch (506:15): [True: 1.59k, False: 485]
  ------------------
  507|       |            // Formats %:::z.
  508|  1.59k|            FormatTM(&result, std::string(pending, cur - 1), tm);
  509|  1.59k|            bp = FormatOffset(ep, al.offset, ":*:");
  510|  1.59k|            result.append(bp, ep);
  511|  1.59k|            pending = cur += 4;
  512|  1.59k|            continue;
  513|  1.59k|          }
  514|  2.08k|        }
  515|  5.01k|      }
  516|  17.2k|    }
  517|       |
  518|       |    // Loop if there is no E modifier.
  519|   142k|    if (*cur != 'E' || ++cur == end) continue;
  ------------------
  |  Branch (519:9): [True: 59.8k, False: 82.7k]
  |  Branch (519:24): [True: 4, False: 82.7k]
  ------------------
  520|       |
  521|       |    // Format our extensions.
  522|  82.7k|    if (*cur == 'T') {
  ------------------
  |  Branch (522:9): [True: 4.42k, False: 78.3k]
  ------------------
  523|       |      // Formats %ET.
  524|  4.42k|      FormatTM(&result, std::string(pending, cur - 2), tm);
  525|  4.42k|      result.append("T");
  526|  4.42k|      pending = ++cur;
  527|  78.3k|    } else if (*cur == 'z') {
  ------------------
  |  Branch (527:16): [True: 6.28k, False: 72.0k]
  ------------------
  528|       |      // Formats %Ez.
  529|  6.28k|      FormatTM(&result, std::string(pending, cur - 2), tm);
  530|  6.28k|      bp = FormatOffset(ep, al.offset, ":");
  531|  6.28k|      result.append(bp, ep);
  532|  6.28k|      pending = ++cur;
  533|  72.0k|    } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') {
  ------------------
  |  Branch (533:16): [True: 25.5k, False: 46.5k]
  |  Branch (533:31): [True: 25.5k, False: 8]
  |  Branch (533:49): [True: 3.65k, False: 21.8k]
  ------------------
  534|       |      // Formats %E*z.
  535|  3.65k|      FormatTM(&result, std::string(pending, cur - 2), tm);
  536|  3.65k|      bp = FormatOffset(ep, al.offset, ":*");
  537|  3.65k|      result.append(bp, ep);
  538|  3.65k|      pending = cur += 2;
  539|  68.4k|    } else if (*cur == '*' && cur + 1 != end &&
  ------------------
  |  Branch (539:16): [True: 21.8k, False: 46.5k]
  |  Branch (539:31): [True: 21.8k, False: 8]
  ------------------
  540|  21.8k|               (*(cur + 1) == 'S' || *(cur + 1) == 'f')) {
  ------------------
  |  Branch (540:17): [True: 17.9k, False: 3.92k]
  |  Branch (540:38): [True: 3.04k, False: 885]
  ------------------
  541|       |      // Formats %E*S or %E*F.
  542|  20.9k|      FormatTM(&result, std::string(pending, cur - 2), tm);
  543|  20.9k|      char* cp = ep;
  544|  20.9k|      bp = Format64(cp, 15, fs.count());
  545|   335k|      while (cp != bp && cp[-1] == '0') --cp;
  ------------------
  |  Branch (545:14): [True: 314k, False: 20.9k]
  |  Branch (545:26): [True: 314k, False: 0]
  ------------------
  546|  20.9k|      switch (*(cur + 1)) {
  ------------------
  |  Branch (546:15): [True: 20.9k, False: 0]
  ------------------
  547|  17.9k|        case 'S':
  ------------------
  |  Branch (547:9): [True: 17.9k, False: 3.04k]
  ------------------
  548|  17.9k|          if (cp != bp) *--bp = '.';
  ------------------
  |  Branch (548:15): [True: 0, False: 17.9k]
  ------------------
  549|  17.9k|          bp = Format02d(bp, al.cs.second());
  550|  17.9k|          break;
  551|  3.04k|        case 'f':
  ------------------
  |  Branch (551:9): [True: 3.04k, False: 17.9k]
  ------------------
  552|  3.04k|          if (cp == bp) *--bp = '0';
  ------------------
  |  Branch (552:15): [True: 3.04k, False: 0]
  ------------------
  553|  3.04k|          break;
  554|  20.9k|      }
  555|  20.9k|      result.append(bp, cp);
  556|  20.9k|      pending = cur += 2;
  557|  47.4k|    } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') {
  ------------------
  |  Branch (557:16): [True: 7.18k, False: 40.2k]
  |  Branch (557:31): [True: 7.18k, False: 6]
  |  Branch (557:49): [True: 5.84k, False: 1.33k]
  ------------------
  558|       |      // Formats %E4Y.
  559|  5.84k|      FormatTM(&result, std::string(pending, cur - 2), tm);
  560|  5.84k|      bp = Format64(ep, 4, al.cs.year());
  561|  5.84k|      result.append(bp, ep);
  562|  5.84k|      pending = cur += 2;
  563|  41.5k|    } else if (isdigit(*cur)) {
  ------------------
  |  Branch (563:16): [True: 21.5k, False: 20.0k]
  ------------------
  564|       |      // Possibly found %E#S or %E#f.
  565|  21.5k|      int n = 0;
  566|  21.5k|      if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) {
  ------------------
  |  Branch (566:23): [True: 15.5k, False: 5.96k]
  ------------------
  567|  15.5k|        if (*np == 'S' || *np == 'f') {
  ------------------
  |  Branch (567:13): [True: 4.94k, False: 10.5k]
  |  Branch (567:27): [True: 4.68k, False: 5.90k]
  ------------------
  568|       |          // Formats %E#S or %E#f.
  569|  9.62k|          FormatTM(&result, std::string(pending, cur - 2), tm);
  570|  9.62k|          bp = ep;
  571|  9.62k|          if (n > 0) {
  ------------------
  |  Branch (571:15): [True: 7.59k, False: 2.03k]
  ------------------
  572|  7.59k|            if (n > kDigits10_64) n = kDigits10_64;
  ------------------
  |  Branch (572:17): [True: 3.49k, False: 4.09k]
  ------------------
  573|  7.59k|            bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15]
  ------------------
  |  Branch (573:34): [True: 3.49k, False: 4.09k]
  ------------------
  574|  7.59k|                                          : fs.count() / kExp10[15 - n]);
  575|  7.59k|            if (*np == 'S') *--bp = '.';
  ------------------
  |  Branch (575:17): [True: 3.27k, False: 4.32k]
  ------------------
  576|  7.59k|          }
  577|  9.62k|          if (*np == 'S') bp = Format02d(bp, al.cs.second());
  ------------------
  |  Branch (577:15): [True: 4.94k, False: 4.68k]
  ------------------
  578|  9.62k|          result.append(bp, ep);
  579|  9.62k|          pending = cur = ++np;
  580|  9.62k|        }
  581|  15.5k|      }
  582|  21.5k|    }
  583|  82.7k|  }
  584|       |
  585|       |  // Formats any remaining data.
  586|  9.12k|  FormatTM(&result, std::string(pending, end), tm);
  587|       |
  588|  9.12k|  return result;
  589|  9.12k|}
_ZN4cctz6detail5parseERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_RKNS_9time_zoneEPNS1_6chrono10time_pointINSD_12system_clockENSD_8durationIlNS1_5ratioILl1ELl1EEEEEEEPNSG_IlNSH_ILl1ELl1000000000000000EEEEEPS7_:
  706|  9.12k|           detail::femtoseconds* fs, std::string* err) {
  707|  9.12k|#if __cplusplus < 202002L
  708|       |  // Assert that the std::chrono::system_clock epoch is the Unix epoch.
  709|       |  // This is required by C++20, but was also ubiquitous before that.
  710|       |  // We use this in join_seconds() to simplify overflow detection.
  711|  9.12k|  assert(std::chrono::system_clock::from_time_t(0).time_since_epoch() ==
  ------------------
  |  Branch (711:3): [True: 9.12k, False: 0]
  ------------------
  712|  9.12k|         std::chrono::system_clock::duration::zero());
  713|  9.12k|#endif
  714|       |
  715|       |  // The unparsed input.  Even though we allow NULs in input, and
  716|       |  // match them against corresponding NULs in format, we depend on
  717|       |  // *edata being a NUL so that we can call strptime().  This also
  718|       |  // makes our handling of input easier.
  719|  9.12k|  const char* data = input.c_str();  // NUL terminated
  720|  9.12k|  const char* const edata = data + input.size();
  721|       |
  722|       |  // Skips leading whitespace.
  723|  9.33k|  while (isspace(*data)) ++data;
  ------------------
  |  Branch (723:10): [True: 204, False: 9.12k]
  ------------------
  724|       |
  725|  9.12k|  const year_t kyearmax = std::numeric_limits<year_t>::max();
  726|  9.12k|  const year_t kyearmin = std::numeric_limits<year_t>::min();
  727|       |
  728|       |  // Sets default values for unspecified fields.
  729|  9.12k|  bool saw_year = false;
  730|  9.12k|  year_t year = 1970;
  731|  9.12k|  std::tm tm{};
  732|  9.12k|  tm.tm_year = 1970 - 1900;
  733|  9.12k|  tm.tm_mon = 1 - 1;  // Jan
  734|  9.12k|  tm.tm_mday = 1;
  735|  9.12k|  tm.tm_hour = 0;
  736|  9.12k|  tm.tm_min = 0;
  737|  9.12k|  tm.tm_sec = 0;
  738|  9.12k|  tm.tm_wday = 4;  // Thu
  739|  9.12k|  tm.tm_yday = 0;
  740|  9.12k|  tm.tm_isdst = 0;
  741|  9.12k|  auto subseconds = detail::femtoseconds::zero();
  742|  9.12k|  bool saw_offset = false;
  743|  9.12k|  int offset = 0;  // No offset from passed tz.
  744|  9.12k|  std::string zone = "UTC";
  745|       |
  746|       |  // Even though we allow NULs in format, and match them against
  747|       |  // corresponding NULs in input, we simplify its handling by also
  748|       |  // ensuring that *efmt is a NUL.
  749|  9.12k|  const char* fmt = format.c_str();  // NUL terminated
  750|  9.12k|  const char* const efmt = fmt + format.size();
  751|  9.12k|  bool twelve_hour = false;
  752|  9.12k|  bool afternoon = false;
  753|  9.12k|  int week_num = -1;
  754|  9.12k|  weekday week_start = weekday::sunday;
  755|       |
  756|  9.12k|  bool saw_percent_s = false;
  757|  9.12k|  std::int_fast64_t percent_s = 0;
  758|       |
  759|       |  // Steps through format, one specifier at a time.
  760|  34.7k|  while (data != nullptr && fmt != efmt) {
  ------------------
  |  Branch (760:10): [True: 32.3k, False: 2.40k]
  |  Branch (760:29): [True: 25.5k, False: 6.72k]
  ------------------
  761|  25.5k|    if (isspace(*fmt)) {
  ------------------
  |  Branch (761:9): [True: 1.54k, False: 24.0k]
  ------------------
  762|  2.99k|      while (isspace(*data)) ++data;
  ------------------
  |  Branch (762:14): [True: 1.44k, False: 1.54k]
  ------------------
  763|  1.74k|      while (isspace(*++fmt)) continue;
  ------------------
  |  Branch (763:14): [True: 199, False: 1.54k]
  ------------------
  764|  1.54k|      continue;
  765|  1.54k|    }
  766|       |
  767|  24.0k|    if (*fmt != '%') {
  ------------------
  |  Branch (767:9): [True: 1.08k, False: 22.9k]
  ------------------
  768|  1.08k|      if (data != edata && *data == *fmt) {
  ------------------
  |  Branch (768:11): [True: 1.00k, False: 76]
  |  Branch (768:28): [True: 947, False: 57]
  ------------------
  769|    947|        ++data;
  770|    947|        ++fmt;
  771|    947|      } else {
  772|    133|        data = nullptr;
  773|    133|      }
  774|  1.08k|      continue;
  775|  1.08k|    }
  776|       |
  777|  22.9k|    const char* const percent = fmt;
  778|  22.9k|    if (++fmt == efmt) {
  ------------------
  |  Branch (778:9): [True: 9, False: 22.9k]
  ------------------
  779|      9|      data = nullptr;
  780|      9|      continue;
  781|      9|    }
  782|  22.9k|    switch (*fmt++) {
  ------------------
  |  Branch (782:13): [True: 22.0k, False: 897]
  ------------------
  783|      1|      case '\0':
  ------------------
  |  Branch (783:7): [True: 1, False: 22.9k]
  ------------------
  784|       |        // Because we allow NULs in the format string, we must give
  785|       |        // some meaning to the "%\0" specifier.  We choose the common
  786|       |        // (but undefined) strptime() behavior of failing on unknown
  787|       |        // specifiers.
  788|      1|        data = nullptr;
  789|      1|        continue;
  790|  2.14k|      case 'Y':
  ------------------
  |  Branch (790:7): [True: 2.14k, False: 20.8k]
  ------------------
  791|       |        // Symmetrically with format(), directly handing %Y avoids the
  792|       |        // tm.tm_year overflow problem.  However, tm.tm_year will still be
  793|       |        // used by other specifiers like %D.
  794|  2.14k|        data = ParseInt(data, 0, kyearmin, kyearmax, &year);
  795|  2.14k|        if (data != nullptr) saw_year = true;
  ------------------
  |  Branch (795:13): [True: 2.07k, False: 73]
  ------------------
  796|  2.14k|        continue;
  797|    640|      case 'm':
  ------------------
  |  Branch (797:7): [True: 640, False: 22.3k]
  ------------------
  798|    640|        data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
  799|    640|        if (data != nullptr) tm.tm_mon -= 1;
  ------------------
  |  Branch (799:13): [True: 599, False: 41]
  ------------------
  800|    640|        week_num = -1;
  801|    640|        continue;
  802|    143|      case 'd':
  ------------------
  |  Branch (802:7): [True: 143, False: 22.8k]
  ------------------
  803|    687|      case 'e':
  ------------------
  |  Branch (803:7): [True: 544, False: 22.4k]
  ------------------
  804|    687|        data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
  805|    687|        week_num = -1;
  806|    687|        continue;
  807|    739|      case 'F':
  ------------------
  |  Branch (807:7): [True: 739, False: 22.2k]
  ------------------
  808|    739|        data = ParseInt(data, 0, kyearmin, kyearmax, &year);
  809|    739|        if (data != nullptr) {
  ------------------
  |  Branch (809:13): [True: 705, False: 34]
  ------------------
  810|    705|          saw_year = true;
  811|    705|          data = (*data == '-' ? data + 1 : nullptr);
  ------------------
  |  Branch (811:19): [True: 442, False: 263]
  ------------------
  812|    705|        }
  813|    739|        data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
  814|    739|        if (data != nullptr) {
  ------------------
  |  Branch (814:13): [True: 398, False: 341]
  ------------------
  815|    398|          tm.tm_mon -= 1;
  816|    398|          data = (*data == '-' ? data + 1 : nullptr);
  ------------------
  |  Branch (816:19): [True: 384, False: 14]
  ------------------
  817|    398|        }
  818|    739|        data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
  819|    739|        week_num = -1;
  820|    739|        continue;
  821|    498|      case 'U':
  ------------------
  |  Branch (821:7): [True: 498, False: 22.4k]
  ------------------
  822|    498|        data = ParseInt(data, 0, 0, 53, &week_num);
  823|    498|        week_start = weekday::sunday;
  824|    498|        continue;
  825|    488|      case 'W':
  ------------------
  |  Branch (825:7): [True: 488, False: 22.4k]
  ------------------
  826|    488|        data = ParseInt(data, 0, 0, 53, &week_num);
  827|    488|        week_start = weekday::monday;
  828|    488|        continue;
  829|    363|      case 'u':
  ------------------
  |  Branch (829:7): [True: 363, False: 22.5k]
  ------------------
  830|    363|        data = ParseInt(data, 0, 1, 7, &tm.tm_wday);
  831|    363|        if (data != nullptr) tm.tm_wday %= 7;
  ------------------
  |  Branch (831:13): [True: 145, False: 218]
  ------------------
  832|    363|        continue;
  833|    311|      case 'w':
  ------------------
  |  Branch (833:7): [True: 311, False: 22.6k]
  ------------------
  834|    311|        data = ParseInt(data, 0, 0, 6, &tm.tm_wday);
  835|    311|        continue;
  836|    485|      case 'H':
  ------------------
  |  Branch (836:7): [True: 485, False: 22.4k]
  ------------------
  837|    485|        data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
  838|    485|        twelve_hour = false;
  839|    485|        continue;
  840|    535|      case 'M':
  ------------------
  |  Branch (840:7): [True: 535, False: 22.4k]
  ------------------
  841|    535|        data = ParseInt(data, 2, 0, 59, &tm.tm_min);
  842|    535|        continue;
  843|    554|      case 'S':
  ------------------
  |  Branch (843:7): [True: 554, False: 22.4k]
  ------------------
  844|    554|        data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
  845|    554|        continue;
  846|    462|      case 'T':
  ------------------
  |  Branch (846:7): [True: 462, False: 22.4k]
  ------------------
  847|    462|        data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
  848|    462|        twelve_hour = false;
  849|    462|        data = (data != nullptr && *data == ':' ? data + 1 : nullptr);
  ------------------
  |  Branch (849:17): [True: 424, False: 38]
  |  Branch (849:36): [True: 401, False: 23]
  ------------------
  850|    462|        data = ParseInt(data, 2, 0, 59, &tm.tm_min);
  851|    462|        data = (data != nullptr && *data == ':' ? data + 1 : nullptr);
  ------------------
  |  Branch (851:17): [True: 372, False: 90]
  |  Branch (851:36): [True: 338, False: 34]
  ------------------
  852|    462|        data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
  853|    462|        continue;
  854|     75|      case 'I':
  ------------------
  |  Branch (854:7): [True: 75, False: 22.8k]
  ------------------
  855|    145|      case 'l':
  ------------------
  |  Branch (855:7): [True: 70, False: 22.8k]
  ------------------
  856|    157|      case 'r':  // probably uses %I
  ------------------
  |  Branch (856:7): [True: 12, False: 22.9k]
  ------------------
  857|    157|        twelve_hour = true;
  858|    157|        break;
  859|     27|      case 'R':  // uses %H
  ------------------
  |  Branch (859:7): [True: 27, False: 22.9k]
  ------------------
  860|     28|      case 'c':  // probably uses %H
  ------------------
  |  Branch (860:7): [True: 1, False: 22.9k]
  ------------------
  861|     48|      case 'X':  // probably uses %H
  ------------------
  |  Branch (861:7): [True: 20, False: 22.9k]
  ------------------
  862|     48|        twelve_hour = false;
  863|     48|        break;
  864|  3.50k|      case 'z':
  ------------------
  |  Branch (864:7): [True: 3.50k, False: 19.4k]
  ------------------
  865|  3.50k|        data = ParseOffset(data, "", &offset);
  866|  3.50k|        if (data != nullptr) saw_offset = true;
  ------------------
  |  Branch (866:13): [True: 3.44k, False: 69]
  ------------------
  867|  3.50k|        continue;
  868|    828|      case 'Z':  // ignored; zone abbreviations are ambiguous
  ------------------
  |  Branch (868:7): [True: 828, False: 22.1k]
  ------------------
  869|    828|        data = ParseZone(data, &zone);
  870|    828|        continue;
  871|    606|      case 's':
  ------------------
  |  Branch (871:7): [True: 606, False: 22.3k]
  ------------------
  872|    606|        data = ParseInt(data, 0,
  873|    606|                        std::numeric_limits<std::int_fast64_t>::min(),
  874|    606|                        std::numeric_limits<std::int_fast64_t>::max(),
  875|    606|                        &percent_s);
  876|    606|        if (data != nullptr) saw_percent_s = true;
  ------------------
  |  Branch (876:13): [True: 547, False: 59]
  ------------------
  877|    606|        continue;
  878|    932|      case ':':
  ------------------
  |  Branch (878:7): [True: 932, False: 22.0k]
  ------------------
  879|    932|        if (fmt[0] == 'z' ||
  ------------------
  |  Branch (879:13): [True: 469, False: 463]
  ------------------
  880|    463|            (fmt[0] == ':' &&
  ------------------
  |  Branch (880:14): [True: 451, False: 12]
  ------------------
  881|    893|             (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {
  ------------------
  |  Branch (881:15): [True: 228, False: 223]
  |  Branch (881:33): [True: 209, False: 14]
  |  Branch (881:50): [True: 196, False: 13]
  ------------------
  882|    893|          data = ParseOffset(data, ":", &offset);
  883|    893|          if (data != nullptr) saw_offset = true;
  ------------------
  |  Branch (883:15): [True: 873, False: 20]
  ------------------
  884|    893|          fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;
  ------------------
  |  Branch (884:18): [True: 469, False: 424]
  |  Branch (884:40): [True: 228, False: 196]
  ------------------
  885|    893|          continue;
  886|    893|        }
  887|     39|        break;
  888|    202|      case '%':
  ------------------
  |  Branch (888:7): [True: 202, False: 22.7k]
  ------------------
  889|    202|        data = (*data == '%' ? data + 1 : nullptr);
  ------------------
  |  Branch (889:17): [True: 194, False: 8]
  ------------------
  890|    202|        continue;
  891|  7.77k|      case 'E':
  ------------------
  |  Branch (891:7): [True: 7.77k, False: 15.1k]
  ------------------
  892|  7.77k|        if (fmt[0] == 'T') {
  ------------------
  |  Branch (892:13): [True: 398, False: 7.37k]
  ------------------
  893|    398|          if (*data == 'T' || *data == 't') {
  ------------------
  |  Branch (893:15): [True: 194, False: 204]
  |  Branch (893:31): [True: 194, False: 10]
  ------------------
  894|    388|            ++data;
  895|    388|            ++fmt;
  896|    388|          } else {
  897|     10|            data = nullptr;
  898|     10|          }
  899|    398|          continue;
  900|    398|        }
  901|  7.37k|        if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
  ------------------
  |  Branch (901:13): [True: 1.92k, False: 5.44k]
  |  Branch (901:31): [True: 3.66k, False: 1.78k]
  |  Branch (901:48): [True: 638, False: 3.02k]
  ------------------
  902|  2.56k|          data = ParseOffset(data, ":", &offset);
  903|  2.56k|          if (data != nullptr) saw_offset = true;
  ------------------
  |  Branch (903:15): [True: 2.54k, False: 18]
  ------------------
  904|  2.56k|          fmt += (fmt[0] == 'z') ? 1 : 2;
  ------------------
  |  Branch (904:18): [True: 1.92k, False: 638]
  ------------------
  905|  2.56k|          continue;
  906|  2.56k|        }
  907|  4.80k|        if (fmt[0] == '*' && fmt[1] == 'S') {
  ------------------
  |  Branch (907:13): [True: 3.02k, False: 1.78k]
  |  Branch (907:30): [True: 473, False: 2.55k]
  ------------------
  908|    473|          data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
  909|    473|          if (data != nullptr && *data == '.') {
  ------------------
  |  Branch (909:15): [True: 468, False: 5]
  |  Branch (909:34): [True: 6, False: 462]
  ------------------
  910|      6|            data = ParseSubSeconds(data + 1, &subseconds);
  911|      6|          }
  912|    473|          fmt += 2;
  913|    473|          continue;
  914|    473|        }
  915|  4.33k|        if (fmt[0] == '*' && fmt[1] == 'f') {
  ------------------
  |  Branch (915:13): [True: 2.55k, False: 1.78k]
  |  Branch (915:30): [True: 2.52k, False: 30]
  ------------------
  916|  2.52k|          if (data != nullptr && isdigit(*data)) {
  ------------------
  |  Branch (916:15): [True: 2.52k, False: 0]
  |  Branch (916:34): [True: 971, False: 1.54k]
  ------------------
  917|    971|            data = ParseSubSeconds(data, &subseconds);
  918|    971|          }
  919|  2.52k|          fmt += 2;
  920|  2.52k|          continue;
  921|  2.52k|        }
  922|  1.81k|        if (fmt[0] == '4' && fmt[1] == 'Y') {
  ------------------
  |  Branch (922:13): [True: 672, False: 1.14k]
  |  Branch (922:30): [True: 330, False: 342]
  ------------------
  923|    330|          const char* bp = data;
  924|    330|          data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
  925|    330|          if (data != nullptr) {
  ------------------
  |  Branch (925:15): [True: 309, False: 21]
  ------------------
  926|    309|            if (data - bp == 4) {
  ------------------
  |  Branch (926:17): [True: 263, False: 46]
  ------------------
  927|    263|              saw_year = true;
  928|    263|            } else {
  929|     46|              data = nullptr;  // stopped too soon
  930|     46|            }
  931|    309|          }
  932|    330|          fmt += 2;
  933|    330|          continue;
  934|    330|        }
  935|  1.48k|        if (isdigit(*fmt)) {
  ------------------
  |  Branch (935:13): [True: 1.36k, False: 121]
  ------------------
  936|  1.36k|          int n = 0;  // value ignored
  937|  1.36k|          if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) {
  ------------------
  |  Branch (937:27): [True: 1.22k, False: 136]
  ------------------
  938|  1.22k|            if (*np == 'S') {
  ------------------
  |  Branch (938:17): [True: 337, False: 890]
  ------------------
  939|    337|              data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
  940|    337|              if (data != nullptr && *data == '.') {
  ------------------
  |  Branch (940:19): [True: 313, False: 24]
  |  Branch (940:38): [True: 10, False: 303]
  ------------------
  941|     10|                data = ParseSubSeconds(data + 1, &subseconds);
  942|     10|              }
  943|    337|              fmt = ++np;
  944|    337|              continue;
  945|    337|            }
  946|    890|            if (*np == 'f') {
  ------------------
  |  Branch (946:17): [True: 835, False: 55]
  ------------------
  947|    835|              if (data != nullptr && isdigit(*data)) {
  ------------------
  |  Branch (947:19): [True: 835, False: 0]
  |  Branch (947:38): [True: 392, False: 443]
  ------------------
  948|    392|                data = ParseSubSeconds(data, &subseconds);
  949|    392|              }
  950|    835|              fmt = ++np;
  951|    835|              continue;
  952|    835|            }
  953|    890|          }
  954|  1.36k|        }
  955|    312|        if (*fmt == 'c') twelve_hour = false;  // probably uses %H
  ------------------
  |  Branch (955:13): [True: 1, False: 311]
  ------------------
  956|    312|        if (*fmt == 'X') twelve_hour = false;  // probably uses %H
  ------------------
  |  Branch (956:13): [True: 10, False: 302]
  ------------------
  957|    312|        if (*fmt != '\0') ++fmt;
  ------------------
  |  Branch (957:13): [True: 303, False: 9]
  ------------------
  958|    312|        break;
  959|     94|      case 'O':
  ------------------
  |  Branch (959:7): [True: 94, False: 22.8k]
  ------------------
  960|     94|        if (*fmt == 'H') twelve_hour = false;
  ------------------
  |  Branch (960:13): [True: 34, False: 60]
  ------------------
  961|     94|        if (*fmt == 'I') twelve_hour = true;
  ------------------
  |  Branch (961:13): [True: 38, False: 56]
  ------------------
  962|     94|        if (*fmt != '\0') ++fmt;
  ------------------
  |  Branch (962:13): [True: 89, False: 5]
  ------------------
  963|     94|        break;
  964|  22.9k|    }
  965|       |
  966|       |    // Parses the current specifier.
  967|  1.54k|    const char* const orig_data = data;
  968|  1.54k|    std::string spec(percent, fmt);
  969|  1.54k|    data = ParseTM(data, spec.c_str(), &tm);
  970|       |
  971|       |    // If we successfully parsed %p we need to remember whether the result
  972|       |    // was AM or PM so that we can adjust tm_hour before time_zone::lookup().
  973|       |    // So reparse the input with a known AM hour, and check if it is shifted
  974|       |    // to a PM hour.
  975|  1.54k|    if (spec == "%p" && data != nullptr) {
  ------------------
  |  Branch (975:9): [True: 233, False: 1.31k]
  |  Branch (975:25): [True: 228, False: 5]
  ------------------
  976|    228|      std::string test_input = "1";
  977|    228|      test_input.append(orig_data, data);
  978|    228|      std::tm tmp{};
  979|    228|      ParseTM(test_input.c_str(), "%I%p", &tmp);
  980|    228|      afternoon = (tmp.tm_hour == 13);
  981|    228|    }
  982|  1.54k|  }
  983|       |
  984|       |  // Adjust a 12-hour tm_hour value if it should be in the afternoon.
  985|  9.12k|  if (twelve_hour && afternoon && tm.tm_hour < 12) {
  ------------------
  |  Branch (985:7): [True: 41, False: 9.08k]
  |  Branch (985:22): [True: 2, False: 39]
  |  Branch (985:35): [True: 1, False: 1]
  ------------------
  986|      1|    tm.tm_hour += 12;
  987|      1|  }
  988|       |
  989|  9.12k|  if (data == nullptr) {
  ------------------
  |  Branch (989:7): [True: 2.40k, False: 6.72k]
  ------------------
  990|  2.40k|    if (err != nullptr) *err = "Failed to parse input";
  ------------------
  |  Branch (990:9): [True: 0, False: 2.40k]
  ------------------
  991|  2.40k|    return false;
  992|  2.40k|  }
  993|       |
  994|       |  // Skip any remaining whitespace.
  995|  6.92k|  while (isspace(*data)) ++data;
  ------------------
  |  Branch (995:10): [True: 200, False: 6.72k]
  ------------------
  996|       |
  997|       |  // parse() must consume the entire input string.
  998|  6.72k|  if (data != edata) {
  ------------------
  |  Branch (998:7): [True: 268, False: 6.45k]
  ------------------
  999|    268|    if (err != nullptr) *err = "Illegal trailing data in input string";
  ------------------
  |  Branch (999:9): [True: 0, False: 268]
  ------------------
 1000|    268|    return false;
 1001|    268|  }
 1002|       |
 1003|       |  // If we saw %s then we ignore anything else and return that time.
 1004|  6.45k|  if (saw_percent_s) {
  ------------------
  |  Branch (1004:7): [True: 280, False: 6.17k]
  ------------------
 1005|    280|    *sec = FromUnixSeconds(percent_s);
 1006|    280|    *fs = detail::femtoseconds::zero();
 1007|    280|    return true;
 1008|    280|  }
 1009|       |
 1010|       |  // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields
 1011|       |  // in UTC and then shift by that offset.  Otherwise we want to interpret
 1012|       |  // the fields directly in the passed time_zone.
 1013|  6.17k|  time_zone ptz = saw_offset ? utc_time_zone() : tz;
  ------------------
  |  Branch (1013:19): [True: 210, False: 5.96k]
  ------------------
 1014|       |
 1015|       |  // Allows a leap second of 60 to normalize forward to the following ":00".
 1016|  6.17k|  if (tm.tm_sec == 60) {
  ------------------
  |  Branch (1016:7): [True: 41, False: 6.13k]
  ------------------
 1017|     41|    tm.tm_sec -= 1;
 1018|     41|    offset -= 1;
 1019|     41|    subseconds = detail::femtoseconds::zero();
 1020|     41|  }
 1021|       |
 1022|  6.17k|  if (!saw_year) {
  ------------------
  |  Branch (1022:7): [True: 4.33k, False: 1.83k]
  ------------------
 1023|  4.33k|    year = year_t{tm.tm_year};
 1024|  4.33k|    if (year > kyearmax - 1900) {
  ------------------
  |  Branch (1024:9): [True: 0, False: 4.33k]
  ------------------
 1025|       |      // Platform-dependent, maybe unreachable.
 1026|      0|      if (err != nullptr) *err = "Out-of-range year";
  ------------------
  |  Branch (1026:11): [True: 0, False: 0]
  ------------------
 1027|      0|      return false;
 1028|      0|    }
 1029|  4.33k|    year += 1900;
 1030|  4.33k|  }
 1031|       |
 1032|       |  // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number.
 1033|  6.17k|  if (week_num != -1) {
  ------------------
  |  Branch (1033:7): [True: 336, False: 5.83k]
  ------------------
 1034|    336|    if (!FromWeek(week_num, week_start, &year, &tm)) {
  ------------------
  |  Branch (1034:9): [True: 2, False: 334]
  ------------------
 1035|      2|      if (err != nullptr) *err = "Out-of-range field";
  ------------------
  |  Branch (1035:11): [True: 0, False: 2]
  ------------------
 1036|      2|      return false;
 1037|      2|    }
 1038|    336|  }
 1039|       |
 1040|  6.17k|  const int month = tm.tm_mon + 1;
 1041|  6.17k|  civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
 1042|       |
 1043|       |  // parse() should not allow normalization. Due to the restricted field
 1044|       |  // ranges above (see ParseInt()), the only possibility is for days to roll
 1045|       |  // into months. That is, parsing "Sep 31" should not produce "Oct 1".
 1046|  6.17k|  if (cs.month() != month || cs.day() != tm.tm_mday) {
  ------------------
  |  Branch (1046:7): [True: 3, False: 6.17k]
  |  Branch (1046:30): [True: 0, False: 6.17k]
  ------------------
 1047|      3|    if (err != nullptr) *err = "Out-of-range field";
  ------------------
  |  Branch (1047:9): [True: 0, False: 3]
  ------------------
 1048|      3|    return false;
 1049|      3|  }
 1050|       |
 1051|       |  // Accounts for the offset adjustment before converting to absolute time.
 1052|  6.17k|  if ((offset < 0 && cs > civil_second::max() + offset) ||
  ------------------
  |  Branch (1052:7): [True: 1, False: 6.16k]
  |  Branch (1052:8): [True: 122, False: 6.04k]
  |  Branch (1052:22): [True: 0, False: 122]
  ------------------
 1053|  6.17k|      (offset > 0 && cs < civil_second::min() + offset)) {
  ------------------
  |  Branch (1053:8): [True: 93, False: 6.07k]
  |  Branch (1053:22): [True: 1, False: 92]
  ------------------
 1054|      1|    if (err != nullptr) *err = "Out-of-range field";
  ------------------
  |  Branch (1054:9): [True: 0, False: 1]
  ------------------
 1055|      1|    return false;
 1056|      1|  }
 1057|  6.16k|  cs -= offset;
 1058|       |
 1059|  6.16k|  const auto tp = ptz.lookup(cs).pre;
 1060|       |  // Checks for overflow/underflow and returns an error as necessary.
 1061|  6.16k|  if (tp == time_point<seconds>::max()) {
  ------------------
  |  Branch (1061:7): [True: 379, False: 5.79k]
  ------------------
 1062|    379|    const auto al = ptz.lookup(time_point<seconds>::max());
 1063|    379|    if (cs > al.cs) {
  ------------------
  |  Branch (1063:9): [True: 228, False: 151]
  ------------------
 1064|    228|      if (err != nullptr) *err = "Out-of-range field";
  ------------------
  |  Branch (1064:11): [True: 0, False: 228]
  ------------------
 1065|    228|      return false;
 1066|    228|    }
 1067|    379|  }
 1068|  5.94k|  if (tp == time_point<seconds>::min()) {
  ------------------
  |  Branch (1068:7): [True: 368, False: 5.57k]
  ------------------
 1069|    368|    const auto al = ptz.lookup(time_point<seconds>::min());
 1070|    368|    if (cs < al.cs) {
  ------------------
  |  Branch (1070:9): [True: 159, False: 209]
  ------------------
 1071|    159|      if (err != nullptr) *err = "Out-of-range field";
  ------------------
  |  Branch (1071:11): [True: 0, False: 159]
  ------------------
 1072|    159|      return false;
 1073|    159|    }
 1074|    368|  }
 1075|       |
 1076|  5.78k|  *sec = tp;
 1077|  5.78k|  *fs = subseconds;
 1078|  5.78k|  return true;
 1079|  5.94k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_14ToTMERKNS_9time_zone15absolute_lookupE:
  121|  9.12k|std::tm ToTM(const time_zone::absolute_lookup& al) {
  122|  9.12k|  std::tm tm{};
  123|  9.12k|  tm.tm_sec = al.cs.second();
  124|  9.12k|  tm.tm_min = al.cs.minute();
  125|  9.12k|  tm.tm_hour = al.cs.hour();
  126|  9.12k|  tm.tm_mday = al.cs.day();
  127|  9.12k|  tm.tm_mon = al.cs.month() - 1;
  128|       |
  129|       |  // Saturate tm.tm_year in cases of over/underflow.
  130|  9.12k|  if (al.cs.year() < std::numeric_limits<int>::min() + 1900) {
  ------------------
  |  Branch (130:7): [True: 0, False: 9.12k]
  ------------------
  131|      0|    tm.tm_year = std::numeric_limits<int>::min();
  132|  9.12k|  } else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) {
  ------------------
  |  Branch (132:14): [True: 654, False: 8.47k]
  ------------------
  133|    654|    tm.tm_year = std::numeric_limits<int>::max();
  134|  8.47k|  } else {
  135|  8.47k|    tm.tm_year = static_cast<int>(al.cs.year() - 1900);
  136|  8.47k|  }
  137|       |
  138|  9.12k|  tm.tm_wday = ToTmWday(get_weekday(al.cs));
  139|  9.12k|  tm.tm_yday = get_yearday(al.cs) - 1;
  140|  9.12k|  tm.tm_isdst = al.is_dst ? 1 : 0;
  ------------------
  |  Branch (140:17): [True: 714, False: 8.41k]
  ------------------
  141|  9.12k|  return tm;
  142|  9.12k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_18ToTmWdayENS0_7weekdayE:
   80|  9.12k|int ToTmWday(weekday wd) {
   81|  9.12k|  switch (wd) {
  ------------------
  |  Branch (81:11): [True: 9.12k, False: 0]
  ------------------
   82|    514|    case weekday::sunday:
  ------------------
  |  Branch (82:5): [True: 514, False: 8.61k]
  ------------------
   83|    514|      return 0;
   84|    493|    case weekday::monday:
  ------------------
  |  Branch (84:5): [True: 493, False: 8.63k]
  ------------------
   85|    493|      return 1;
   86|  6.26k|    case weekday::tuesday:
  ------------------
  |  Branch (86:5): [True: 6.26k, False: 2.86k]
  ------------------
   87|  6.26k|      return 2;
   88|    488|    case weekday::wednesday:
  ------------------
  |  Branch (88:5): [True: 488, False: 8.64k]
  ------------------
   89|    488|      return 3;
   90|    559|    case weekday::thursday:
  ------------------
  |  Branch (90:5): [True: 559, False: 8.56k]
  ------------------
   91|    559|      return 4;
   92|    381|    case weekday::friday:
  ------------------
  |  Branch (92:5): [True: 381, False: 8.74k]
  ------------------
   93|    381|      return 5;
   94|    425|    case weekday::saturday:
  ------------------
  |  Branch (94:5): [True: 425, False: 8.70k]
  ------------------
   95|    425|      return 6;
   96|  9.12k|  }
   97|      0|  return 0; /*NOTREACHED*/
   98|  9.12k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_18FormatTMEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERKS8_RK2tm:
  224|   121k|void FormatTM(std::string* out, const std::string& fmt, const std::tm& tm) {
  225|       |  // We assume that 16 times the length of the format string will
  226|       |  // be sufficient to store the result.  The extreme case appears
  227|       |  // to be "%c" (2 chars), which, in the POSIX locale, produces
  228|       |  // "Thu Jan 1 00:00:00 1970" (24 chars).
  229|   121k|  auto out_size = out->size();
  230|   121k|  auto buf_size = (16 * fmt.size()) + 1;
  231|   121k|  out->resize(out_size + buf_size);
  232|   121k|  auto len = strftime(&(*out)[out_size], buf_size, fmt.c_str(), &tm);
  233|   121k|  out->resize(out_size + len);
  234|   121k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_18Format64EPcil:
  156|  46.5k|char* Format64(char* ep, int width, std::int_fast64_t v) {
  157|  46.5k|  bool neg = false;
  158|  46.5k|  if (v < 0) {
  ------------------
  |  Branch (158:7): [True: 924, False: 45.6k]
  ------------------
  159|    924|    --width;
  160|    924|    neg = true;
  161|    924|    if (v == std::numeric_limits<std::int_fast64_t>::min()) {
  ------------------
  |  Branch (161:9): [True: 0, False: 924]
  ------------------
  162|       |      // Avoid negating minimum value.
  163|      0|      std::int_fast64_t last_digit = -(v % 10);
  164|      0|      v /= 10;
  165|      0|      if (last_digit < 0) {
  ------------------
  |  Branch (165:11): [True: 0, False: 0]
  ------------------
  166|      0|        ++v;
  167|      0|        last_digit += 10;
  168|      0|      }
  169|      0|      --width;
  170|      0|      *--ep = kDigits[last_digit];
  171|      0|    }
  172|    924|    v = -v;
  173|    924|  }
  174|   214k|  do {
  175|   214k|    --width;
  176|   214k|    *--ep = kDigits[v % 10];
  177|   214k|  } while (v /= 10);
  ------------------
  |  Branch (177:12): [True: 168k, False: 46.5k]
  ------------------
  178|   414k|  while (--width >= 0) *--ep = '0';  // zero pad
  ------------------
  |  Branch (178:10): [True: 368k, False: 46.5k]
  ------------------
  179|  46.5k|  if (neg) *--ep = '-';
  ------------------
  |  Branch (179:7): [True: 924, False: 45.6k]
  ------------------
  180|  46.5k|  return ep;
  181|  46.5k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_19Format02dEPci:
  184|   104k|char* Format02d(char* ep, int v) {
  185|   104k|  *--ep = kDigits[v % 10];
  186|   104k|  *--ep = kDigits[(v / 10) % 10];
  187|   104k|  return ep;
  188|   104k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_16ToWeekERKNS0_10civil_timeINS0_7day_tagEEENS0_7weekdayE:
  146|  7.95k|int ToWeek(const civil_day& cd, weekday week_start) {
  147|  7.95k|  const civil_day d(cd.year() % 400, cd.month(), cd.day());
  148|  7.95k|  return static_cast<int>((d - prev_weekday(civil_year(d), week_start)) / 7);
  149|  7.95k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_112FormatOffsetEPciPKc:
  191|  30.3k|char* FormatOffset(char* ep, int offset, const char* mode) {
  192|       |  // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and
  193|       |  // generate a "negative zero" when we're formatting a zero offset
  194|       |  // as the result of a failed load_time_zone().
  195|  30.3k|  char sign = '+';
  196|  30.3k|  if (offset < 0) {
  ------------------
  |  Branch (196:7): [True: 4.03k, False: 26.3k]
  ------------------
  197|  4.03k|    offset = -offset;  // bounded by 24h so no overflow
  198|  4.03k|    sign = '-';
  199|  4.03k|  }
  200|  30.3k|  const int seconds = offset % 60;
  201|  30.3k|  const int minutes = (offset /= 60) % 60;
  202|  30.3k|  const int hours = offset /= 60;
  203|  30.3k|  const char sep = mode[0];
  204|  30.3k|  const bool ext = (sep != '\0' && mode[1] == '*');
  ------------------
  |  Branch (204:21): [True: 22.7k, False: 7.62k]
  |  Branch (204:36): [True: 7.84k, False: 14.9k]
  ------------------
  205|  30.3k|  const bool ccc = (ext && mode[2] == ':');
  ------------------
  |  Branch (205:21): [True: 7.84k, False: 22.5k]
  |  Branch (205:28): [True: 1.59k, False: 6.24k]
  ------------------
  206|  30.3k|  if (ext && (!ccc || seconds != 0)) {
  ------------------
  |  Branch (206:7): [True: 7.84k, False: 22.5k]
  |  Branch (206:15): [True: 6.24k, False: 1.59k]
  |  Branch (206:23): [True: 375, False: 1.22k]
  ------------------
  207|  6.62k|    ep = Format02d(ep, seconds);
  208|  6.62k|    *--ep = sep;
  209|  23.7k|  } else {
  210|       |    // If we're not rendering seconds, sub-minute negative offsets
  211|       |    // should get a positive sign (e.g., offset=-10s => "+00:00").
  212|  23.7k|    if (hours == 0 && minutes == 0) sign = '+';
  ------------------
  |  Branch (212:9): [True: 3.72k, False: 20.0k]
  |  Branch (212:23): [True: 2.78k, False: 941]
  ------------------
  213|  23.7k|  }
  214|  30.3k|  if (!ccc || minutes != 0 || seconds != 0) {
  ------------------
  |  Branch (214:7): [True: 28.7k, False: 1.59k]
  |  Branch (214:15): [True: 383, False: 1.21k]
  |  Branch (214:31): [True: 203, False: 1.01k]
  ------------------
  215|  29.3k|    ep = Format02d(ep, minutes);
  216|  29.3k|    if (sep != '\0') *--ep = sep;
  ------------------
  |  Branch (216:9): [True: 21.7k, False: 7.62k]
  ------------------
  217|  29.3k|  }
  218|  30.3k|  ep = Format02d(ep, hours);
  219|  30.3k|  *--ep = sign;
  220|  30.3k|  return ep;
  221|  30.3k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_17isdigitEc:
   60|  46.4k|bool isdigit(char ch) {
   61|  46.4k|  return std::isdigit(static_cast<unsigned char>(ch)) != 0;
   62|  46.4k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_17isspaceEc:
   64|   366k|bool isspace(char ch) {
   65|   366k|  return std::isspace(static_cast<unsigned char>(ch)) != 0;
   66|   366k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_111ParseOffsetEPKcS3_Pi:
  593|  6.96k|const char* ParseOffset(const char* dp, const char* mode, int* offset) {
  594|  6.96k|  if (dp != nullptr) {
  ------------------
  |  Branch (594:7): [True: 6.96k, False: 0]
  ------------------
  595|  6.96k|    const char first = *dp++;
  596|  6.96k|    if (first == '+' || first == '-') {
  ------------------
  |  Branch (596:9): [True: 1.33k, False: 5.63k]
  |  Branch (596:25): [True: 3.82k, False: 1.80k]
  ------------------
  597|  5.16k|      char sep = mode[0];
  598|  5.16k|      int hours = 0;
  599|  5.16k|      int minutes = 0;
  600|  5.16k|      int seconds = 0;
  601|  5.16k|      const char* ap = ParseInt(dp, 2, 0, 23, &hours);
  602|  5.16k|      if (ap != nullptr && ap - dp == 2) {
  ------------------
  |  Branch (602:11): [True: 5.13k, False: 32]
  |  Branch (602:28): [True: 5.11k, False: 15]
  ------------------
  603|  5.11k|        dp = ap;
  604|  5.11k|        if (sep != '\0' && *ap == sep) ++ap;
  ------------------
  |  Branch (604:13): [True: 2.33k, False: 2.77k]
  |  Branch (604:28): [True: 19, False: 2.31k]
  ------------------
  605|  5.11k|        const char* bp = ParseInt(ap, 2, 0, 59, &minutes);
  606|  5.11k|        if (bp != nullptr && bp - ap == 2) {
  ------------------
  |  Branch (606:13): [True: 3.06k, False: 2.04k]
  |  Branch (606:30): [True: 2.34k, False: 719]
  ------------------
  607|  2.34k|          dp = bp;
  608|  2.34k|          if (sep != '\0' && *bp == sep) ++bp;
  ------------------
  |  Branch (608:15): [True: 1.16k, False: 1.18k]
  |  Branch (608:30): [True: 18, False: 1.14k]
  ------------------
  609|  2.34k|          const char* cp = ParseInt(bp, 2, 0, 59, &seconds);
  610|  2.34k|          if (cp != nullptr && cp - bp == 2) dp = cp;
  ------------------
  |  Branch (610:15): [True: 939, False: 1.40k]
  |  Branch (610:32): [True: 586, False: 353]
  ------------------
  611|  2.34k|        }
  612|  5.11k|        *offset = ((hours * 60 + minutes) * 60) + seconds;
  613|  5.11k|        if (first == '-') *offset = -*offset;
  ------------------
  |  Branch (613:13): [True: 3.79k, False: 1.32k]
  ------------------
  614|  5.11k|      } else {
  615|     47|        dp = nullptr;
  616|     47|      }
  617|  5.16k|    } else if (first == 'Z' || first == 'z') {  // Zulu
  ------------------
  |  Branch (617:16): [True: 672, False: 1.13k]
  |  Branch (617:32): [True: 1.07k, False: 60]
  ------------------
  618|  1.74k|      *offset = 0;
  619|  1.74k|    } else {
  620|     60|      dp = nullptr;
  621|     60|    }
  622|  6.96k|  }
  623|  6.96k|  return dp;
  624|  6.96k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_19ParseZoneEPKcPNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEE:
  626|    828|const char* ParseZone(const char* dp, std::string* zone) {
  627|    828|  zone->clear();
  628|    828|  if (dp != nullptr) {
  ------------------
  |  Branch (628:7): [True: 828, False: 0]
  ------------------
  629|   319k|    while (*dp != '\0' && !isspace(*dp)) zone->push_back(*dp++);
  ------------------
  |  Branch (629:12): [True: 319k, False: 272]
  |  Branch (629:27): [True: 319k, False: 556]
  ------------------
  630|    828|    if (zone->empty()) dp = nullptr;
  ------------------
  |  Branch (630:9): [True: 21, False: 807]
  ------------------
  631|    828|  }
  632|    828|  return dp;
  633|    828|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_115ParseSubSecondsEPKcPNSt3__16chrono8durationIlNS4_5ratioILl1ELl1000000000000000EEEEE:
  635|  1.37k|const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) {
  636|  1.37k|  if (dp != nullptr) {
  ------------------
  |  Branch (636:7): [True: 1.37k, False: 0]
  ------------------
  637|  1.37k|    std::int_fast64_t v = 0;
  638|  1.37k|    std::int_fast64_t exp = 0;
  639|  1.37k|    const char* const bp = dp;
  640|  3.78k|    while (const char* cp = strchr(kDigits, *dp)) {
  ------------------
  |  Branch (640:24): [True: 2.46k, False: 1.32k]
  ------------------
  641|  2.46k|      int d = static_cast<int>(cp - kDigits);
  642|  2.46k|      if (d >= 10) break;
  ------------------
  |  Branch (642:11): [True: 59, False: 2.40k]
  ------------------
  643|  2.40k|      if (exp < 15) {
  ------------------
  |  Branch (643:11): [True: 2.08k, False: 324]
  ------------------
  644|  2.08k|        exp += 1;
  645|  2.08k|        v *= 10;
  646|  2.08k|        v += d;
  647|  2.08k|      }
  648|  2.40k|      ++dp;
  649|  2.40k|    }
  650|  1.37k|    if (dp != bp) {
  ------------------
  |  Branch (650:9): [True: 1.37k, False: 7]
  ------------------
  651|  1.37k|      v *= kExp10[15 - exp];
  652|  1.37k|      *subseconds = detail::femtoseconds(v);
  653|  1.37k|    } else {
  654|      7|      dp = nullptr;
  655|      7|    }
  656|  1.37k|  }
  657|  1.37k|  return dp;
  658|  1.37k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_17ParseTMEPKcS3_P2tm:
  661|  1.77k|const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {
  662|  1.77k|  if (dp != nullptr) {
  ------------------
  |  Branch (662:7): [True: 1.77k, False: 0]
  ------------------
  663|  1.77k|    dp = strptime(dp, fmt, tm);
  664|  1.77k|  }
  665|  1.77k|  return dp;
  666|  1.77k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_18FromWeekEiNS0_7weekdayEPlP2tm:
  671|    336|bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
  672|    336|  const civil_year y(*year % 400);
  673|    336|  civil_day cd = prev_weekday(y, week_start);  // week 0
  674|    336|  cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7);
  675|    336|  if (const year_t shift = cd.year() - y.year()) {
  ------------------
  |  Branch (675:20): [True: 203, False: 133]
  ------------------
  676|    203|    if (shift > 0) {
  ------------------
  |  Branch (676:9): [True: 71, False: 132]
  ------------------
  677|     71|      if (*year > std::numeric_limits<year_t>::max() - shift) return false;
  ------------------
  |  Branch (677:11): [True: 1, False: 70]
  ------------------
  678|    132|    } else {
  679|    132|      if (*year < std::numeric_limits<year_t>::min() - shift) return false;
  ------------------
  |  Branch (679:11): [True: 1, False: 131]
  ------------------
  680|    132|    }
  681|    201|    *year += shift;
  682|    201|  }
  683|    334|  tm->tm_mon = cd.month() - 1;
  684|    334|  tm->tm_mday = cd.day();
  685|    334|  return true;
  686|    336|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_110FromTmWdayEi:
  101|    336|weekday FromTmWday(int tm_wday) {
  102|    336|  switch (tm_wday) {
  ------------------
  |  Branch (102:11): [True: 336, False: 0]
  ------------------
  103|     10|    case 0:
  ------------------
  |  Branch (103:5): [True: 10, False: 326]
  ------------------
  104|     10|      return weekday::sunday;
  105|     14|    case 1:
  ------------------
  |  Branch (105:5): [True: 14, False: 322]
  ------------------
  106|     14|      return weekday::monday;
  107|      1|    case 2:
  ------------------
  |  Branch (107:5): [True: 1, False: 335]
  ------------------
  108|      1|      return weekday::tuesday;
  109|     10|    case 3:
  ------------------
  |  Branch (109:5): [True: 10, False: 326]
  ------------------
  110|     10|      return weekday::wednesday;
  111|    290|    case 4:
  ------------------
  |  Branch (111:5): [True: 290, False: 46]
  ------------------
  112|    290|      return weekday::thursday;
  113|      7|    case 5:
  ------------------
  |  Branch (113:5): [True: 7, False: 329]
  ------------------
  114|      7|      return weekday::friday;
  115|      4|    case 6:
  ------------------
  |  Branch (115:5): [True: 4, False: 332]
  ------------------
  116|      4|      return weekday::saturday;
  117|    336|  }
  118|      0|  return weekday::sunday; /*NOTREACHED*/
  119|    336|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_18ParseIntIiEEPKcS4_iT_S5_PS5_:
  238|  43.7k|const char* ParseInt(const char* dp, int width, T min, T max, T* vp) {
  239|  43.7k|  if (dp != nullptr) {
  ------------------
  |  Branch (239:7): [True: 42.8k, False: 837]
  ------------------
  240|  42.8k|    const T kmin = std::numeric_limits<T>::min();
  241|  42.8k|    bool erange = false;
  242|  42.8k|    bool neg = false;
  243|  42.8k|    T value = 0;
  244|  42.8k|    if (*dp == '-') {
  ------------------
  |  Branch (244:9): [True: 2.43k, False: 40.4k]
  ------------------
  245|  2.43k|      neg = true;
  246|  2.43k|      if (width <= 0 || --width != 0) {
  ------------------
  |  Branch (246:11): [True: 204, False: 2.22k]
  |  Branch (246:25): [True: 2.22k, False: 0]
  ------------------
  247|  2.43k|        ++dp;
  248|  2.43k|      } else {
  249|      0|        dp = nullptr;  // width was 1
  250|      0|      }
  251|  2.43k|    }
  252|  42.8k|    if (const char* const bp = dp) {
  ------------------
  |  Branch (252:27): [True: 42.8k, False: 0]
  ------------------
  253|   179k|      while (const char* cp = strchr(kDigits, *dp)) {
  ------------------
  |  Branch (253:26): [True: 156k, False: 22.5k]
  ------------------
  254|   156k|        int d = static_cast<int>(cp - kDigits);
  255|   156k|        if (d >= 10) break;
  ------------------
  |  Branch (255:13): [True: 1.90k, False: 154k]
  ------------------
  256|   154k|        if (value < kmin / 10) {
  ------------------
  |  Branch (256:13): [True: 3.29k, False: 151k]
  ------------------
  257|  3.29k|          erange = true;
  258|  3.29k|          break;
  259|  3.29k|        }
  260|   151k|        value *= 10;
  261|   151k|        if (value < kmin + d) {
  ------------------
  |  Branch (261:13): [True: 707, False: 150k]
  ------------------
  262|    707|          erange = true;
  263|    707|          break;
  264|    707|        }
  265|   150k|        value -= d;
  266|   150k|        dp += 1;
  267|   150k|        if (width > 0 && --width == 0) break;
  ------------------
  |  Branch (267:13): [True: 29.2k, False: 121k]
  |  Branch (267:26): [True: 14.3k, False: 14.8k]
  ------------------
  268|   150k|      }
  269|  42.8k|      if (dp != bp && !erange && (neg || value != kmin)) {
  ------------------
  |  Branch (269:11): [True: 41.5k, False: 1.36k]
  |  Branch (269:23): [True: 37.5k, False: 4.00k]
  |  Branch (269:35): [True: 2.40k, False: 35.1k]
  |  Branch (269:42): [True: 34.8k, False: 283]
  ------------------
  270|  37.2k|        if (!neg || value != 0) {
  ------------------
  |  Branch (270:13): [True: 34.8k, False: 2.40k]
  |  Branch (270:21): [True: 1.13k, False: 1.26k]
  ------------------
  271|  35.9k|          if (!neg) value = -value;  // make positive
  ------------------
  |  Branch (271:15): [True: 34.8k, False: 1.13k]
  ------------------
  272|  35.9k|          if (min <= value && value <= max) {
  ------------------
  |  Branch (272:15): [True: 34.8k, False: 1.14k]
  |  Branch (272:31): [True: 32.1k, False: 2.67k]
  ------------------
  273|  32.1k|            *vp = value;
  274|  32.1k|          } else {
  275|  3.81k|            dp = nullptr;
  276|  3.81k|          }
  277|  35.9k|        } else {
  278|  1.26k|          dp = nullptr;
  279|  1.26k|        }
  280|  37.2k|      } else {
  281|  5.65k|        dp = nullptr;
  282|  5.65k|      }
  283|  42.8k|    }
  284|  42.8k|  }
  285|  43.7k|  return dp;
  286|  43.7k|}
time_zone_format.cc:_ZN4cctz6detail12_GLOBAL__N_18ParseIntIlEEPKcS4_iT_S5_PS5_:
  238|  3.82k|const char* ParseInt(const char* dp, int width, T min, T max, T* vp) {
  239|  3.82k|  if (dp != nullptr) {
  ------------------
  |  Branch (239:7): [True: 3.82k, False: 0]
  ------------------
  240|  3.82k|    const T kmin = std::numeric_limits<T>::min();
  241|  3.82k|    bool erange = false;
  242|  3.82k|    bool neg = false;
  243|  3.82k|    T value = 0;
  244|  3.82k|    if (*dp == '-') {
  ------------------
  |  Branch (244:9): [True: 1.85k, False: 1.97k]
  ------------------
  245|  1.85k|      neg = true;
  246|  1.85k|      if (width <= 0 || --width != 0) {
  ------------------
  |  Branch (246:11): [True: 1.79k, False: 61]
  |  Branch (246:25): [True: 61, False: 0]
  ------------------
  247|  1.85k|        ++dp;
  248|  1.85k|      } else {
  249|      0|        dp = nullptr;  // width was 1
  250|      0|      }
  251|  1.85k|    }
  252|  3.82k|    if (const char* const bp = dp) {
  ------------------
  |  Branch (252:27): [True: 3.82k, False: 0]
  ------------------
  253|  33.9k|      while (const char* cp = strchr(kDigits, *dp)) {
  ------------------
  |  Branch (253:26): [True: 32.9k, False: 1.02k]
  ------------------
  254|  32.9k|        int d = static_cast<int>(cp - kDigits);
  255|  32.9k|        if (d >= 10) break;
  ------------------
  |  Branch (255:13): [True: 2.44k, False: 30.5k]
  ------------------
  256|  30.5k|        if (value < kmin / 10) {
  ------------------
  |  Branch (256:13): [True: 84, False: 30.4k]
  ------------------
  257|     84|          erange = true;
  258|     84|          break;
  259|     84|        }
  260|  30.4k|        value *= 10;
  261|  30.4k|        if (value < kmin + d) {
  ------------------
  |  Branch (261:13): [True: 3, False: 30.4k]
  ------------------
  262|      3|          erange = true;
  263|      3|          break;
  264|      3|        }
  265|  30.4k|        value -= d;
  266|  30.4k|        dp += 1;
  267|  30.4k|        if (width > 0 && --width == 0) break;
  ------------------
  |  Branch (267:13): [True: 1.08k, False: 29.3k]
  |  Branch (267:26): [True: 263, False: 825]
  ------------------
  268|  30.4k|      }
  269|  3.82k|      if (dp != bp && !erange && (neg || value != kmin)) {
  ------------------
  |  Branch (269:11): [True: 3.73k, False: 92]
  |  Branch (269:23): [True: 3.64k, False: 87]
  |  Branch (269:35): [True: 1.83k, False: 1.80k]
  |  Branch (269:42): [True: 1.80k, False: 3]
  ------------------
  270|  3.64k|        if (!neg || value != 0) {
  ------------------
  |  Branch (270:13): [True: 1.80k, False: 1.83k]
  |  Branch (270:21): [True: 1.82k, False: 5]
  ------------------
  271|  3.63k|          if (!neg) value = -value;  // make positive
  ------------------
  |  Branch (271:15): [True: 1.80k, False: 1.82k]
  ------------------
  272|  3.63k|          if (min <= value && value <= max) {
  ------------------
  |  Branch (272:15): [True: 3.63k, False: 0]
  |  Branch (272:31): [True: 3.63k, False: 0]
  ------------------
  273|  3.63k|            *vp = value;
  274|  3.63k|          } else {
  275|      0|            dp = nullptr;
  276|      0|          }
  277|  3.63k|        } else {
  278|      5|          dp = nullptr;
  279|      5|        }
  280|  3.64k|      } else {
  281|    182|        dp = nullptr;
  282|    182|      }
  283|  3.82k|    }
  284|  3.82k|  }
  285|  3.82k|  return dp;
  286|  3.82k|}

_ZN4cctz10TimeZoneIf3UTCEv:
   21|      1|std::unique_ptr<TimeZoneIf> TimeZoneIf::UTC() {
   22|      1|  return TimeZoneInfo::UTC();
   23|      1|}
_ZN4cctz10TimeZoneIf4MakeERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   25|  1.56k|std::unique_ptr<TimeZoneIf> TimeZoneIf::Make(const std::string& name) {
   26|       |  // Support "libc:localtime" and "libc:*" to access the legacy
   27|       |  // localtime and UTC support respectively from the C library.
   28|       |  // NOTE: The "libc:*" zones are internal, test-only interfaces, and
   29|       |  // are subject to change/removal without notice. Do not use them.
   30|  1.56k|  if (name.compare(0, 5, "libc:") == 0) {
  ------------------
  |  Branch (30:7): [True: 272, False: 1.29k]
  ------------------
   31|    272|    return TimeZoneLibC::Make(name.substr(5));
   32|    272|  }
   33|       |
   34|       |  // Otherwise use the "zoneinfo" implementation.
   35|  1.29k|  return TimeZoneInfo::Make(name);
   36|  1.56k|}
_ZN4cctz10TimeZoneIfD2Ev:
   39|    711|TimeZoneIf::~TimeZoneIf() {}

_ZN4cctz13ToUnixSecondsERKNSt3__16chrono10time_pointINS1_12system_clockENS1_8durationIlNS0_5ratioILl1ELl1EEEEEEE:
   61|  16.1k|inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) {
   62|  16.1k|  return (tp - std::chrono::time_point_cast<seconds>(
   63|  16.1k|                   std::chrono::system_clock::from_time_t(0))).count();
   64|  16.1k|}
_ZN4cctz15FromUnixSecondsEl:
   65|  15.0k|inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {
   66|  15.0k|  return std::chrono::time_point_cast<seconds>(
   67|  15.0k|             std::chrono::system_clock::from_time_t(0)) + seconds(t);
   68|  15.0k|}
_ZN4cctz10TimeZoneIfC2Ev:
   52|  1.56k|  TimeZoneIf() = default;

_ZN4cctz9time_zone4Impl3UTCEv:
   45|    210|time_zone time_zone::Impl::UTC() {
   46|    210|  return time_zone(UTCImpl());
   47|    210|}
_ZN4cctz9time_zone4Impl12LoadTimeZoneERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEPS0_:
   49|  9.83k|bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
   50|  9.83k|  const Impl* const utc_impl = UTCImpl();
   51|       |
   52|       |  // Check for UTC (which is never a key in time_zone_map).
   53|  9.83k|  auto offset = seconds::zero();
   54|  9.83k|  if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) {
  ------------------
  |  Branch (54:7): [True: 2.07k, False: 7.76k]
  |  Branch (54:7): [True: 1.66k, False: 8.17k]
  |  Branch (54:45): [True: 1.66k, False: 417]
  ------------------
   55|  1.66k|    *tz = time_zone(utc_impl);
   56|  1.66k|    return true;
   57|  1.66k|  }
   58|       |
   59|       |  // Check whether the time zone has already been loaded.
   60|  8.17k|  {
   61|  8.17k|    std::lock_guard<std::mutex> lock(TimeZoneMutex());
   62|  8.17k|    if (time_zone_map != nullptr) {
  ------------------
  |  Branch (62:9): [True: 8.17k, False: 1]
  ------------------
   63|  8.17k|      TimeZoneImplByName::const_iterator itr = time_zone_map->find(name);
   64|  8.17k|      if (itr != time_zone_map->end()) {
  ------------------
  |  Branch (64:11): [True: 6.61k, False: 1.56k]
  ------------------
   65|  6.61k|        *tz = time_zone(itr->second);
   66|  6.61k|        return itr->second != utc_impl;
   67|  6.61k|      }
   68|  8.17k|    }
   69|  8.17k|  }
   70|       |
   71|       |  // Load the new time zone (outside the lock).
   72|  1.56k|  std::unique_ptr<const Impl> new_impl(new Impl(name));
   73|       |
   74|       |  // Add the new time zone to the map.
   75|  1.56k|  std::lock_guard<std::mutex> lock(TimeZoneMutex());
   76|  1.56k|  if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName;
  ------------------
  |  Branch (76:7): [True: 1, False: 1.56k]
  ------------------
   77|  1.56k|  if (!new_impl->zone_) {
  ------------------
  |  Branch (77:7): [True: 711, False: 852]
  ------------------
   78|       |    // Load failed, but a successful insertion may have happened concurrently.
   79|       |    // Check it now that we have the lock. Otherwise, avoid caching negative
   80|       |    // entries to avoid unbounded growth and DoS attacks.
   81|    711|    auto itr = time_zone_map->find(name);
   82|    711|    const Impl* impl = (itr != time_zone_map->end()) ? itr->second : utc_impl;
  ------------------
  |  Branch (82:24): [True: 0, False: 711]
  ------------------
   83|    711|    *tz = time_zone(impl);
   84|    711|    return impl != utc_impl;
   85|    711|  }
   86|    852|  const Impl*& impl = (*time_zone_map)[name];
   87|    852|  if (impl == nullptr) {  // this thread won any load race
  ------------------
  |  Branch (87:7): [True: 852, False: 0]
  ------------------
   88|    852|    impl = new_impl.release();
   89|    852|  }
   90|    852|  *tz = time_zone(impl);
   91|    852|  return impl != utc_impl;
   92|  1.56k|}
_ZN4cctz9time_zone4ImplC2Ev:
  109|      1|time_zone::Impl::Impl() : name_("UTC"), zone_(TimeZoneIf::UTC()) {}
_ZN4cctz9time_zone4ImplC2ERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  112|  1.56k|    : name_(name), zone_(TimeZoneIf::Make(name_)) {}
_ZN4cctz9time_zone4Impl7UTCImplEv:
  114|  10.0k|const time_zone::Impl* time_zone::Impl::UTCImpl() {
  115|  10.0k|  static const Impl* utc_impl = new Impl;
  116|  10.0k|  return utc_impl;
  117|  10.0k|}
time_zone_impl.cc:_ZN4cctz12_GLOBAL__N_113TimeZoneMutexEv:
   36|  9.74k|std::mutex& TimeZoneMutex() {
   37|       |  // This mutex is intentionally "leaked" to avoid the static deinitialization
   38|       |  // order fiasco (std::mutex's destructor is not trivial on many platforms).
   39|  9.74k|  static std::mutex* time_zone_mutex = new std::mutex;
   40|  9.74k|  return *time_zone_mutex;
   41|  9.74k|}

_ZNK4cctz9time_zone4Impl9BreakTimeERKNSt3__16chrono10time_pointINS3_12system_clockENS3_8durationIlNS2_5ratioILl1ELl1EEEEEEE:
   49|  9.87k|  time_zone::absolute_lookup BreakTime(const time_point<seconds>& tp) const {
   50|  9.87k|    return zone_->BreakTime(tp);
   51|  9.87k|  }
_ZNK4cctz9time_zone4Impl8MakeTimeERKNS_6detail10civil_timeINS2_10second_tagEEE:
   56|  15.2k|  time_zone::civil_lookup MakeTime(const civil_second& cs) const {
   57|  15.2k|    return zone_->MakeTime(cs);
   58|  15.2k|  }

_ZN4cctz12TimeZoneInfo17GetTransitionTypeElbRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEPh:
  273|    377|                                     std::uint_least8_t* index) {
  274|    377|  std::size_t type_index = 0;
  275|    377|  std::size_t abbr_index = abbreviations_.size();
  276|    567|  for (; type_index != transition_types_.size(); ++type_index) {
  ------------------
  |  Branch (276:10): [True: 567, False: 0]
  ------------------
  277|    567|    const TransitionType& tt(transition_types_[type_index]);
  278|    567|    const char* tt_abbr = &abbreviations_[tt.abbr_index];
  279|    567|    if (tt_abbr == abbr) abbr_index = tt.abbr_index;
  ------------------
  |  Branch (279:9): [True: 377, False: 190]
  ------------------
  280|    567|    if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) {
  ------------------
  |  Branch (280:9): [True: 392, False: 175]
  |  Branch (280:40): [True: 387, False: 5]
  ------------------
  281|    387|      if (abbr_index == tt.abbr_index) break;  // reuse
  ------------------
  |  Branch (281:11): [True: 377, False: 10]
  ------------------
  282|    387|    }
  283|    567|  }
  284|    377|  if (type_index > 255 || abbr_index > 255) {
  ------------------
  |  Branch (284:7): [True: 0, False: 377]
  |  Branch (284:27): [True: 0, False: 377]
  ------------------
  285|       |    // No index space (8 bits) available for a new type or abbreviation.
  286|      0|    return false;
  287|      0|  }
  288|    377|  if (type_index == transition_types_.size()) {
  ------------------
  |  Branch (288:7): [True: 0, False: 377]
  ------------------
  289|      0|    TransitionType& tt(*transition_types_.emplace(transition_types_.end()));
  290|      0|    tt.utc_offset = static_cast<std::int_least32_t>(utc_offset);
  291|      0|    tt.is_dst = is_dst;
  292|      0|    if (abbr_index == abbreviations_.size()) {
  ------------------
  |  Branch (292:9): [True: 0, False: 0]
  ------------------
  293|      0|      abbreviations_.append(abbr);
  294|      0|      abbreviations_.append(1, '\0');
  295|      0|    }
  296|      0|    tt.abbr_index = static_cast<std::uint_least8_t>(abbr_index);
  297|      0|  }
  298|    377|  *index = static_cast<std::uint_least8_t>(type_index);
  299|    377|  return true;
  300|    377|}
_ZNK4cctz12TimeZoneInfo16EquivTransitionsEhh:
  306|    117|                                    std::uint_fast8_t tt2_index) const {
  307|    117|  if (tt1_index == tt2_index) return true;
  ------------------
  |  Branch (307:7): [True: 117, False: 0]
  ------------------
  308|      0|  const TransitionType& tt1(transition_types_[tt1_index]);
  309|      0|  const TransitionType& tt2(transition_types_[tt2_index]);
  310|      0|  if (tt1.utc_offset != tt2.utc_offset) return false;
  ------------------
  |  Branch (310:7): [True: 0, False: 0]
  ------------------
  311|      0|  if (tt1.is_dst != tt2.is_dst) return false;
  ------------------
  |  Branch (311:7): [True: 0, False: 0]
  ------------------
  312|      0|  if (tt1.abbr_index != tt2.abbr_index) return false;
  ------------------
  |  Branch (312:7): [True: 0, False: 0]
  ------------------
  313|      0|  return true;
  314|      0|}
_ZN4cctz12TimeZoneInfo17ExtendTransitionsEv:
  318|    247|bool TimeZoneInfo::ExtendTransitions() {
  319|    247|  extended_ = false;
  320|    247|  if (future_spec_.empty()) return true;  // last transition prevails
  ------------------
  |  Branch (320:7): [True: 0, False: 247]
  ------------------
  321|       |
  322|    247|  PosixTimeZone posix;
  323|    247|  if (!ParsePosixSpec(future_spec_, &posix)) return false;
  ------------------
  |  Branch (323:7): [True: 0, False: 247]
  ------------------
  324|       |
  325|       |  // Find transition type for the future std specification.
  326|    247|  std::uint_least8_t std_ti;
  327|    247|  if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti))
  ------------------
  |  Branch (327:7): [True: 0, False: 247]
  ------------------
  328|      0|    return false;
  329|       |
  330|    247|  if (posix.dst_abbr.empty()) {  // std only
  ------------------
  |  Branch (330:7): [True: 117, False: 130]
  ------------------
  331|       |    // The future specification should match the last transition, and
  332|       |    // that means that handling the future will fall out naturally.
  333|    117|    return EquivTransitions(transitions_.back().type_index, std_ti);
  334|    117|  }
  335|       |
  336|       |  // Find transition type for the future dst specification.
  337|    130|  std::uint_least8_t dst_ti;
  338|    130|  if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti))
  ------------------
  |  Branch (338:7): [True: 0, False: 130]
  ------------------
  339|      0|    return false;
  340|       |
  341|    130|  if (AllYearDST(posix)) {  // dst only
  ------------------
  |  Branch (341:7): [True: 0, False: 130]
  ------------------
  342|       |    // The future specification should match the last transition, and
  343|       |    // that means that handling the future will fall out naturally.
  344|      0|    return EquivTransitions(transitions_.back().type_index, dst_ti);
  345|      0|  }
  346|       |
  347|       |  // We require that zoneinfo data with a rule for future transitions
  348|       |  // ends with a non-negative transition.  This removes the need to add
  349|       |  // any "second-half" transition to ensure differences between adjacent
  350|       |  // transitions are always representable, while also guaranteeing that
  351|       |  // the arithmetic used to shift between 400-year cycles never overflows.
  352|       |  // All valid zones easily meet this requirement.
  353|    130|  if (transitions_.back().unix_time < 0) return false;
  ------------------
  |  Branch (353:7): [True: 0, False: 130]
  ------------------
  354|       |
  355|       |  // Extend the transitions for an additional 401 years using the future
  356|       |  // specification. Years beyond those can be handled by mapping back to
  357|       |  // a cycle-equivalent year within that range. Note that we need 401
  358|       |  // (well, at least the first transition in the 401st year) so that the
  359|       |  // end of the 400th year is mapped back to an extended year. And first
  360|       |  // we may also need two additional transitions for the current year.
  361|    130|  transitions_.reserve(transitions_.size() + 2 + 401 * 2);
  362|    130|  extended_ = true;
  363|       |
  364|    130|  const Transition& last(transitions_.back());
  365|    130|  const std::int_fast64_t last_time = last.unix_time;
  366|    130|  const TransitionType& last_tt(transition_types_[last.type_index]);
  367|    130|  last_year_ = LocalTime(last_time, last_tt).cs.year();
  368|    130|  bool leap_year = IsLeap(last_year_);
  369|    130|  const civil_second jan1(last_year_);
  370|    130|  std::int_fast64_t jan1_time = jan1 - civil_second();
  371|    130|  int jan1_weekday = ToPosixWeekday(get_weekday(jan1));
  372|       |
  373|    130|  Transition dst = {0, dst_ti, civil_second(), civil_second()};
  374|    130|  Transition std = {0, std_ti, civil_second(), civil_second()};
  375|  52.2k|  for (const year_t limit = last_year_ + 401;; ++last_year_) {
  376|  52.2k|    auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start);
  377|  52.2k|    auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end);
  378|  52.2k|    dst.unix_time = jan1_time + dst_trans_off - posix.std_offset;
  379|  52.2k|    std.unix_time = jan1_time + std_trans_off - posix.dst_offset;
  380|  52.2k|    const auto* ta = dst.unix_time < std.unix_time ? &dst : &std;
  ------------------
  |  Branch (380:22): [True: 52.2k, False: 0]
  ------------------
  381|  52.2k|    const auto* tb = dst.unix_time < std.unix_time ? &std : &dst;
  ------------------
  |  Branch (381:22): [True: 52.2k, False: 0]
  ------------------
  382|  52.2k|    if (last_time < tb->unix_time) {
  ------------------
  |  Branch (382:9): [True: 52.1k, False: 130]
  ------------------
  383|  52.1k|      if (last_time < ta->unix_time) transitions_.push_back(*ta);
  ------------------
  |  Branch (383:11): [True: 52.1k, False: 0]
  ------------------
  384|  52.1k|      transitions_.push_back(*tb);
  385|  52.1k|    }
  386|  52.2k|    if (last_year_ == limit) break;
  ------------------
  |  Branch (386:9): [True: 130, False: 52.1k]
  ------------------
  387|  52.1k|    jan1_time += kSecsPerYear[leap_year];
  388|  52.1k|    jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;
  389|  52.1k|    leap_year = !leap_year && IsLeap(last_year_ + 1);
  ------------------
  |  Branch (389:17): [True: 39.5k, False: 12.6k]
  |  Branch (389:31): [True: 12.6k, False: 26.9k]
  ------------------
  390|  52.1k|  }
  391|       |
  392|    130|  return true;
  393|    130|}
_ZN4cctz12TimeZoneInfo17ResetToBuiltinUTCERKNSt3__16chrono8durationIlNS1_5ratioILl1ELl1EEEEE:
  670|    334|bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
  671|    334|  transition_types_.resize(1);
  672|    334|  TransitionType& tt(transition_types_.back());
  673|    334|  tt.utc_offset = static_cast<std::int_least32_t>(offset.count());
  674|    334|  tt.is_dst = false;
  675|    334|  tt.abbr_index = 0;
  676|       |
  677|       |  // We temporarily add some redundant, contemporary (2015 through 2025)
  678|       |  // transitions for performance reasons.  See TimeZoneInfo::LocalTime().
  679|       |  // TODO: Fix the performance issue and remove the extra transitions.
  680|    334|  transitions_.clear();
  681|    334|  transitions_.reserve(12);
  682|    334|  for (const std::int_fast64_t unix_time : {
  ------------------
  |  Branch (682:42): [True: 4.00k, False: 334]
  ------------------
  683|    334|           -(1LL << 59),  // a "first half" transition
  684|    334|           1420070400LL,  // 2015-01-01T00:00:00+00:00
  685|    334|           1451606400LL,  // 2016-01-01T00:00:00+00:00
  686|    334|           1483228800LL,  // 2017-01-01T00:00:00+00:00
  687|    334|           1514764800LL,  // 2018-01-01T00:00:00+00:00
  688|    334|           1546300800LL,  // 2019-01-01T00:00:00+00:00
  689|    334|           1577836800LL,  // 2020-01-01T00:00:00+00:00
  690|    334|           1609459200LL,  // 2021-01-01T00:00:00+00:00
  691|    334|           1640995200LL,  // 2022-01-01T00:00:00+00:00
  692|    334|           1672531200LL,  // 2023-01-01T00:00:00+00:00
  693|    334|           1704067200LL,  // 2024-01-01T00:00:00+00:00
  694|    334|           1735689600LL,  // 2025-01-01T00:00:00+00:00
  695|  4.00k|       }) {
  696|  4.00k|    Transition& tr(*transitions_.emplace(transitions_.end()));
  697|  4.00k|    tr.unix_time = unix_time;
  698|  4.00k|    tr.type_index = 0;
  699|  4.00k|    tr.civil_sec = LocalTime(tr.unix_time, tt).cs;
  700|  4.00k|    tr.prev_civil_sec = tr.civil_sec - 1;
  701|  4.00k|  }
  702|       |
  703|    334|  default_transition_type_ = 0;
  704|    334|  abbreviations_ = FixedOffsetToAbbr(offset);
  705|    334|  abbreviations_.append(1, '\0');
  706|    334|  future_spec_.clear();  // never needed for a fixed-offset zone
  707|    334|  extended_ = false;
  708|       |
  709|    334|  tt.civil_max = LocalTime(seconds::max().count(), tt).cs;
  710|    334|  tt.civil_min = LocalTime(seconds::min().count(), tt).cs;
  711|       |
  712|    334|  transitions_.shrink_to_fit();
  713|    334|  return true;
  714|    334|}
_ZN4cctz12TimeZoneInfo4LoadEPNS_14ZoneInfoSourceE:
  716|    248|bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
  717|       |  // Read and validate the header.
  718|    248|  tzhead tzh;
  719|    248|  if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh))
  ------------------
  |  Branch (719:7): [True: 0, False: 248]
  ------------------
  720|      0|    return false;
  721|    248|  if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
  ------------------
  |  |   27|    248|#define TZ_MAGIC "TZif"
  ------------------
  |  Branch (721:7): [True: 1, False: 247]
  ------------------
  722|      1|    return false;
  723|    247|  Header hdr;
  724|    247|  if (!hdr.Build(tzh))
  ------------------
  |  Branch (724:7): [True: 0, False: 247]
  ------------------
  725|      0|    return false;
  726|    247|  std::size_t time_len = 4;
  727|    247|  if (tzh.tzh_version[0] != '\0') {
  ------------------
  |  Branch (727:7): [True: 247, False: 0]
  ------------------
  728|       |    // Skip the 4-byte data.
  729|    247|    if (zip->Skip(hdr.DataLength(time_len)) != 0)
  ------------------
  |  Branch (729:9): [True: 0, False: 247]
  ------------------
  730|      0|      return false;
  731|       |    // Read and validate the header for the 8-byte data.
  732|    247|    if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh))
  ------------------
  |  Branch (732:9): [True: 0, False: 247]
  ------------------
  733|      0|      return false;
  734|    247|    if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
  ------------------
  |  |   27|    247|#define TZ_MAGIC "TZif"
  ------------------
  |  Branch (734:9): [True: 0, False: 247]
  ------------------
  735|      0|      return false;
  736|    247|    if (tzh.tzh_version[0] == '\0')
  ------------------
  |  Branch (736:9): [True: 0, False: 247]
  ------------------
  737|      0|      return false;
  738|    247|    if (!hdr.Build(tzh))
  ------------------
  |  Branch (738:9): [True: 0, False: 247]
  ------------------
  739|      0|      return false;
  740|    247|    time_len = 8;
  741|    247|  }
  742|    247|  if (hdr.typecnt == 0)
  ------------------
  |  Branch (742:7): [True: 0, False: 247]
  ------------------
  743|      0|    return false;
  744|    247|  if (hdr.leapcnt != 0) {
  ------------------
  |  Branch (744:7): [True: 0, False: 247]
  ------------------
  745|       |    // This code assumes 60-second minutes so we do not want
  746|       |    // the leap-second encoded zoneinfo. We could reverse the
  747|       |    // compensation, but the "right" encoding is rarely used
  748|       |    // so currently we simply reject such data.
  749|      0|    return false;
  750|      0|  }
  751|    247|  if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt)
  ------------------
  |  Branch (751:7): [True: 135, False: 112]
  |  Branch (751:30): [True: 0, False: 135]
  ------------------
  752|      0|    return false;
  753|    247|  if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt)
  ------------------
  |  Branch (753:7): [True: 83, False: 164]
  |  Branch (753:29): [True: 0, False: 83]
  ------------------
  754|      0|    return false;
  755|       |
  756|       |  // Bound the header counts before sizing tbuf so that a hostile TZif blob
  757|       |  // cannot force a very large zero-filled allocation from a tiny input.
  758|    247|  if (hdr.timecnt > TZ_MAX_TIMES)
  ------------------
  |  |   94|    247|# define TZ_MAX_TIMES 2000
  ------------------
  |  Branch (758:7): [True: 0, False: 247]
  ------------------
  759|      0|    return false;
  760|    247|  if (hdr.typecnt > TZ_MAX_TYPES)
  ------------------
  |  |   99|    247|# define TZ_MAX_TYPES 256 /* Limited to 256 by Internet RFC 9636.  */
  ------------------
  |  Branch (760:7): [True: 0, False: 247]
  ------------------
  761|      0|    return false;
  762|    247|  if (hdr.charcnt > TZ_MAX_CHARS)
  ------------------
  |  |  104|    247|# define TZ_MAX_CHARS 256	/* Maximum number of abbreviation characters */
  ------------------
  |  Branch (762:7): [True: 0, False: 247]
  ------------------
  763|      0|    return false;
  764|       |
  765|       |  // Read the data into a local buffer.
  766|    247|  std::size_t len = hdr.DataLength(time_len);
  767|    247|  std::vector<char> tbuf(len);
  768|    247|  if (zip->Read(tbuf.data(), len) != len)
  ------------------
  |  Branch (768:7): [True: 0, False: 247]
  ------------------
  769|      0|    return false;
  770|    247|  const char* bp = tbuf.data();
  771|       |
  772|       |  // Decode and validate the transitions.
  773|    247|  transitions_.reserve(hdr.timecnt + 2);
  774|    247|  transitions_.resize(hdr.timecnt);
  775|  17.1k|  for (std::size_t i = 0; i != hdr.timecnt; ++i) {
  ------------------
  |  Branch (775:27): [True: 16.9k, False: 247]
  ------------------
  776|  16.9k|    transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp);
  ------------------
  |  Branch (776:33): [True: 0, False: 16.9k]
  ------------------
  777|  16.9k|    bp += time_len;
  778|       |    // A valid zoneinfo file keeps transition times far from the int64 limits.
  779|       |    // A hostile one can place them at the extremes, where the reverse-conversion
  780|       |    // arithmetic in MakeTime() (tr.unix_time +/- a sub-day civil delta, see
  781|       |    // MakeSkipped()/MakeRepeated()) overflows. Bound them to +/-(1<<59), the
  782|       |    // times used by the no-op transitions added below.
  783|  16.9k|    if (transitions_[i].unix_time < -(1LL << 59) ||
  ------------------
  |  Branch (783:9): [True: 0, False: 16.9k]
  ------------------
  784|  16.9k|        transitions_[i].unix_time > (1LL << 59))
  ------------------
  |  Branch (784:9): [True: 0, False: 16.9k]
  ------------------
  785|      0|      return false;  // out of range
  786|  16.9k|  }
  787|    247|  bool seen_type_0 = false;
  788|  17.1k|  for (std::size_t i = 0; i != hdr.timecnt; ++i) {
  ------------------
  |  Branch (788:27): [True: 16.9k, False: 247]
  ------------------
  789|  16.9k|    transitions_[i].type_index = Decode8(bp++);
  790|  16.9k|    if (transitions_[i].type_index >= hdr.typecnt)
  ------------------
  |  Branch (790:9): [True: 0, False: 16.9k]
  ------------------
  791|      0|      return false;
  792|  16.9k|    if (transitions_[i].type_index == 0)
  ------------------
  |  Branch (792:9): [True: 5.14k, False: 11.7k]
  ------------------
  793|  5.14k|      seen_type_0 = true;
  794|  16.9k|  }
  795|       |
  796|       |  // Decode and validate the transition types.
  797|    247|  transition_types_.reserve(hdr.typecnt + 2);
  798|    247|  transition_types_.resize(hdr.typecnt);
  799|    947|  for (std::size_t i = 0; i != hdr.typecnt; ++i) {
  ------------------
  |  Branch (799:27): [True: 700, False: 247]
  ------------------
  800|    700|    transition_types_[i].utc_offset =
  801|    700|        static_cast<std::int_least32_t>(Decode32(bp));
  802|    700|    if (transition_types_[i].utc_offset >= kSecsPerDay ||
  ------------------
  |  Branch (802:9): [True: 0, False: 700]
  ------------------
  803|    700|        transition_types_[i].utc_offset <= -kSecsPerDay)
  ------------------
  |  Branch (803:9): [True: 0, False: 700]
  ------------------
  804|      0|      return false;
  805|    700|    bp += 4;
  806|    700|    transition_types_[i].is_dst = (Decode8(bp++) != 0);
  807|    700|    transition_types_[i].abbr_index = Decode8(bp++);
  808|    700|    if (transition_types_[i].abbr_index >= hdr.charcnt)
  ------------------
  |  Branch (808:9): [True: 0, False: 700]
  ------------------
  809|      0|      return false;
  810|    700|  }
  811|       |
  812|       |  // Determine the before-first-transition type.
  813|    247|  default_transition_type_ = 0;
  814|    247|  if (seen_type_0 && hdr.timecnt != 0) {
  ------------------
  |  Branch (814:7): [True: 130, False: 117]
  |  Branch (814:22): [True: 130, False: 0]
  ------------------
  815|    130|    std::size_t index = 0;
  816|    130|    if (transition_types_[0].is_dst) {
  ------------------
  |  Branch (816:9): [True: 0, False: 130]
  ------------------
  817|      0|      index = transitions_[0].type_index;
  818|      0|      while (index != 0 && transition_types_[index].is_dst)
  ------------------
  |  Branch (818:14): [True: 0, False: 0]
  |  Branch (818:28): [True: 0, False: 0]
  ------------------
  819|      0|        --index;
  820|      0|    }
  821|    130|    while (index != hdr.typecnt && transition_types_[index].is_dst)
  ------------------
  |  Branch (821:12): [True: 130, False: 0]
  |  Branch (821:36): [True: 0, False: 130]
  ------------------
  822|      0|      ++index;
  823|    130|    if (index != hdr.typecnt)
  ------------------
  |  Branch (823:9): [True: 130, False: 0]
  ------------------
  824|    130|      default_transition_type_ = static_cast<std::uint_fast8_t>(index);
  825|    130|  }
  826|       |
  827|       |  // Copy all the abbreviations. The area holds NUL-terminated strings, and
  828|       |  // LocalTime() hands out a pointer into it, so the final abbreviation has
  829|       |  // to be terminated within the area itself. Otherwise an abbreviation runs
  830|       |  // on into whatever ExtendTransitions() later appends. (hdr.charcnt != 0
  831|       |  // because every abbr_index was validated to be less than it.)
  832|    247|  if (bp[hdr.charcnt - 1] != '\0')
  ------------------
  |  Branch (832:7): [True: 0, False: 247]
  ------------------
  833|      0|    return false;
  834|    247|  abbreviations_.reserve(hdr.charcnt + 10);
  835|    247|  abbreviations_.assign(bp, hdr.charcnt);
  836|    247|  bp += hdr.charcnt;
  837|       |
  838|       |  // Skip the unused portions. We've already dispensed with leap-second
  839|       |  // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when
  840|       |  // interpreting a POSIX spec that does not include start/end rules, and
  841|       |  // that isn't the case here (see "zic -p").
  842|    247|  bp += (time_len + 4) * hdr.leapcnt;  // leap-time + TAI-UTC
  843|    247|  bp += 1 * hdr.ttisstdcnt;            // UTC/local indicators
  844|    247|  bp += 1 * hdr.ttisutcnt;             // standard/wall indicators
  845|    247|  assert(bp == tbuf.data() + tbuf.size());
  ------------------
  |  Branch (845:3): [True: 247, False: 0]
  ------------------
  846|       |
  847|    247|  future_spec_.clear();
  848|    247|  if (tzh.tzh_version[0] != '\0') {
  ------------------
  |  Branch (848:7): [True: 247, False: 0]
  ------------------
  849|       |    // Snarf up the NL-enclosed future POSIX spec. Note
  850|       |    // that version '3' files utilize an extended format.
  851|    247|    auto get_char = [](ZoneInfoSource* azip) -> int {
  852|    247|      unsigned char ch;  // all non-EOF results are positive
  853|    247|      return (azip->Read(&ch, 1) == 1) ? ch : EOF;
  854|    247|    };
  855|    247|    if (get_char(zip) != '\n')
  ------------------
  |  Branch (855:9): [True: 0, False: 247]
  ------------------
  856|      0|      return false;
  857|  4.08k|    for (int c = get_char(zip); c != '\n'; c = get_char(zip)) {
  ------------------
  |  Branch (857:33): [True: 3.83k, False: 247]
  ------------------
  858|  3.83k|      if (c == EOF)
  ------------------
  |  Branch (858:11): [True: 0, False: 3.83k]
  ------------------
  859|      0|        return false;
  860|  3.83k|      future_spec_.push_back(static_cast<char>(c));
  861|  3.83k|    }
  862|    247|  }
  863|       |
  864|       |  // We don't check for EOF so that we're forwards compatible.
  865|       |
  866|       |  // If we did not find version information during the standard loading
  867|       |  // process (as of tzh_version '3' that is unsupported), then ask the
  868|       |  // ZoneInfoSource for any out-of-bound version string it may be privy to.
  869|    247|  if (version_.empty()) {
  ------------------
  |  Branch (869:7): [True: 247, False: 0]
  ------------------
  870|    247|    version_ = zip->Version();
  871|    247|  }
  872|       |
  873|       |  // Ensure that there is always a transition in the first half of the
  874|       |  // time line (the second half is handled below) so that the signed
  875|       |  // difference between a civil_second and the civil_second of its
  876|       |  // previous transition is always representable, without overflow.
  877|    247|  if (transitions_.empty() || transitions_.front().unix_time >= 0) {
  ------------------
  |  Branch (877:7): [True: 112, False: 135]
  |  Branch (877:31): [True: 80, False: 55]
  ------------------
  878|    192|    Transition& tr(*transitions_.emplace(transitions_.begin()));
  879|    192|    tr.unix_time = -(1LL << 59);  // -18267312070-10-26T17:01:52+00:00
  880|    192|    tr.type_index = default_transition_type_;
  881|    192|  }
  882|       |
  883|       |  // Extend the transitions using the future specification.
  884|    247|  if (!ExtendTransitions()) return false;
  ------------------
  |  Branch (884:7): [True: 0, False: 247]
  ------------------
  885|       |
  886|       |  // Ensure that there is always a transition in the second half of the
  887|       |  // time line (the first half is handled above) so that the signed
  888|       |  // difference between a civil_second and the civil_second of its
  889|       |  // previous transition is always representable, without overflow.
  890|    247|  const Transition& last(transitions_.back());
  891|    247|  if (last.unix_time < 0) {
  ------------------
  |  Branch (891:7): [True: 112, False: 135]
  ------------------
  892|    112|    assert(!extended_);
  ------------------
  |  Branch (892:5): [True: 112, False: 0]
  ------------------
  893|    112|    const std::uint_fast8_t type_index = last.type_index;
  894|    112|    Transition& tr(*transitions_.emplace(transitions_.end()));
  895|    112|    tr.unix_time = 2147483647;  // 2038-01-19T03:14:07+00:00
  896|    112|    tr.type_index = type_index;
  897|    112|  }
  898|       |
  899|       |  // Compute the local civil time for each transition and the preceding
  900|       |  // second. These will be used for reverse conversions in MakeTime().
  901|    247|  const TransitionType* ttp = &transition_types_[default_transition_type_];
  902|   121k|  for (std::size_t i = 0; i != transitions_.size(); ++i) {
  ------------------
  |  Branch (902:27): [True: 121k, False: 247]
  ------------------
  903|   121k|    Transition& tr(transitions_[i]);
  904|   121k|    tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1;
  905|   121k|    ttp = &transition_types_[tr.type_index];
  906|   121k|    tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs;
  907|   121k|    if (i != 0) {
  ------------------
  |  Branch (907:9): [True: 121k, False: 247]
  ------------------
  908|       |      // Check that offset changes don't cross each other. No one
  909|       |      // does this in practice, and we depend on increasing absolute
  910|       |      // and civil times in BreakTime() and MakeTime() respectively.
  911|   121k|      if (!Transition::ByUnixTime()(transitions_[i - 1], tr) ||
  ------------------
  |  Branch (911:11): [True: 0, False: 121k]
  |  Branch (911:11): [True: 0, False: 121k]
  ------------------
  912|   121k|          !Transition::ByCivilTime()(transitions_[i - 1], tr)) {
  ------------------
  |  Branch (912:11): [True: 0, False: 121k]
  ------------------
  913|      0|        return false;  // out of order
  914|      0|      }
  915|   121k|    }
  916|   121k|  }
  917|       |
  918|       |  // Compute the maximum/minimum civil times that can be converted to a
  919|       |  // time_point<seconds> for each of the zone's transition types.
  920|    700|  for (auto& tt : transition_types_) {
  ------------------
  |  Branch (920:17): [True: 700, False: 247]
  ------------------
  921|    700|    tt.civil_max = LocalTime(seconds::max().count(), tt).cs;
  922|    700|    tt.civil_min = LocalTime(seconds::min().count(), tt).cs;
  923|    700|  }
  924|       |
  925|    247|  transitions_.shrink_to_fit();
  926|    247|  return true;
  927|    247|}
_ZN4cctz12TimeZoneInfo4LoadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  929|  1.29k|bool TimeZoneInfo::Load(const std::string& name) {
  930|       |  // We can ensure that the loading of UTC or any other fixed-offset
  931|       |  // zone never fails because the simple, fixed-offset state can be
  932|       |  // internally generated. Note that this depends on our choice to not
  933|       |  // accept leap-second encoded ("right") zoneinfo.
  934|  1.29k|  auto offset = seconds::zero();
  935|  1.29k|  if (FixedOffsetFromName(name, &offset)) {
  ------------------
  |  Branch (935:7): [True: 333, False: 958]
  ------------------
  936|    333|    return ResetToBuiltinUTC(offset);
  937|    333|  }
  938|       |
  939|       |  // Find and use a ZoneInfoSource to load the named zone.
  940|    958|  auto zip = cctz_extension::zone_info_source_factory(
  941|    958|      name, [](const std::string& n) -> std::unique_ptr<ZoneInfoSource> {
  942|    958|        if (auto z = FileZoneInfoSource::Open(n)) return z;
  943|    958|        if (auto z = AndroidZoneInfoSource::Open(n)) return z;
  944|    958|        if (auto z = FuchsiaZoneInfoSource::Open(n)) return z;
  945|    958|        return nullptr;
  946|    958|      });
  947|    958|  return zip != nullptr && Load(zip.get());
  ------------------
  |  Branch (947:10): [True: 248, False: 710]
  |  Branch (947:28): [True: 247, False: 1]
  ------------------
  948|  1.29k|}
_ZN4cctz12TimeZoneInfo3UTCEv:
  950|      1|std::unique_ptr<TimeZoneInfo> TimeZoneInfo::UTC() {
  951|      1|  auto tz = std::unique_ptr<TimeZoneInfo>(new TimeZoneInfo);
  952|      1|  tz->ResetToBuiltinUTC(seconds::zero());
  953|      1|  return tz;
  954|      1|}
_ZN4cctz12TimeZoneInfo4MakeERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  956|  1.29k|std::unique_ptr<TimeZoneInfo> TimeZoneInfo::Make(const std::string& name) {
  957|  1.29k|  auto tz = std::unique_ptr<TimeZoneInfo>(new TimeZoneInfo);
  958|  1.29k|  if (!tz->Load(name)) tz.reset();  // fallback to UTC
  ------------------
  |  Branch (958:7): [True: 711, False: 580]
  ------------------
  959|  1.29k|  return tz;
  960|  1.29k|}
_ZNK4cctz12TimeZoneInfo9LocalTimeElRKNS_14TransitionTypeE:
  964|   250k|    std::int_fast64_t unix_time, const TransitionType& tt) const {
  965|       |  // A civil time in "+offset" looks like (time+offset) in UTC.
  966|       |  // Note: We perform two additions in the civil_second domain to
  967|       |  // sidestep the chance of overflow in (unix_time + tt.utc_offset).
  968|   250k|  return {(civil_second() + unix_time) + tt.utc_offset,
  969|   250k|          tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
  970|   250k|}
_ZNK4cctz12TimeZoneInfo9LocalTimeElRKNS_10TransitionE:
  974|  6.95k|    std::int_fast64_t unix_time, const Transition& tr) const {
  975|  6.95k|  const TransitionType& tt = transition_types_[tr.type_index];
  976|       |  // Note: (unix_time - tr.unix_time) will never overflow as we
  977|       |  // have ensured that there is always a "nearby" transition.
  978|  6.95k|  return {tr.civil_sec + (unix_time - tr.unix_time),  // TODO: Optimize.
  979|  6.95k|          tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
  980|  6.95k|}
_ZNK4cctz12TimeZoneInfo9TimeLocalERKNS_6detail10civil_timeINS1_10second_tagEEEl:
  984|  1.67k|                                                year_t c4_shift) const {
  985|  1.67k|  assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_);
  ------------------
  |  Branch (985:3): [True: 1.67k, False: 0]
  |  Branch (985:3): [True: 1.67k, False: 0]
  |  Branch (985:3): [True: 1.67k, False: 0]
  ------------------
  986|  1.67k|  time_zone::civil_lookup cl = MakeTime(cs);
  987|  1.67k|  if (c4_shift > seconds::max().count() / kSecsPer400Years) {
  ------------------
  |  Branch (987:7): [True: 149, False: 1.52k]
  ------------------
  988|    149|    cl.pre = cl.trans = cl.post = time_point<seconds>::max();
  989|  1.52k|  } else {
  990|  1.52k|    const auto offset = seconds(c4_shift * kSecsPer400Years);
  991|  1.52k|    const auto limit = time_point<seconds>::max() - offset;
  992|  4.56k|    for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) {
  ------------------
  |  Branch (992:19): [True: 4.56k, False: 1.52k]
  ------------------
  993|  4.56k|      if (*tp > limit) {
  ------------------
  |  Branch (993:11): [True: 30, False: 4.53k]
  ------------------
  994|     30|        *tp = time_point<seconds>::max();
  995|  4.53k|      } else {
  996|  4.53k|        *tp += offset;
  997|  4.53k|      }
  998|  4.56k|    }
  999|  1.52k|  }
 1000|  1.67k|  return cl;
 1001|  1.67k|}
_ZNK4cctz12TimeZoneInfo9BreakTimeERKNSt3__16chrono10time_pointINS2_12system_clockENS2_8durationIlNS1_5ratioILl1ELl1EEEEEEE:
 1004|  9.77k|    const time_point<seconds>& tp) const {
 1005|  9.77k|  std::int_fast64_t unix_time = ToUnixSeconds(tp);
 1006|  9.77k|  const std::size_t timecnt = transitions_.size();
 1007|  9.77k|  assert(timecnt != 0);  // We always add a transition.
  ------------------
  |  Branch (1007:3): [True: 9.77k, False: 0]
  ------------------
 1008|       |
 1009|  9.77k|  if (unix_time < transitions_[0].unix_time) {
  ------------------
  |  Branch (1009:7): [True: 1.32k, False: 8.44k]
  ------------------
 1010|  1.32k|    return LocalTime(unix_time, transition_types_[default_transition_type_]);
 1011|  1.32k|  }
 1012|  8.44k|  if (unix_time >= transitions_[timecnt - 1].unix_time) {
  ------------------
  |  Branch (1012:7): [True: 2.75k, False: 5.68k]
  ------------------
 1013|       |    // After the last transition. If we extended the transitions using
 1014|       |    // future_spec_, shift back to a supported year using the 400-year
 1015|       |    // cycle of calendaric equivalence and then compensate accordingly.
 1016|  2.75k|    if (extended_) {
  ------------------
  |  Branch (1016:9): [True: 1.49k, False: 1.26k]
  ------------------
 1017|  1.49k|      const std::int_fast64_t diff =
 1018|  1.49k|          unix_time - transitions_[timecnt - 1].unix_time;
 1019|  1.49k|      const year_t shift = diff / kSecsPer400Years + 1;
 1020|  1.49k|      const auto d = seconds(shift * kSecsPer400Years);
 1021|  1.49k|      time_zone::absolute_lookup al = BreakTime(tp - d);
 1022|  1.49k|      al.cs = YearShift(al.cs, shift * 400);
 1023|  1.49k|      return al;
 1024|  1.49k|    }
 1025|  1.26k|    return LocalTime(unix_time, transitions_[timecnt - 1]);
 1026|  2.75k|  }
 1027|       |
 1028|  5.68k|  const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed);
 1029|  5.68k|  if (0 < hint && hint < timecnt) {
  ------------------
  |  Branch (1029:7): [True: 5.36k, False: 319]
  |  Branch (1029:19): [True: 5.36k, False: 0]
  ------------------
 1030|  5.36k|    if (transitions_[hint - 1].unix_time <= unix_time) {
  ------------------
  |  Branch (1030:9): [True: 4.41k, False: 946]
  ------------------
 1031|  4.41k|      if (unix_time < transitions_[hint].unix_time) {
  ------------------
  |  Branch (1031:11): [True: 3.46k, False: 952]
  ------------------
 1032|  3.46k|        return LocalTime(unix_time, transitions_[hint - 1]);
 1033|  3.46k|      }
 1034|  4.41k|    }
 1035|  5.36k|  }
 1036|       |
 1037|  2.21k|  const Transition target = {unix_time, 0, civil_second(), civil_second()};
 1038|  2.21k|  const Transition* begin = &transitions_[0];
 1039|  2.21k|  const Transition* tr = std::upper_bound(begin, begin + timecnt, target,
 1040|  2.21k|                                          Transition::ByUnixTime());
 1041|  2.21k|  local_time_hint_.store(static_cast<std::size_t>(tr - begin),
 1042|  2.21k|                         std::memory_order_relaxed);
 1043|  2.21k|  return LocalTime(unix_time, *--tr);
 1044|  5.68k|}
_ZNK4cctz12TimeZoneInfo8MakeTimeERKNS_6detail10civil_timeINS1_10second_tagEEE:
 1046|  14.6k|time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const {
 1047|  14.6k|  const std::size_t timecnt = transitions_.size();
 1048|  14.6k|  assert(timecnt != 0);  // We always add a transition.
  ------------------
  |  Branch (1048:3): [True: 14.6k, False: 0]
  ------------------
 1049|       |
 1050|       |  // Find the first transition after our target civil time.
 1051|  14.6k|  const Transition* tr = nullptr;
 1052|  14.6k|  const Transition* begin = &transitions_[0];
 1053|  14.6k|  const Transition* end = begin + timecnt;
 1054|  14.6k|  if (cs < begin->civil_sec) {
  ------------------
  |  Branch (1054:7): [True: 1.61k, False: 13.0k]
  ------------------
 1055|  1.61k|    tr = begin;
 1056|  13.0k|  } else if (cs >= transitions_[timecnt - 1].civil_sec) {
  ------------------
  |  Branch (1056:14): [True: 3.07k, False: 9.96k]
  ------------------
 1057|  3.07k|    tr = end;
 1058|  9.96k|  } else {
 1059|  9.96k|    const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed);
 1060|  9.96k|    if (0 < hint && hint < timecnt) {
  ------------------
  |  Branch (1060:9): [True: 9.39k, False: 565]
  |  Branch (1060:21): [True: 9.39k, False: 0]
  ------------------
 1061|  9.39k|      if (transitions_[hint - 1].civil_sec <= cs) {
  ------------------
  |  Branch (1061:11): [True: 7.68k, False: 1.71k]
  ------------------
 1062|  7.68k|        if (cs < transitions_[hint].civil_sec) {
  ------------------
  |  Branch (1062:13): [True: 5.98k, False: 1.70k]
  ------------------
 1063|  5.98k|          tr = begin + hint;
 1064|  5.98k|        }
 1065|  7.68k|      }
 1066|  9.39k|    }
 1067|  9.96k|    if (tr == nullptr) {
  ------------------
  |  Branch (1067:9): [True: 3.98k, False: 5.98k]
  ------------------
 1068|  3.98k|      const Transition target = {0, 0, cs, civil_second()};
 1069|  3.98k|      tr = std::upper_bound(begin, end, target, Transition::ByCivilTime());
 1070|  3.98k|      time_local_hint_.store(static_cast<std::size_t>(tr - begin),
 1071|  3.98k|                             std::memory_order_relaxed);
 1072|  3.98k|    }
 1073|  9.96k|  }
 1074|       |
 1075|  14.6k|  if (tr == begin) {
  ------------------
  |  Branch (1075:7): [True: 1.61k, False: 13.0k]
  ------------------
 1076|  1.61k|    if (tr->prev_civil_sec >= cs) {
  ------------------
  |  Branch (1076:9): [True: 1.60k, False: 1]
  ------------------
 1077|       |      // Before first transition, so use the default offset.
 1078|  1.60k|      const TransitionType& tt(transition_types_[default_transition_type_]);
 1079|  1.60k|      if (cs < tt.civil_min) return MakeUnique(time_point<seconds>::min());
  ------------------
  |  Branch (1079:11): [True: 159, False: 1.45k]
  ------------------
 1080|  1.45k|      return MakeUnique(cs - (civil_second() + tt.utc_offset));
 1081|  1.60k|    }
 1082|       |    // tr->prev_civil_sec < cs < tr->civil_sec
 1083|      1|    return MakeSkipped(*tr, cs);
 1084|  1.61k|  }
 1085|       |
 1086|  13.0k|  if (tr == end) {
  ------------------
  |  Branch (1086:7): [True: 3.07k, False: 9.96k]
  ------------------
 1087|  3.07k|    if (cs > (--tr)->prev_civil_sec) {
  ------------------
  |  Branch (1087:9): [True: 3.06k, False: 6]
  ------------------
 1088|       |      // After the last transition. If we extended the transitions using
 1089|       |      // future_spec_, shift back to a supported year using the 400-year
 1090|       |      // cycle of calendaric equivalence and then compensate accordingly.
 1091|  3.06k|      if (extended_ && cs.year() > last_year_) {
  ------------------
  |  Branch (1091:11): [True: 1.68k, False: 1.38k]
  |  Branch (1091:24): [True: 1.67k, False: 16]
  ------------------
 1092|  1.67k|        const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1;
 1093|  1.67k|        return TimeLocal(YearShift(cs, shift * -400), shift);
 1094|  1.67k|      }
 1095|  1.39k|      const TransitionType& tt(transition_types_[tr->type_index]);
 1096|  1.39k|      if (cs > tt.civil_max) return MakeUnique(time_point<seconds>::max());
  ------------------
  |  Branch (1096:11): [True: 69, False: 1.32k]
  ------------------
 1097|  1.32k|      return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
 1098|  1.39k|    }
 1099|       |    // tr->civil_sec <= cs <= tr->prev_civil_sec
 1100|      6|    return MakeRepeated(*tr, cs);
 1101|  3.07k|  }
 1102|       |
 1103|  9.96k|  if (tr->prev_civil_sec < cs) {
  ------------------
  |  Branch (1103:7): [True: 10, False: 9.95k]
  ------------------
 1104|       |    // tr->prev_civil_sec < cs < tr->civil_sec
 1105|     10|    return MakeSkipped(*tr, cs);
 1106|     10|  }
 1107|       |
 1108|  9.95k|  if (cs <= (--tr)->prev_civil_sec) {
  ------------------
  |  Branch (1108:7): [True: 27, False: 9.92k]
  ------------------
 1109|       |    // tr->civil_sec <= cs <= tr->prev_civil_sec
 1110|     27|    return MakeRepeated(*tr, cs);
 1111|     27|  }
 1112|       |
 1113|       |  // In between transitions.
 1114|  9.92k|  return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
 1115|  9.95k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_110AllYearDSTERKNS_13PosixTimeZoneE:
  189|    130|bool AllYearDST(const PosixTimeZone& posix) {
  190|    130|  if (posix.dst_start.date.fmt != PosixTransition::N) return false;
  ------------------
  |  Branch (190:7): [True: 130, False: 0]
  ------------------
  191|      0|  if (posix.dst_start.date.n.day != 0) return false;
  ------------------
  |  Branch (191:7): [True: 0, False: 0]
  ------------------
  192|      0|  if (posix.dst_start.time.offset != 0) return false;
  ------------------
  |  Branch (192:7): [True: 0, False: 0]
  ------------------
  193|       |
  194|      0|  if (posix.dst_end.date.fmt != PosixTransition::J) return false;
  ------------------
  |  Branch (194:7): [True: 0, False: 0]
  ------------------
  195|      0|  if (posix.dst_end.date.j.day != kDaysPerYear[0]) return false;
  ------------------
  |  Branch (195:7): [True: 0, False: 0]
  ------------------
  196|      0|  const auto offset = posix.std_offset - posix.dst_offset;
  197|      0|  if (posix.dst_end.time.offset + offset != kSecsPerDay) return false;
  ------------------
  |  Branch (197:7): [True: 0, False: 0]
  ------------------
  198|       |
  199|      0|  return true;
  200|      0|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_16IsLeapEl:
   68|  39.6k|inline bool IsLeap(year_t year) {
   69|  39.6k|  return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
  ------------------
  |  Branch (69:10): [True: 13.0k, False: 26.6k]
  |  Branch (69:30): [True: 12.4k, False: 520]
  |  Branch (69:51): [True: 130, False: 390]
  ------------------
   70|  39.6k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_114ToPosixWeekdayENS_6detail7weekdayE:
   95|    130|inline int ToPosixWeekday(weekday wd) {
   96|    130|  switch (wd) {
  ------------------
  |  Branch (96:11): [True: 130, False: 0]
  ------------------
   97|      0|    case weekday::sunday:
  ------------------
  |  Branch (97:5): [True: 0, False: 130]
  ------------------
   98|      0|      return 0;
   99|      0|    case weekday::monday:
  ------------------
  |  Branch (99:5): [True: 0, False: 130]
  ------------------
  100|      0|      return 1;
  101|      0|    case weekday::tuesday:
  ------------------
  |  Branch (101:5): [True: 0, False: 130]
  ------------------
  102|      0|      return 2;
  103|      0|    case weekday::wednesday:
  ------------------
  |  Branch (103:5): [True: 0, False: 130]
  ------------------
  104|      0|      return 3;
  105|    130|    case weekday::thursday:
  ------------------
  |  Branch (105:5): [True: 130, False: 0]
  ------------------
  106|    130|      return 4;
  107|      0|    case weekday::friday:
  ------------------
  |  Branch (107:5): [True: 0, False: 130]
  ------------------
  108|      0|      return 5;
  109|      0|    case weekday::saturday:
  ------------------
  |  Branch (109:5): [True: 0, False: 130]
  ------------------
  110|      0|      return 6;
  111|    130|  }
  112|      0|  return 0; /*NOTREACHED*/
  113|    130|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_111TransOffsetEbiRKNS_15PosixTransitionE:
  204|   104k|                              const PosixTransition& pt) {
  205|   104k|  std::int_fast64_t days = 0;
  206|   104k|  switch (pt.date.fmt) {
  ------------------
  |  Branch (206:11): [True: 104k, False: 0]
  ------------------
  207|      0|    case PosixTransition::J: {
  ------------------
  |  Branch (207:5): [True: 0, False: 104k]
  ------------------
  208|      0|      days = pt.date.j.day;
  209|      0|      if (!leap_year || days < kMonthOffsets[1][3]) days -= 1;
  ------------------
  |  Branch (209:11): [True: 0, False: 0]
  |  Branch (209:25): [True: 0, False: 0]
  ------------------
  210|      0|      break;
  211|      0|    }
  212|      0|    case PosixTransition::N: {
  ------------------
  |  Branch (212:5): [True: 0, False: 104k]
  ------------------
  213|      0|      days = pt.date.n.day;
  214|      0|      break;
  215|      0|    }
  216|   104k|    case PosixTransition::M: {
  ------------------
  |  Branch (216:5): [True: 104k, False: 0]
  ------------------
  217|   104k|      const bool last_week = (pt.date.m.week == 5);
  218|   104k|      days = kMonthOffsets[leap_year][pt.date.m.month + last_week];
  219|   104k|      const std::int_fast64_t weekday = (jan1_weekday + days) % 7;
  220|   104k|      if (last_week) {
  ------------------
  |  Branch (220:11): [True: 102k, False: 2.41k]
  ------------------
  221|   102k|        days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1;
  222|   102k|      } else {
  223|  2.41k|        days += (pt.date.m.weekday + 7 - weekday) % 7;
  224|  2.41k|        days += (pt.date.m.week - 1) * 7;
  225|  2.41k|      }
  226|   104k|      break;
  227|      0|    }
  228|   104k|  }
  229|   104k|  return (days * kSecsPerDay) + pt.time.offset;
  230|   104k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_16Header5BuildERK6tzhead:
  157|    494|bool Header::Build(const tzhead& tzh) {
  158|    494|  std::int_fast32_t v;
  159|    494|  if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false;
  ------------------
  |  Branch (159:7): [True: 0, False: 494]
  ------------------
  160|    494|  timecnt = static_cast<std::size_t>(v);
  161|    494|  if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false;
  ------------------
  |  Branch (161:7): [True: 0, False: 494]
  ------------------
  162|    494|  typecnt = static_cast<std::size_t>(v);
  163|    494|  if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false;
  ------------------
  |  Branch (163:7): [True: 0, False: 494]
  ------------------
  164|    494|  charcnt = static_cast<std::size_t>(v);
  165|    494|  if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false;
  ------------------
  |  Branch (165:7): [True: 0, False: 494]
  ------------------
  166|    494|  leapcnt = static_cast<std::size_t>(v);
  167|    494|  if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false;
  ------------------
  |  Branch (167:7): [True: 0, False: 494]
  ------------------
  168|    494|  ttisstdcnt = static_cast<std::size_t>(v);
  169|    494|  if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false;
  ------------------
  |  Branch (169:7): [True: 0, False: 494]
  ------------------
  170|    494|  ttisutcnt = static_cast<std::size_t>(v);
  171|    494|  return true;
  172|    494|}
time_zone_info.cc:_ZNK4cctz12_GLOBAL__N_16Header10DataLengthEm:
  176|    494|std::size_t Header::DataLength(std::size_t time_len) const {
  177|    494|  std::size_t len = 0;
  178|    494|  len += (time_len + 1) * timecnt;  // unix_time + type_index
  179|    494|  len += (4 + 1 + 1) * typecnt;     // utc_offset + is_dst + abbr_index
  180|    494|  len += 1 * charcnt;               // abbreviations
  181|    494|  len += (time_len + 4) * leapcnt;  // leap-time + TAI-UTC
  182|    494|  len += 1 * ttisstdcnt;            // UTC/local indicators
  183|    494|  len += 1 * ttisutcnt;             // standard/wall indicators
  184|    494|  return len;
  185|    494|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_18Decode32EPKc:
  126|  3.66k|std::int_fast32_t Decode32(const char* cp) {
  127|  3.66k|  std::uint_fast32_t v = 0;
  128|  18.3k|  for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++);
  ------------------
  |  Branch (128:19): [True: 14.6k, False: 3.66k]
  ------------------
  129|  3.66k|  const std::int_fast32_t s32max = 0x7fffffff;
  130|  3.66k|  const auto s32maxU = static_cast<std::uint_fast32_t>(s32max);
  131|  3.66k|  if (v <= s32maxU) return static_cast<std::int_fast32_t>(v);
  ------------------
  |  Branch (131:7): [True: 3.61k, False: 53]
  ------------------
  132|     53|  return static_cast<std::int_fast32_t>(v - s32maxU - 1) - s32max - 1;
  133|  3.66k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_18Decode64EPKc:
  135|  16.9k|std::int_fast64_t Decode64(const char* cp) {
  136|  16.9k|  std::uint_fast64_t v = 0;
  137|   152k|  for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++);
  ------------------
  |  Branch (137:19): [True: 135k, False: 16.9k]
  ------------------
  138|  16.9k|  const std::int_fast64_t s64max = 0x7fffffffffffffff;
  139|  16.9k|  const auto s64maxU = static_cast<std::uint_fast64_t>(s64max);
  140|  16.9k|  if (v <= s64maxU) return static_cast<std::int_fast64_t>(v);
  ------------------
  |  Branch (140:7): [True: 16.2k, False: 742]
  ------------------
  141|    742|  return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1;
  142|  16.9k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_17Decode8EPKc:
  116|   168k|inline std::uint_fast8_t Decode8(const char* cp) {
  117|   168k|  return static_cast<std::uint_fast8_t>(*cp) & 0xff;
  118|   168k|}
time_zone_info.cc:_ZZN4cctz12TimeZoneInfo4LoadEPNS_14ZoneInfoSourceEENK3$_0clES2_:
  851|  4.32k|    auto get_char = [](ZoneInfoSource* azip) -> int {
  852|  4.32k|      unsigned char ch;  // all non-EOF results are positive
  853|  4.32k|      return (azip->Read(&ch, 1) == 1) ? ch : EOF;
  ------------------
  |  Branch (853:14): [True: 4.32k, False: 0]
  ------------------
  854|  4.32k|    };
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_19YearShiftERKNS_6detail10civil_timeINS1_10second_tagEEEl:
  263|  3.16k|inline civil_second YearShift(const civil_second& cs, year_t shift) {
  264|  3.16k|  return civil_second(cs.year() + shift, cs.month(), cs.day(),
  265|  3.16k|                      cs.hour(), cs.minute(), cs.second());
  266|  3.16k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_110MakeUniqueERKNSt3__16chrono10time_pointINS2_12system_clockENS2_8durationIlNS1_5ratioILl1ELl1EEEEEEE:
  232|  12.9k|inline time_zone::civil_lookup MakeUnique(const time_point<seconds>& tp) {
  233|  12.9k|  time_zone::civil_lookup cl;
  234|  12.9k|  cl.kind = time_zone::civil_lookup::UNIQUE;
  235|  12.9k|  cl.pre = cl.trans = cl.post = tp;
  236|  12.9k|  return cl;
  237|  12.9k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_110MakeUniqueEl:
  239|  12.7k|inline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) {
  240|  12.7k|  return MakeUnique(FromUnixSeconds(unix_time));
  241|  12.7k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_111MakeSkippedERKNS_10TransitionERKNS_6detail10civil_timeINS4_10second_tagEEE:
  244|     11|                                           const civil_second& cs) {
  245|     11|  time_zone::civil_lookup cl;
  246|     11|  cl.kind = time_zone::civil_lookup::SKIPPED;
  247|     11|  cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec));
  248|     11|  cl.trans = FromUnixSeconds(tr.unix_time);
  249|     11|  cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs));
  250|     11|  return cl;
  251|     11|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_112MakeRepeatedERKNS_10TransitionERKNS_6detail10civil_timeINS4_10second_tagEEE:
  254|     33|                                            const civil_second& cs) {
  255|     33|  time_zone::civil_lookup cl;
  256|     33|  cl.kind = time_zone::civil_lookup::REPEATED;
  257|     33|  cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs));
  258|     33|  cl.trans = FromUnixSeconds(tr.unix_time);
  259|     33|  cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec));
  260|     33|  return cl;
  261|     33|}
time_zone_info.cc:_ZZN4cctz12TimeZoneInfo4LoadERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEENK3$_0clES9_:
  941|    958|      name, [](const std::string& n) -> std::unique_ptr<ZoneInfoSource> {
  942|    958|        if (auto z = FileZoneInfoSource::Open(n)) return z;
  ------------------
  |  Branch (942:18): [True: 248, False: 710]
  ------------------
  943|    710|        if (auto z = AndroidZoneInfoSource::Open(n)) return z;
  ------------------
  |  Branch (943:18): [True: 0, False: 710]
  ------------------
  944|    710|        if (auto z = FuchsiaZoneInfoSource::Open(n)) return z;
  ------------------
  |  Branch (944:18): [True: 0, False: 710]
  ------------------
  945|    710|        return nullptr;
  946|    710|      });
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_118FileZoneInfoSource4OpenERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  500|    958|    const std::string& name) {
  501|       |  // Use of the "file:" prefix is intended for testing purposes only.
  502|    958|  const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
  ------------------
  |  Branch (502:27): [True: 20, False: 938]
  ------------------
  503|       |
  504|       |  // Reject unsafe paths (e.g., "../../etc/passwd").
  505|    958|  if (UnsafePath(name, pos)) {
  ------------------
  |  Branch (505:7): [True: 13, False: 945]
  ------------------
  506|     13|    return nullptr;
  507|     13|  }
  508|       |
  509|       |  // Map the time-zone name to a path name.
  510|    945|  std::string path;
  511|    945|  if (pos == name.size() || name[pos] != '/') {
  ------------------
  |  Branch (511:7): [True: 16, False: 929]
  |  Branch (511:29): [True: 911, False: 18]
  ------------------
  512|    927|    const char* tzdir = "/usr/share/zoneinfo";
  513|    927|    char* tzdir_env = nullptr;
  514|       |#if defined(_MSC_VER)
  515|       |    _dupenv_s(&tzdir_env, nullptr, "TZDIR");
  516|       |#else
  517|    927|    tzdir_env = std::getenv("TZDIR");
  518|    927|#endif
  519|    927|    if (tzdir_env && *tzdir_env) tzdir = tzdir_env;
  ------------------
  |  Branch (519:9): [True: 0, False: 927]
  |  Branch (519:22): [True: 0, False: 0]
  ------------------
  520|    927|    path += tzdir;
  521|    927|    path += '/';
  522|       |#if defined(_MSC_VER)
  523|       |    free(tzdir_env);
  524|       |#endif
  525|    927|  }
  526|    945|  path.append(name, pos, std::string::npos);
  527|       |
  528|       |  // Open the zoneinfo file.
  529|    945|  auto fp = FOpen(path.c_str());
  530|    945|  if (fp == nullptr) return nullptr;
  ------------------
  |  Branch (530:7): [True: 697, False: 248]
  ------------------
  531|    248|  return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(std::move(fp)));
  532|    945|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_110UnsafePathERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEm:
  455|  1.66k|bool UnsafePath(const std::string& name, std::size_t pos) {
  456|       |  // Path traversal: a ".." component that is at the beginning or preceded
  457|       |  // by a separator, and at the end or followed by a separator.
  458|  34.9k|  for (auto i = pos; (i = name.find("..", i)) != std::string::npos; i += 2) {
  ------------------
  |  Branch (458:22): [True: 33.2k, False: 1.64k]
  ------------------
  459|  33.2k|    if ((i == pos || IsPathSeparator(name[i - 1])) &&
  ------------------
  |  Branch (459:10): [True: 114, False: 33.1k]
  |  Branch (459:22): [True: 18.1k, False: 15.0k]
  ------------------
  460|  18.2k|        (i == name.size() - 2 || IsPathSeparator(name[i + 2]))) {
  ------------------
  |  Branch (460:10): [True: 24, False: 18.2k]
  |  Branch (460:34): [True: 2, False: 18.2k]
  ------------------
  461|     26|      return true;
  462|     26|    }
  463|  33.2k|  }
  464|  1.64k|  return false;
  465|  1.66k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_115IsPathSeparatorEc:
  446|  51.4k|inline bool IsPathSeparator(char c) {
  447|       |#if defined(_WIN32)
  448|       |  return c == '/' || c == '\\';
  449|       |#else
  450|  51.4k|  return c == '/';
  451|  51.4k|#endif
  452|  51.4k|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_15FOpenEPKc:
  400|  5.80k|inline FilePtr FOpen(const char* path) {
  401|       |#if defined(_MSC_VER)
  402|       |  FILE* fp;
  403|       |  if (fopen_s(&fp, path, "rb") != 0) fp = nullptr;
  404|       |  return FilePtr(fp, fclose);
  405|       |#else
  406|       |  // Open non-blocking and verify the target is a regular file before handing it
  407|       |  // to stdio. Zone names are potentially attacker-controlled, and a plain
  408|       |  // fopen() on a FIFO or device node (reachable via the "file:" prefix or an
  409|       |  // absolute path) would block indefinitely or read unbounded data.
  410|       |#ifndef O_CLOEXEC
  411|       |#define O_CLOEXEC 0
  412|       |#endif
  413|       |#ifndef O_NONBLOCK
  414|       |#define O_NONBLOCK 0
  415|       |#endif
  416|  5.80k|  const int fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  417|  5.80k|  if (fd >= 0) {
  ------------------
  |  Branch (417:7): [True: 297, False: 5.51k]
  ------------------
  418|       |#if defined(__APPLE__)
  419|       |    // On Apple platforms, avoid fstat() to prevent triggering Apple's Required
  420|       |    // Reason API (NSPrivacyAccessedAPICategoryFileTimestamp) scanner.
  421|       |    // Security implications of skipping this check on Apple platforms:
  422|       |    //   - FIFO hangs are mitigated by O_NONBLOCK
  423|       |    //   - Path traversal is handled by UnsafePath()
  424|       |    //   - /usr/share/zoneinfo is a read-only system volume on iOS
  425|       |    // On general POSIX operating systems, the check remains as
  426|       |    // defense-in-depth.
  427|       |    auto is_regular = [](int) { return true; };
  428|       |#else
  429|    297|    auto is_regular = [](int stat_fd) {
  430|    297|      struct stat st;
  431|    297|      return fstat(stat_fd, &st) == 0 && S_ISREG(st.st_mode);
  432|    297|    };
  433|    297|#endif
  434|    297|    if (is_regular(fd)) {
  ------------------
  |  Branch (434:9): [True: 248, False: 49]
  ------------------
  435|    248|      FILE* fp = fdopen(fd, "rb");
  436|    248|      if (fp != nullptr) return FilePtr(fp, fclose);
  ------------------
  |  Branch (436:11): [True: 248, False: 0]
  ------------------
  437|    248|    }
  438|     49|    close(fd);
  439|     49|  }
  440|  5.56k|  return FilePtr(nullptr, fclose);
  441|  5.80k|#endif
  442|  5.80k|}
time_zone_info.cc:_ZZN4cctz12_GLOBAL__N_15FOpenEPKcENKUliE_clEi:
  429|    297|    auto is_regular = [](int stat_fd) {
  430|    297|      struct stat st;
  431|    297|      return fstat(stat_fd, &st) == 0 && S_ISREG(st.st_mode);
  ------------------
  |  Branch (431:14): [True: 297, False: 0]
  |  Branch (431:42): [True: 248, False: 49]
  ------------------
  432|    297|    };
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_118FileZoneInfoSourceC2ENSt3__110unique_ptrI8_IO_FILEPFiPS4_EEEm:
  492|    248|      : fp_(std::move(fp)), len_(len) {}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_118FileZoneInfoSource4ReadEPvm:
  472|  5.07k|  std::size_t Read(void* ptr, std::size_t size) override {
  473|  5.07k|    size = std::min(size, len_);
  474|  5.07k|    std::size_t nread = fread(ptr, 1, size, fp_.get());
  475|  5.07k|    len_ -= nread;
  476|  5.07k|    return nread;
  477|  5.07k|  }
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_118FileZoneInfoSource4SkipEm:
  478|    247|  int Skip(std::size_t offset) override {
  479|    247|    offset = std::min(offset, len_);
  480|    247|    int rc = fseek(fp_.get(), static_cast<long>(offset), SEEK_CUR);
  481|    247|    if (rc == 0) len_ -= offset;
  ------------------
  |  Branch (481:9): [True: 247, False: 0]
  ------------------
  482|    247|    return rc;
  483|    247|  }
time_zone_info.cc:_ZNK4cctz12_GLOBAL__N_118FileZoneInfoSource7VersionEv:
  484|    247|  std::string Version() const override {
  485|       |    // TODO: It would nice if the zoneinfo data included the tzdb version.
  486|    247|    return std::string();
  487|    247|  }
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_121AndroidZoneInfoSource4OpenERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  547|    710|    const std::string& name) {
  548|       |  // Use of the "file:" prefix is intended for testing purposes only.
  549|    710|  const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
  ------------------
  |  Branch (549:27): [True: 20, False: 690]
  ------------------
  550|       |
  551|       |  // See Android's libc/tzcode/bionic.cpp for additional information.
  552|    710|  for (const char* tzdata : {"/apex/com.android.tzdata/etc/tz/tzdata",
  ------------------
  |  Branch (552:27): [True: 2.13k, False: 710]
  ------------------
  553|    710|                             "/data/misc/zoneinfo/current/tzdata",
  554|  2.13k|                             "/system/usr/share/zoneinfo/tzdata"}) {
  555|  2.13k|    auto fp = FOpen(tzdata);
  556|  2.13k|    if (fp == nullptr) continue;
  ------------------
  |  Branch (556:9): [True: 2.13k, False: 0]
  ------------------
  557|       |
  558|      0|    char hbuf[24];  // covers header.zonetab_offset too
  559|      0|    if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue;
  ------------------
  |  Branch (559:9): [True: 0, False: 0]
  ------------------
  560|      0|    if (strncmp(hbuf, "tzdata", 6) != 0) continue;
  ------------------
  |  Branch (560:9): [True: 0, False: 0]
  ------------------
  561|      0|    const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : "";
  ------------------
  |  Branch (561:24): [True: 0, False: 0]
  ------------------
  562|      0|    const std::int_fast32_t index_offset = Decode32(hbuf + 12);
  563|      0|    const std::int_fast32_t data_offset = Decode32(hbuf + 16);
  564|      0|    if (index_offset < 0 || data_offset < index_offset) continue;
  ------------------
  |  Branch (564:9): [True: 0, False: 0]
  |  Branch (564:29): [True: 0, False: 0]
  ------------------
  565|      0|    if (fseek(fp.get(), static_cast<long>(index_offset), SEEK_SET) != 0)
  ------------------
  |  Branch (565:9): [True: 0, False: 0]
  ------------------
  566|      0|      continue;
  567|       |
  568|      0|    char ebuf[52];  // covers entry.unused too
  569|      0|    const std::size_t index_size =
  570|      0|        static_cast<std::size_t>(data_offset - index_offset);
  571|      0|    const std::size_t zonecnt = index_size / sizeof(ebuf);
  572|      0|    if (zonecnt * sizeof(ebuf) != index_size) continue;
  ------------------
  |  Branch (572:9): [True: 0, False: 0]
  ------------------
  573|      0|    for (std::size_t i = 0; i != zonecnt; ++i) {
  ------------------
  |  Branch (573:29): [True: 0, False: 0]
  ------------------
  574|      0|      if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break;
  ------------------
  |  Branch (574:11): [True: 0, False: 0]
  ------------------
  575|      0|      const std::int_fast64_t start =
  576|      0|          std::int_fast64_t{data_offset} + Decode32(ebuf + 40);
  577|      0|      const std::int_fast32_t length = Decode32(ebuf + 44);
  578|      0|      if (start < 0 || length < 0) break;
  ------------------
  |  Branch (578:11): [True: 0, False: 0]
  |  Branch (578:24): [True: 0, False: 0]
  ------------------
  579|       |      // fseek() takes a long
  580|      0|      if (start > std::numeric_limits<long>::max()) break;
  ------------------
  |  Branch (580:11): [True: 0, False: 0]
  ------------------
  581|      0|      ebuf[40] = '\0';  // ensure zone name is NUL terminated
  582|      0|      if (strcmp(name.c_str() + pos, ebuf) == 0) {
  ------------------
  |  Branch (582:11): [True: 0, False: 0]
  ------------------
  583|      0|        if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break;
  ------------------
  |  Branch (583:13): [True: 0, False: 0]
  ------------------
  584|      0|        return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource(
  585|      0|            std::move(fp), static_cast<std::size_t>(length), vers));
  586|      0|      }
  587|      0|    }
  588|      0|  }
  589|       |
  590|    710|  return nullptr;
  591|    710|}
time_zone_info.cc:_ZN4cctz12_GLOBAL__N_121FuchsiaZoneInfoSource4OpenERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  613|    710|    const std::string& name) {
  614|       |  // Use of the "file:" prefix is intended for testing purposes only.
  615|    710|  const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
  ------------------
  |  Branch (615:27): [True: 20, False: 690]
  ------------------
  616|       |
  617|       |  // Reject unsafe paths (e.g., "../../etc/passwd").
  618|    710|  if (UnsafePath(name, pos)) {
  ------------------
  |  Branch (618:7): [True: 13, False: 697]
  ------------------
  619|     13|    return nullptr;
  620|     13|  }
  621|       |
  622|       |  // Prefixes where a Fuchsia component might find zoneinfo files,
  623|       |  // in descending order of preference.
  624|    697|  const auto kTzdataPrefixes = {
  625|       |      // The tzdata from `config-data`.
  626|    697|      "/config/data/tzdata/",
  627|       |      // The tzdata bundled in the component's package.
  628|    697|      "/pkg/data/tzdata/",
  629|       |      // General data storage.
  630|    697|      "/data/tzdata/",
  631|       |      // The recommended path for routed-in tzdata files.
  632|       |      // See for details:
  633|       |      // https://fuchsia.dev/fuchsia-src/concepts/process/namespaces?hl=en#typical_directory_structure
  634|    697|      "/config/tzdata/",
  635|    697|  };
  636|    697|  const auto kEmptyPrefix = {""};
  637|    697|  const bool name_absolute = (pos != name.size() && name[pos] == '/');
  ------------------
  |  Branch (637:31): [True: 681, False: 16]
  |  Branch (637:53): [True: 18, False: 663]
  ------------------
  638|    697|  const auto prefixes = name_absolute ? kEmptyPrefix : kTzdataPrefixes;
  ------------------
  |  Branch (638:25): [True: 18, False: 679]
  ------------------
  639|       |
  640|       |  // Fuchsia builds place zoneinfo files at "<prefix><format><name>".
  641|  2.73k|  for (const std::string prefix : prefixes) {
  ------------------
  |  Branch (641:33): [True: 2.73k, False: 697]
  ------------------
  642|  2.73k|    std::string path = prefix;
  643|  2.73k|    if (!prefix.empty()) path += "zoneinfo/tzif2/";  // format
  ------------------
  |  Branch (643:9): [True: 2.71k, False: 18]
  ------------------
  644|  2.73k|    path.append(name, pos, std::string::npos);
  645|       |
  646|  2.73k|    auto fp = FOpen(path.c_str());
  647|  2.73k|    if (fp == nullptr) continue;
  ------------------
  |  Branch (647:9): [True: 2.73k, False: 0]
  ------------------
  648|       |
  649|      0|    std::string version;
  650|      0|    if (!prefix.empty()) {
  ------------------
  |  Branch (650:9): [True: 0, False: 0]
  ------------------
  651|       |      // Fuchsia builds place the version in "<prefix>revision.txt".
  652|      0|      std::ifstream version_stream(prefix + "revision.txt");
  653|      0|      if (version_stream.is_open()) {
  ------------------
  |  Branch (653:11): [True: 0, False: 0]
  ------------------
  654|       |        // revision.txt should contain no newlines, but to be
  655|       |        // defensive we read just the first line.
  656|      0|        std::getline(version_stream, version);
  657|      0|      }
  658|      0|    }
  659|       |
  660|      0|    return std::unique_ptr<ZoneInfoSource>(
  661|      0|        new FuchsiaZoneInfoSource(std::move(fp), std::move(version)));
  662|  2.73k|  }
  663|       |
  664|    697|  return nullptr;
  665|    697|}

_ZNK4cctz10Transition10ByUnixTimeclERKS0_S3_:
   41|   141k|    inline bool operator()(const Transition& lhs, const Transition& rhs) const {
   42|   141k|      return lhs.unix_time < rhs.unix_time;
   43|   141k|    }
_ZNK4cctz10Transition11ByCivilTimeclERKS0_S3_:
   46|   156k|    inline bool operator()(const Transition& lhs, const Transition& rhs) const {
   47|   156k|      return lhs.civil_sec < rhs.civil_sec;
   48|   156k|    }
_ZN4cctz12TimeZoneInfoC2Ev:
   81|  1.29k|  TimeZoneInfo() = default;

_ZN4cctz12TimeZoneLibC4MakeERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  194|    272|std::unique_ptr<TimeZoneLibC> TimeZoneLibC::Make(const std::string& name) {
  195|    272|  return std::unique_ptr<TimeZoneLibC>(new TimeZoneLibC(name));
  196|    272|}
_ZNK4cctz12TimeZoneLibC9BreakTimeERKNSt3__16chrono10time_pointINS2_12system_clockENS2_8durationIlNS1_5ratioILl1ELl1EEEEEEE:
  199|  1.59k|    const time_point<seconds>& tp) const {
  200|  1.59k|  time_zone::absolute_lookup al;
  201|  1.59k|  al.offset = 0;
  202|  1.59k|  al.is_dst = false;
  203|  1.59k|  al.abbr = "-00";
  204|       |
  205|  1.59k|  const std::int_fast64_t s = ToUnixSeconds(tp);
  206|       |
  207|       |  // If std::time_t cannot hold the input we saturate the output.
  208|  1.59k|  if (s < std::numeric_limits<std::time_t>::min()) {
  ------------------
  |  Branch (208:7): [True: 0, False: 1.59k]
  ------------------
  209|      0|    al.cs = civil_second::min();
  210|      0|    return al;
  211|      0|  }
  212|  1.59k|  if (s > std::numeric_limits<std::time_t>::max()) {
  ------------------
  |  Branch (212:7): [True: 0, False: 1.59k]
  ------------------
  213|      0|    al.cs = civil_second::max();
  214|      0|    return al;
  215|      0|  }
  216|       |
  217|  1.59k|  const std::time_t t = static_cast<std::time_t>(s);
  218|  1.59k|  std::tm tm;
  219|  1.59k|  std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm);
  ------------------
  |  Branch (219:18): [True: 450, False: 1.14k]
  ------------------
  220|       |
  221|       |  // If std::tm cannot hold the result we saturate the output.
  222|  1.59k|  if (tmp == nullptr) {
  ------------------
  |  Branch (222:7): [True: 456, False: 1.13k]
  ------------------
  223|    456|    al.cs = (s < 0) ? civil_second::min() : civil_second::max();
  ------------------
  |  Branch (223:13): [True: 209, False: 247]
  ------------------
  224|    456|    return al;
  225|    456|  }
  226|       |
  227|  1.13k|  const year_t year = tmp->tm_year + year_t{1900};
  228|  1.13k|  al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday,
  229|  1.13k|                       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  230|  1.13k|  al.offset = static_cast<int>(tm_gmtoff(*tmp));
  231|  1.13k|  al.abbr = local_ ? tm_zone(*tmp) : "UTC";  // as expected by cctz
  ------------------
  |  Branch (231:13): [True: 307, False: 831]
  ------------------
  232|  1.13k|  al.is_dst = tmp->tm_isdst > 0;
  233|  1.13k|  return al;
  234|  1.59k|}
_ZNK4cctz12TimeZoneLibC8MakeTimeERKNS_6detail10civil_timeINS1_10second_tagEEE:
  236|  2.32k|time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
  237|  2.32k|  if (!local_) {
  ------------------
  |  Branch (237:7): [True: 1.68k, False: 632]
  ------------------
  238|       |    // If time_point<seconds> cannot hold the result we saturate.
  239|  1.68k|    static const civil_second min_tp_cs =
  240|  1.68k|        civil_second() + ToUnixSeconds(time_point<seconds>::min());
  241|  1.68k|    static const civil_second max_tp_cs =
  242|  1.68k|        civil_second() + ToUnixSeconds(time_point<seconds>::max());
  243|  1.68k|    const time_point<seconds> tp =
  244|  1.68k|        (cs < min_tp_cs)
  ------------------
  |  Branch (244:9): [True: 110, False: 1.57k]
  ------------------
  245|  1.68k|            ? time_point<seconds>::min()
  246|  1.68k|            : (cs > max_tp_cs) ? time_point<seconds>::max()
  ------------------
  |  Branch (246:15): [True: 117, False: 1.46k]
  ------------------
  247|  1.57k|                               : FromUnixSeconds(cs - civil_second());
  248|  1.68k|    return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
  249|  1.68k|  }
  250|       |
  251|       |  // If tm_year cannot hold the requested year we saturate the result.
  252|    632|  if (cs.year() < 0) {
  ------------------
  |  Branch (252:7): [True: 411, False: 221]
  ------------------
  253|    411|    if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) {
  ------------------
  |  Branch (253:9): [True: 98, False: 313]
  ------------------
  254|     98|      const time_point<seconds> tp = time_point<seconds>::min();
  255|     98|      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
  256|     98|    }
  257|    411|  } else {
  258|    221|    if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) {
  ------------------
  |  Branch (258:9): [True: 44, False: 177]
  ------------------
  259|     44|      const time_point<seconds> tp = time_point<seconds>::max();
  260|     44|      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
  261|     44|    }
  262|    221|  }
  263|       |
  264|       |  // We probe with "is_dst" values of 0 and 1 to try to distinguish unique
  265|       |  // civil seconds from skipped or repeated ones.  This is not always possible
  266|       |  // however, as the "dst" flag does not change over some offset transitions.
  267|       |  // We are also subject to the vagaries of mktime() implementations. For
  268|       |  // example, some implementations treat "tm_isdst" as a demand (useless),
  269|       |  // and some as a disambiguator (useful).
  270|    490|  std::time_t t0, t1;
  271|    490|  std::tm tm0, tm1;
  272|    490|  if (make_time(cs, 0, &t0, &tm0) && make_time(cs, 1, &t1, &tm1)) {
  ------------------
  |  Branch (272:7): [True: 490, False: 0]
  |  Branch (272:38): [True: 489, False: 1]
  ------------------
  273|    489|    if (tm0.tm_isdst == tm1.tm_isdst) {
  ------------------
  |  Branch (273:9): [True: 489, False: 0]
  ------------------
  274|       |      // The civil time was singular (pre == trans == post).
  275|    489|      const time_point<seconds> tp = FromUnixSeconds(tm0.tm_isdst ? t1 : t0);
  ------------------
  |  Branch (275:54): [True: 0, False: 489]
  ------------------
  276|    489|      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
  277|    489|    }
  278|       |
  279|      0|    tm_gmtoff_t offset = tm_gmtoff(tm0);
  280|      0|    if (t0 < t1) {  // negative DST
  ------------------
  |  Branch (280:9): [True: 0, False: 0]
  ------------------
  281|      0|      std::swap(t0, t1);
  282|      0|      offset = tm_gmtoff(tm1);
  283|      0|    }
  284|       |
  285|      0|    const std::time_t tt = find_trans(t1, t0, offset);
  286|      0|    const time_point<seconds> trans = FromUnixSeconds(tt);
  287|       |
  288|      0|    if (tm0.tm_isdst) {
  ------------------
  |  Branch (288:9): [True: 0, False: 0]
  ------------------
  289|       |      // The civil time did not exist (pre >= trans > post).
  290|      0|      const time_point<seconds> pre = FromUnixSeconds(t0);
  291|      0|      const time_point<seconds> post = FromUnixSeconds(t1);
  292|      0|      return {time_zone::civil_lookup::SKIPPED, pre, trans, post};
  293|      0|    }
  294|       |
  295|       |    // The civil time was ambiguous (pre < trans <= post).
  296|      0|    const time_point<seconds> pre = FromUnixSeconds(t1);
  297|      0|    const time_point<seconds> post = FromUnixSeconds(t0);
  298|      0|    return {time_zone::civil_lookup::REPEATED, pre, trans, post};
  299|      0|  }
  300|       |
  301|       |  // make_time() failed somehow so we saturate the result.
  302|      1|  const time_point<seconds> tp = (cs < civil_second())
  ------------------
  |  Branch (302:34): [True: 1, False: 0]
  ------------------
  303|      1|                                     ? time_point<seconds>::min()
  304|      1|                                     : time_point<seconds>::max();
  305|      1|  return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
  306|    490|}
_ZN4cctz12TimeZoneLibCC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  327|    272|    : local_(name == "localtime") {}
time_zone_libc.cc:_ZN4cctz12_GLOBAL__N_110local_timeEPKlP2tm:
  129|    453|inline std::tm* local_time(const std::time_t *timep, std::tm *result) {
  130|       |#if defined(_WIN32) || defined(_WIN64)
  131|       |    return localtime_s(result, timep) ? nullptr : result;
  132|       |#else
  133|    453|    return localtime_r(timep, result);
  134|    453|#endif
  135|    453|}
time_zone_libc.cc:_ZN4cctz12_GLOBAL__N_17gm_timeEPKlP2tm:
  121|  1.14k|inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
  122|       |#if defined(_WIN32) || defined(_WIN64)
  123|       |    return gmtime_s(result, timep) ? nullptr : result;
  124|       |#else
  125|  1.14k|    return gmtime_r(timep, result);
  126|  1.14k|#endif
  127|  1.14k|}
time_zone_libc.cc:_ZN4cctz12_GLOBAL__N_19make_timeERKNS_6detail10civil_timeINS1_10second_tagEEEiPlP2tm:
  141|    980|               std::tm* tm) {
  142|    980|  tm->tm_year = static_cast<int>(cs.year() - year_t{1900});
  143|    980|  tm->tm_mon = cs.month() - 1;
  144|    980|  tm->tm_mday = cs.day();
  145|    980|  tm->tm_hour = cs.hour();
  146|    980|  tm->tm_min = cs.minute();
  147|    980|  tm->tm_sec = cs.second();
  148|    980|  tm->tm_isdst = is_dst;
  149|    980|  *t = std::mktime(tm);
  150|    980|  if (*t == std::time_t{-1}) {
  ------------------
  |  Branch (150:7): [True: 3, False: 977]
  ------------------
  151|      3|    std::tm tm2;
  152|      3|    const std::tm* tmp = local_time(t, &tm2);
  153|      3|    if (tmp == nullptr || tmp->tm_year != tm->tm_year ||
  ------------------
  |  Branch (153:9): [True: 0, False: 3]
  |  Branch (153:27): [True: 1, False: 2]
  ------------------
  154|      2|        tmp->tm_mon != tm->tm_mon || tmp->tm_mday != tm->tm_mday ||
  ------------------
  |  Branch (154:9): [True: 0, False: 2]
  |  Branch (154:38): [True: 0, False: 2]
  ------------------
  155|      2|        tmp->tm_hour != tm->tm_hour || tmp->tm_min != tm->tm_min ||
  ------------------
  |  Branch (155:9): [True: 0, False: 2]
  |  Branch (155:40): [True: 0, False: 2]
  ------------------
  156|      2|        tmp->tm_sec != tm->tm_sec) {
  ------------------
  |  Branch (156:9): [True: 0, False: 2]
  ------------------
  157|       |      // A true error (not just one second before the epoch).
  158|      1|      return false;
  159|      1|    }
  160|      3|  }
  161|    979|  return true;
  162|    980|}
time_zone_libc.cc:_ZN4cctz12_GLOBAL__N_19tm_gmtoffI2tmEEDtdtfp_9tm_gmtoffERKT_:
   92|  1.13k|auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) {
   93|  1.13k|  return tm.tm_gmtoff;
   94|  1.13k|}
time_zone_libc.cc:_ZN4cctz12_GLOBAL__N_17tm_zoneI2tmEEDtdtfp_7tm_zoneERKT_:
  110|    307|auto tm_zone(const T& tm) -> decltype(tm.tm_zone) {
  111|    307|  return tm.tm_zone;
  112|    307|}

_ZNK4cctz9time_zone6lookupERKNSt3__16chrono10time_pointINS2_12system_clockENS2_8durationIlNS1_5ratioILl1ELl1EEEEEEE:
   53|  9.87k|    const time_point<seconds>& tp) const {
   54|  9.87k|  return effective_impl().BreakTime(tp);
   55|  9.87k|}
_ZNK4cctz9time_zone6lookupERKNS_6detail10civil_timeINS1_10second_tagEEE:
   57|  15.2k|time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const {
   58|  15.2k|  return effective_impl().MakeTime(cs);
   59|  15.2k|}
_ZNK4cctz9time_zone14effective_implEv:
   79|  25.1k|const time_zone::Impl& time_zone::effective_impl() const {
   80|  25.1k|  if (impl_ == nullptr) {
  ------------------
  |  Branch (80:7): [True: 0, False: 25.1k]
  ------------------
   81|       |    // Dereferencing an implicit-UTC time_zone is expected to be
   82|       |    // rare, so we don't mind paying a small synchronization cost.
   83|      0|    return *time_zone::Impl::UTC().impl_;
   84|      0|  }
   85|  25.1k|  return *impl_;
   86|  25.1k|}
_ZN4cctz14load_time_zoneERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPNS_9time_zoneE:
   88|  9.83k|bool load_time_zone(const std::string& name, time_zone* tz) {
   89|  9.83k|  return time_zone::Impl::LoadTimeZone(name, tz);
   90|  9.83k|}
_ZN4cctz13utc_time_zoneEv:
   92|    210|time_zone utc_time_zone() {
   93|    210|  return time_zone::Impl::UTC();  // avoid name lookup
   94|    210|}

_ZN4cctz14ParsePosixSpecERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEPNS_13PosixTimeZoneE:
  135|    247|bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) {
  136|    247|  const char* p = spec.c_str();
  137|    247|  if (*p == ':') return false;
  ------------------
  |  Branch (137:7): [True: 0, False: 247]
  ------------------
  138|       |
  139|    247|  p = ParseAbbr(p, &res->std_abbr);
  140|    247|  p = ParseOffset(p, 0, 24, -1, &res->std_offset);
  141|    247|  if (p == nullptr) return false;
  ------------------
  |  Branch (141:7): [True: 0, False: 247]
  ------------------
  142|    247|  if (*p == '\0') return true;
  ------------------
  |  Branch (142:7): [True: 117, False: 130]
  ------------------
  143|       |
  144|    130|  p = ParseAbbr(p, &res->dst_abbr);
  145|    130|  if (p == nullptr) return false;
  ------------------
  |  Branch (145:7): [True: 0, False: 130]
  ------------------
  146|    130|  res->dst_offset = res->std_offset + (60 * 60);  // default
  147|    130|  if (*p != ',') p = ParseOffset(p, 0, 24, -1, &res->dst_offset);
  ------------------
  |  Branch (147:7): [True: 0, False: 130]
  ------------------
  148|       |
  149|    130|  p = ParseDateTime(p, &res->dst_start);
  150|    130|  p = ParseDateTime(p, &res->dst_end);
  151|       |
  152|    130|  return p != nullptr && *p == '\0';
  ------------------
  |  Branch (152:10): [True: 130, False: 0]
  |  Branch (152:26): [True: 130, False: 0]
  ------------------
  153|    130|}
time_zone_posix.cc:_ZN4cctz12_GLOBAL__N_19ParseAbbrEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
   46|    377|const char* ParseAbbr(const char* p, std::string* abbr) {
   47|    377|  const char* op = p;
   48|    377|  if (*p == '<') {  // special zoneinfo <...> form
  ------------------
  |  Branch (48:7): [True: 5, False: 372]
  ------------------
   49|      5|    if (*++p == '>' || *p == '\0') return nullptr;  // no "<>"
  ------------------
  |  Branch (49:9): [True: 0, False: 5]
  |  Branch (49:24): [True: 0, False: 5]
  ------------------
   50|     15|    while (*++p != '>') {
  ------------------
  |  Branch (50:12): [True: 10, False: 5]
  ------------------
   51|     10|      if (*p == '\0') return nullptr;
  ------------------
  |  Branch (51:11): [True: 0, False: 10]
  ------------------
   52|     10|    }
   53|      5|    abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1);
   54|      5|    return ++p;
   55|      5|  }
   56|  1.61k|  while (*p != '\0') {
  ------------------
  |  Branch (56:10): [True: 1.61k, False: 0]
  ------------------
   57|  1.61k|    if (strchr("-+,", *p)) break;
  ------------------
  |  Branch (57:9): [True: 194, False: 1.42k]
  ------------------
   58|  1.42k|    if (strchr(kDigits, *p)) break;
  ------------------
  |  Branch (58:9): [True: 178, False: 1.24k]
  ------------------
   59|  1.24k|    ++p;
   60|  1.24k|  }
   61|    372|  if (p - op < 3) return nullptr;
  ------------------
  |  Branch (61:7): [True: 0, False: 372]
  ------------------
   62|    372|  abbr->assign(op, static_cast<std::size_t>(p - op));
   63|    372|  return p;
   64|    372|}
time_zone_posix.cc:_ZN4cctz12_GLOBAL__N_111ParseOffsetEPKciiiPl:
   68|    391|                        std::int_fast32_t* offset) {
   69|    391|  if (p == nullptr) return nullptr;
  ------------------
  |  Branch (69:7): [True: 0, False: 391]
  ------------------
   70|    391|  if (*p == '+' || *p == '-') {
  ------------------
  |  Branch (70:7): [True: 0, False: 391]
  |  Branch (70:20): [True: 69, False: 322]
  ------------------
   71|     69|    if (*p++ == '-') sign = -sign;
  ------------------
  |  Branch (71:9): [True: 69, False: 0]
  ------------------
   72|     69|  }
   73|    391|  int hours = 0;
   74|    391|  int minutes = 0;
   75|    391|  int seconds = 0;
   76|       |
   77|    391|  p = ParseInt(p, min_hour, max_hour, &hours);
   78|    391|  if (p == nullptr) return nullptr;
  ------------------
  |  Branch (78:7): [True: 0, False: 391]
  ------------------
   79|    391|  if (*p == ':') {
  ------------------
  |  Branch (79:7): [True: 0, False: 391]
  ------------------
   80|      0|    p = ParseInt(p + 1, 0, 59, &minutes);
   81|      0|    if (p == nullptr) return nullptr;
  ------------------
  |  Branch (81:9): [True: 0, False: 0]
  ------------------
   82|      0|    if (*p == ':') {
  ------------------
  |  Branch (82:9): [True: 0, False: 0]
  ------------------
   83|      0|      p = ParseInt(p + 1, 0, 59, &seconds);
   84|      0|      if (p == nullptr) return nullptr;
  ------------------
  |  Branch (84:11): [True: 0, False: 0]
  ------------------
   85|      0|    }
   86|      0|  }
   87|    391|  *offset = sign * ((((hours * 60) + minutes) * 60) + seconds);
   88|    391|  return p;
   89|    391|}
time_zone_posix.cc:_ZN4cctz12_GLOBAL__N_18ParseIntEPKciiPi:
   28|  1.17k|const char* ParseInt(const char* p, int min, int max, int* vp) {
   29|  1.17k|  int value = 0;
   30|  1.17k|  const char* op = p;
   31|  1.17k|  const int kMaxInt = std::numeric_limits<int>::max();
   32|  2.48k|  for (; const char* dp = strchr(kDigits, *p); ++p) {
  ------------------
  |  Branch (32:22): [True: 1.56k, False: 924]
  ------------------
   33|  1.56k|    int d = static_cast<int>(dp - kDigits);
   34|  1.56k|    if (d >= 10) break;  // '\0'
  ------------------
  |  Branch (34:9): [True: 247, False: 1.31k]
  ------------------
   35|  1.31k|    if (value > kMaxInt / 10) return nullptr;
  ------------------
  |  Branch (35:9): [True: 0, False: 1.31k]
  ------------------
   36|  1.31k|    value *= 10;
   37|  1.31k|    if (value > kMaxInt - d) return nullptr;
  ------------------
  |  Branch (37:9): [True: 0, False: 1.31k]
  ------------------
   38|  1.31k|    value += d;
   39|  1.31k|  }
   40|  1.17k|  if (p == op || value < min || value > max) return nullptr;
  ------------------
  |  Branch (40:7): [True: 0, False: 1.17k]
  |  Branch (40:18): [True: 0, False: 1.17k]
  |  Branch (40:33): [True: 0, False: 1.17k]
  ------------------
   41|  1.17k|  *vp = value;
   42|  1.17k|  return p;
   43|  1.17k|}
time_zone_posix.cc:_ZN4cctz12_GLOBAL__N_113ParseDateTimeEPKcPNS_15PosixTransitionE:
   92|    260|const char* ParseDateTime(const char* p, PosixTransition* res) {
   93|    260|  if (p != nullptr) {
  ------------------
  |  Branch (93:7): [True: 260, False: 0]
  ------------------
   94|    260|    if (*p != ',') return nullptr;
  ------------------
  |  Branch (94:9): [True: 0, False: 260]
  ------------------
   95|    260|    if (*++p == 'M') {
  ------------------
  |  Branch (95:9): [True: 260, False: 0]
  ------------------
   96|    260|      int month = 0;
   97|    260|      if ((p = ParseInt(p + 1, 1, 12, &month)) != nullptr) {
  ------------------
  |  Branch (97:11): [True: 260, False: 0]
  ------------------
   98|    260|        if (*p != '.') return nullptr;
  ------------------
  |  Branch (98:13): [True: 0, False: 260]
  ------------------
   99|    260|        int week = 0;
  100|    260|        if ((p = ParseInt(p + 1, 1, 5, &week)) != nullptr) {
  ------------------
  |  Branch (100:13): [True: 260, False: 0]
  ------------------
  101|    260|          if (*p != '.') return nullptr;
  ------------------
  |  Branch (101:15): [True: 0, False: 260]
  ------------------
  102|    260|          int weekday = 0;
  103|    260|          if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) {
  ------------------
  |  Branch (103:15): [True: 260, False: 0]
  ------------------
  104|    260|            res->date.fmt = PosixTransition::M;
  105|    260|            res->date.m.month = static_cast<std::int_fast8_t>(month);
  106|    260|            res->date.m.week = static_cast<std::int_fast8_t>(week);
  107|    260|            res->date.m.weekday = static_cast<std::int_fast8_t>(weekday);
  108|    260|          }
  109|    260|        }
  110|    260|      }
  111|    260|    } else if (*p == 'J') {
  ------------------
  |  Branch (111:16): [True: 0, False: 0]
  ------------------
  112|      0|      int day = 0;
  113|      0|      if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) {
  ------------------
  |  Branch (113:11): [True: 0, False: 0]
  ------------------
  114|      0|        res->date.fmt = PosixTransition::J;
  115|      0|        res->date.j.day = static_cast<std::int_fast16_t>(day);
  116|      0|      }
  117|      0|    } else {
  118|      0|      int day = 0;
  119|      0|      if ((p = ParseInt(p, 0, 365, &day)) != nullptr) {
  ------------------
  |  Branch (119:11): [True: 0, False: 0]
  ------------------
  120|      0|        res->date.fmt = PosixTransition::N;
  121|      0|        res->date.n.day = static_cast<std::int_fast16_t>(day);
  122|      0|      }
  123|      0|    }
  124|    260|    if (p != nullptr) {
  ------------------
  |  Branch (124:9): [True: 260, False: 0]
  ------------------
  125|    260|      res->time.offset = 2 * 60 * 60;  // default offset is 02:00:00
  126|    260|      if (*p == '/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset);
  ------------------
  |  Branch (126:11): [True: 144, False: 116]
  ------------------
  127|    260|    }
  128|    260|  }
  129|    260|  return p;
  130|    260|}

_ZN4cctz14ZoneInfoSourceD2Ev:
   20|    248|ZoneInfoSource::~ZoneInfoSource() {}
zone_info_source.cc:_ZN14cctz_extension12_GLOBAL__N_114DefaultFactoryERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERKNS1_8functionIFNS1_10unique_ptrIN4cctz14ZoneInfoSourceENS1_14default_deleteISD_EEEES9_EEE:
   34|    958|        const std::string& name)>& fallback_factory) {
   35|    958|  return fallback_factory(name);
   36|    958|}

