tor-browser

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

time_zone_posix.cc (4824B)


      1 // Copyright 2016 Google Inc. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //   https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 //   Unless required by applicable law or agreed to in writing, software
     10 //   distributed under the License is distributed on an "AS IS" BASIS,
     11 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 //   See the License for the specific language governing permissions and
     13 //   limitations under the License.
     14 
     15 #include "absl/time/internal/cctz/src/time_zone_posix.h"
     16 
     17 #include <cstddef>
     18 #include <cstring>
     19 #include <limits>
     20 #include <string>
     21 
     22 #include "absl/base/config.h"
     23 
     24 namespace absl {
     25 ABSL_NAMESPACE_BEGIN
     26 namespace time_internal {
     27 namespace cctz {
     28 
     29 namespace {
     30 
     31 const char kDigits[] = "0123456789";
     32 
     33 const char* ParseInt(const char* p, int min, int max, int* vp) {
     34  int value = 0;
     35  const char* op = p;
     36  const int kMaxInt = std::numeric_limits<int>::max();
     37  for (; const char* dp = strchr(kDigits, *p); ++p) {
     38    int d = static_cast<int>(dp - kDigits);
     39    if (d >= 10) break;  // '\0'
     40    if (value > kMaxInt / 10) return nullptr;
     41    value *= 10;
     42    if (value > kMaxInt - d) return nullptr;
     43    value += d;
     44  }
     45  if (p == op || value < min || value > max) return nullptr;
     46  *vp = value;
     47  return p;
     48 }
     49 
     50 // abbr = <.*?> | [^-+,\d]{3,}
     51 const char* ParseAbbr(const char* p, std::string* abbr) {
     52  const char* op = p;
     53  if (*p == '<') {  // special zoneinfo <...> form
     54    while (*++p != '>') {
     55      if (*p == '\0') return nullptr;
     56    }
     57    abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1);
     58    return ++p;
     59  }
     60  while (*p != '\0') {
     61    if (strchr("-+,", *p)) break;
     62    if (strchr(kDigits, *p)) break;
     63    ++p;
     64  }
     65  if (p - op < 3) return nullptr;
     66  abbr->assign(op, static_cast<std::size_t>(p - op));
     67  return p;
     68 }
     69 
     70 // offset = [+|-]hh[:mm[:ss]] (aggregated into single seconds value)
     71 const char* ParseOffset(const char* p, int min_hour, int max_hour, int sign,
     72                        std::int_fast32_t* offset) {
     73  if (p == nullptr) return nullptr;
     74  if (*p == '+' || *p == '-') {
     75    if (*p++ == '-') sign = -sign;
     76  }
     77  int hours = 0;
     78  int minutes = 0;
     79  int seconds = 0;
     80 
     81  p = ParseInt(p, min_hour, max_hour, &hours);
     82  if (p == nullptr) return nullptr;
     83  if (*p == ':') {
     84    p = ParseInt(p + 1, 0, 59, &minutes);
     85    if (p == nullptr) return nullptr;
     86    if (*p == ':') {
     87      p = ParseInt(p + 1, 0, 59, &seconds);
     88      if (p == nullptr) return nullptr;
     89    }
     90  }
     91  *offset = sign * ((((hours * 60) + minutes) * 60) + seconds);
     92  return p;
     93 }
     94 
     95 // datetime = ( Jn | n | Mm.w.d ) [ / offset ]
     96 const char* ParseDateTime(const char* p, PosixTransition* res) {
     97  if (p != nullptr && *p == ',') {
     98    if (*++p == 'M') {
     99      int month = 0;
    100      if ((p = ParseInt(p + 1, 1, 12, &month)) != nullptr && *p == '.') {
    101        int week = 0;
    102        if ((p = ParseInt(p + 1, 1, 5, &week)) != nullptr && *p == '.') {
    103          int weekday = 0;
    104          if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) {
    105            res->date.fmt = PosixTransition::M;
    106            res->date.m.month = static_cast<std::int_fast8_t>(month);
    107            res->date.m.week = static_cast<std::int_fast8_t>(week);
    108            res->date.m.weekday = static_cast<std::int_fast8_t>(weekday);
    109          }
    110        }
    111      }
    112    } else if (*p == 'J') {
    113      int day = 0;
    114      if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) {
    115        res->date.fmt = PosixTransition::J;
    116        res->date.j.day = static_cast<std::int_fast16_t>(day);
    117      }
    118    } else {
    119      int day = 0;
    120      if ((p = ParseInt(p, 0, 365, &day)) != nullptr) {
    121        res->date.fmt = PosixTransition::N;
    122        res->date.n.day = static_cast<std::int_fast16_t>(day);
    123      }
    124    }
    125  }
    126  if (p != nullptr) {
    127    res->time.offset = 2 * 60 * 60;  // default offset is 02:00:00
    128    if (*p == '/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset);
    129  }
    130  return p;
    131 }
    132 
    133 }  // namespace
    134 
    135 // spec = std offset [ dst [ offset ] , datetime , datetime ]
    136 bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) {
    137  const char* p = spec.c_str();
    138  if (*p == ':') return false;
    139 
    140  p = ParseAbbr(p, &res->std_abbr);
    141  p = ParseOffset(p, 0, 24, -1, &res->std_offset);
    142  if (p == nullptr) return false;
    143  if (*p == '\0') return true;
    144 
    145  p = ParseAbbr(p, &res->dst_abbr);
    146  if (p == nullptr) return false;
    147  res->dst_offset = res->std_offset + (60 * 60);  // default
    148  if (*p != ',') p = ParseOffset(p, 0, 24, -1, &res->dst_offset);
    149 
    150  p = ParseDateTime(p, &res->dst_start);
    151  p = ParseDateTime(p, &res->dst_end);
    152 
    153  return p != nullptr && *p == '\0';
    154 }
    155 
    156 }  // namespace cctz
    157 }  // namespace time_internal
    158 ABSL_NAMESPACE_END
    159 }  // namespace absl