tor-browser

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

marshalling.cc (9372B)


      1 //
      2 //  Copyright 2019 The Abseil Authors.
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      https://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 
     16 #include "absl/flags/marshalling.h"
     17 
     18 #include <stddef.h>
     19 
     20 #include <cmath>
     21 #include <limits>
     22 #include <sstream>
     23 #include <string>
     24 #include <type_traits>
     25 #include <vector>
     26 
     27 #include "absl/base/config.h"
     28 #include "absl/base/log_severity.h"
     29 #include "absl/base/macros.h"
     30 #include "absl/numeric/int128.h"
     31 #include "absl/strings/ascii.h"
     32 #include "absl/strings/match.h"
     33 #include "absl/strings/numbers.h"
     34 #include "absl/strings/str_cat.h"
     35 #include "absl/strings/str_format.h"
     36 #include "absl/strings/str_join.h"
     37 #include "absl/strings/str_split.h"
     38 #include "absl/strings/string_view.h"
     39 
     40 namespace absl {
     41 ABSL_NAMESPACE_BEGIN
     42 namespace flags_internal {
     43 
     44 // --------------------------------------------------------------------
     45 // AbslParseFlag specializations for boolean type.
     46 
     47 bool AbslParseFlag(absl::string_view text, bool* dst, std::string*) {
     48  const char* kTrue[] = {"1", "t", "true", "y", "yes"};
     49  const char* kFalse[] = {"0", "f", "false", "n", "no"};
     50  static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
     51 
     52  text = absl::StripAsciiWhitespace(text);
     53 
     54  for (size_t i = 0; i < ABSL_ARRAYSIZE(kTrue); ++i) {
     55    if (absl::EqualsIgnoreCase(text, kTrue[i])) {
     56      *dst = true;
     57      return true;
     58    } else if (absl::EqualsIgnoreCase(text, kFalse[i])) {
     59      *dst = false;
     60      return true;
     61    }
     62  }
     63  return false;  // didn't match a legal input
     64 }
     65 
     66 // --------------------------------------------------------------------
     67 // AbslParseFlag for integral types.
     68 
     69 // Return the base to use for parsing text as an integer.  Leading 0x
     70 // puts us in base 16.  But leading 0 does not put us in base 8. It
     71 // caused too many bugs when we had that behavior.
     72 static int NumericBase(absl::string_view text) {
     73  if (text.empty()) return 0;
     74  size_t num_start = (text[0] == '-' || text[0] == '+') ? 1 : 0;
     75  const bool hex = (text.size() >= num_start + 2 && text[num_start] == '0' &&
     76                    (text[num_start + 1] == 'x' || text[num_start + 1] == 'X'));
     77  return hex ? 16 : 10;
     78 }
     79 
     80 template <typename IntType>
     81 inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
     82  text = absl::StripAsciiWhitespace(text);
     83 
     84  return absl::numbers_internal::safe_strtoi_base(text, &dst,
     85                                                  NumericBase(text));
     86 }
     87 
     88 bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
     89  int val;
     90  if (!ParseFlagImpl(text, val)) return false;
     91  if (static_cast<short>(val) != val)  // worked, but number out of range
     92    return false;
     93  *dst = static_cast<short>(val);
     94  return true;
     95 }
     96 
     97 bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
     98  unsigned int val;
     99  if (!ParseFlagImpl(text, val)) return false;
    100  if (static_cast<unsigned short>(val) !=
    101      val)  // worked, but number out of range
    102    return false;
    103  *dst = static_cast<unsigned short>(val);
    104  return true;
    105 }
    106 
    107 bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
    108  return ParseFlagImpl(text, *dst);
    109 }
    110 
    111 bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
    112  return ParseFlagImpl(text, *dst);
    113 }
    114 
    115 bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
    116  return ParseFlagImpl(text, *dst);
    117 }
    118 
    119 bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
    120  return ParseFlagImpl(text, *dst);
    121 }
    122 
    123 bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
    124  return ParseFlagImpl(text, *dst);
    125 }
    126 
    127 bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
    128                   std::string*) {
    129  return ParseFlagImpl(text, *dst);
    130 }
    131 
    132 bool AbslParseFlag(absl::string_view text, absl::int128* dst, std::string*) {
    133  text = absl::StripAsciiWhitespace(text);
    134 
    135  // check hex
    136  int base = NumericBase(text);
    137  if (!absl::numbers_internal::safe_strto128_base(text, dst, base)) {
    138    return false;
    139  }
    140 
    141  return base == 16 ? absl::SimpleHexAtoi(text, dst)
    142                    : absl::SimpleAtoi(text, dst);
    143 }
    144 
    145 bool AbslParseFlag(absl::string_view text, absl::uint128* dst, std::string*) {
    146  text = absl::StripAsciiWhitespace(text);
    147 
    148  // check hex
    149  int base = NumericBase(text);
    150  if (!absl::numbers_internal::safe_strtou128_base(text, dst, base)) {
    151    return false;
    152  }
    153 
    154  return base == 16 ? absl::SimpleHexAtoi(text, dst)
    155                    : absl::SimpleAtoi(text, dst);
    156 }
    157 
    158 // --------------------------------------------------------------------
    159 // AbslParseFlag for floating point types.
    160 
    161 bool AbslParseFlag(absl::string_view text, float* dst, std::string*) {
    162  return absl::SimpleAtof(text, dst);
    163 }
    164 
    165 bool AbslParseFlag(absl::string_view text, double* dst, std::string*) {
    166  return absl::SimpleAtod(text, dst);
    167 }
    168 
    169 // --------------------------------------------------------------------
    170 // AbslParseFlag for strings.
    171 
    172 bool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) {
    173  dst->assign(text.data(), text.size());
    174  return true;
    175 }
    176 
    177 // --------------------------------------------------------------------
    178 // AbslParseFlag for vector of strings.
    179 
    180 bool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst,
    181                   std::string*) {
    182  // An empty flag value corresponds to an empty vector, not a vector
    183  // with a single, empty std::string.
    184  if (text.empty()) {
    185    dst->clear();
    186    return true;
    187  }
    188  *dst = absl::StrSplit(text, ',', absl::AllowEmpty());
    189  return true;
    190 }
    191 
    192 // --------------------------------------------------------------------
    193 // AbslUnparseFlag specializations for various builtin flag types.
    194 
    195 std::string Unparse(bool v) { return v ? "true" : "false"; }
    196 std::string Unparse(short v) { return absl::StrCat(v); }
    197 std::string Unparse(unsigned short v) { return absl::StrCat(v); }
    198 std::string Unparse(int v) { return absl::StrCat(v); }
    199 std::string Unparse(unsigned int v) { return absl::StrCat(v); }
    200 std::string Unparse(long v) { return absl::StrCat(v); }
    201 std::string Unparse(unsigned long v) { return absl::StrCat(v); }
    202 std::string Unparse(long long v) { return absl::StrCat(v); }
    203 std::string Unparse(unsigned long long v) { return absl::StrCat(v); }
    204 std::string Unparse(absl::int128 v) {
    205  std::stringstream ss;
    206  ss << v;
    207  return ss.str();
    208 }
    209 std::string Unparse(absl::uint128 v) {
    210  std::stringstream ss;
    211  ss << v;
    212  return ss.str();
    213 }
    214 
    215 template <typename T>
    216 std::string UnparseFloatingPointVal(T v) {
    217  // digits10 is guaranteed to roundtrip correctly in string -> value -> string
    218  // conversions, but may not be enough to represent all the values correctly.
    219  std::string digit10_str =
    220      absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v);
    221  if (std::isnan(v) || std::isinf(v)) return digit10_str;
    222 
    223  T roundtrip_val = 0;
    224  std::string err;
    225  if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) &&
    226      roundtrip_val == v) {
    227    return digit10_str;
    228  }
    229 
    230  // max_digits10 is the number of base-10 digits that are necessary to uniquely
    231  // represent all distinct values.
    232  return absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v);
    233 }
    234 std::string Unparse(float v) { return UnparseFloatingPointVal(v); }
    235 std::string Unparse(double v) { return UnparseFloatingPointVal(v); }
    236 std::string AbslUnparseFlag(absl::string_view v) { return std::string(v); }
    237 std::string AbslUnparseFlag(const std::vector<std::string>& v) {
    238  return absl::StrJoin(v, ",");
    239 }
    240 
    241 }  // namespace flags_internal
    242 
    243 bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst,
    244                   std::string* err) {
    245  text = absl::StripAsciiWhitespace(text);
    246  if (text.empty()) {
    247    *err = "no value provided";
    248    return false;
    249  }
    250  if (absl::EqualsIgnoreCase(text, "dfatal")) {
    251    *dst = absl::kLogDebugFatal;
    252    return true;
    253  }
    254  if (absl::EqualsIgnoreCase(text, "klogdebugfatal")) {
    255    *dst = absl::kLogDebugFatal;
    256    return true;
    257  }
    258  if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1);
    259  if (absl::EqualsIgnoreCase(text, "info")) {
    260    *dst = absl::LogSeverity::kInfo;
    261    return true;
    262  }
    263  if (absl::EqualsIgnoreCase(text, "warning")) {
    264    *dst = absl::LogSeverity::kWarning;
    265    return true;
    266  }
    267  if (absl::EqualsIgnoreCase(text, "error")) {
    268    *dst = absl::LogSeverity::kError;
    269    return true;
    270  }
    271  if (absl::EqualsIgnoreCase(text, "fatal")) {
    272    *dst = absl::LogSeverity::kFatal;
    273    return true;
    274  }
    275  std::underlying_type<absl::LogSeverity>::type numeric_value;
    276  if (absl::ParseFlag(text, &numeric_value, err)) {
    277    *dst = static_cast<absl::LogSeverity>(numeric_value);
    278    return true;
    279  }
    280  *err =
    281      "only integers, absl::LogSeverity enumerators, and DFATAL are accepted";
    282  return false;
    283 }
    284 
    285 std::string AbslUnparseFlag(absl::LogSeverity v) {
    286  if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v);
    287  return absl::UnparseFlag(static_cast<int>(v));
    288 }
    289 
    290 ABSL_NAMESPACE_END
    291 }  // namespace absl