tor-browser

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

marshalling.h (13784B)


      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 // -----------------------------------------------------------------------------
     17 // File: marshalling.h
     18 // -----------------------------------------------------------------------------
     19 //
     20 // This header file defines the API for extending Abseil flag support to
     21 // custom types, and defines the set of overloads for fundamental types.
     22 //
     23 // Out of the box, the Abseil flags library supports the following types:
     24 //
     25 // * `bool`
     26 // * `int16_t`
     27 // * `uint16_t`
     28 // * `int32_t`
     29 // * `uint32_t`
     30 // * `int64_t`
     31 // * `uint64_t`
     32 // * `float`
     33 // * `double`
     34 // * `std::string`
     35 // * `std::vector<std::string>`
     36 // * `std::optional<T>`
     37 // * `absl::LogSeverity` (provided natively for layering reasons)
     38 //
     39 // Note that support for integral types is implemented using overloads for
     40 // variable-width fundamental types (`short`, `int`, `long`, etc.). However,
     41 // you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
     42 // etc.) we've noted above within flag definitions.
     43 //
     44 // In addition, several Abseil libraries provide their own custom support for
     45 // Abseil flags. Documentation for these formats is provided in the type's
     46 // `AbslParseFlag()` definition.
     47 //
     48 // The Abseil time library provides the following support for civil time values:
     49 //
     50 // * `absl::CivilSecond`
     51 // * `absl::CivilMinute`
     52 // * `absl::CivilHour`
     53 // * `absl::CivilDay`
     54 // * `absl::CivilMonth`
     55 // * `absl::CivilYear`
     56 //
     57 // and also provides support for the following absolute time values:
     58 //
     59 // * `absl::Duration`
     60 // * `absl::Time`
     61 //
     62 // Additional support for Abseil types will be noted here as it is added.
     63 //
     64 // You can also provide your own custom flags by adding overloads for
     65 // `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See
     66 // below.)
     67 //
     68 // -----------------------------------------------------------------------------
     69 // Optional Flags
     70 // -----------------------------------------------------------------------------
     71 //
     72 // The Abseil flags library supports flags of type `std::optional<T>` where
     73 // `T` is a type of one of the supported flags. We refer to this flag type as
     74 // an "optional flag." An optional flag is either "valueless", holding no value
     75 // of type `T` (indicating that the flag has not been set) or a value of type
     76 // `T`. The valueless state in C++ code is represented by a value of
     77 // `std::nullopt` for the optional flag.
     78 //
     79 // Using `std::nullopt` as an optional flag's default value allows you to check
     80 // whether such a flag was ever specified on the command line:
     81 //
     82 //   if (absl::GetFlag(FLAGS_foo).has_value()) {
     83 //     // flag was set on command line
     84 //   } else {
     85 //     // flag was not passed on command line
     86 //   }
     87 //
     88 // Using an optional flag in this manner avoids common workarounds for
     89 // indicating such an unset flag (such as using sentinel values to indicate this
     90 // state).
     91 //
     92 // An optional flag also allows a developer to pass a flag in an "unset"
     93 // valueless state on the command line, allowing the flag to later be set in
     94 // binary logic. An optional flag's valueless state is indicated by the special
     95 // notation of passing the value as an empty string through the syntax `--flag=`
     96 // or `--flag ""`.
     97 //
     98 //   $ binary_with_optional --flag_in_unset_state=
     99 //   $ binary_with_optional --flag_in_unset_state ""
    100 //
    101 // Note: as a result of the above syntax requirements, an optional flag cannot
    102 // be set to a `T` of any value which unparses to the empty string.
    103 //
    104 // -----------------------------------------------------------------------------
    105 // Adding Type Support for Abseil Flags
    106 // -----------------------------------------------------------------------------
    107 //
    108 // To add support for your user-defined type, add overloads of `AbslParseFlag()`
    109 // and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T`
    110 // is a class type, these functions can be friend function definitions. These
    111 // overloads must be added to the same namespace where the type is defined, so
    112 // that they can be discovered by Argument-Dependent Lookup (ADL).
    113 //
    114 // Example:
    115 //
    116 //   namespace foo {
    117 //
    118 //   enum OutputMode { kPlainText, kHtml };
    119 //
    120 //   // AbslParseFlag converts from a string to OutputMode.
    121 //   // Must be in same namespace as OutputMode.
    122 //
    123 //   // Parses an OutputMode from the command line flag value `text`. Returns
    124 //   // `true` and sets `*mode` on success; returns `false` and sets `*error`
    125 //   // on failure.
    126 //   bool AbslParseFlag(absl::string_view text,
    127 //                      OutputMode* mode,
    128 //                      std::string* error) {
    129 //     if (text == "plaintext") {
    130 //       *mode = kPlainText;
    131 //       return true;
    132 //     }
    133 //     if (text == "html") {
    134 //       *mode = kHtml;
    135 //      return true;
    136 //     }
    137 //     *error = "unknown value for enumeration";
    138 //     return false;
    139 //  }
    140 //
    141 //  // AbslUnparseFlag converts from an OutputMode to a string.
    142 //  // Must be in same namespace as OutputMode.
    143 //
    144 //  // Returns a textual flag value corresponding to the OutputMode `mode`.
    145 //  std::string AbslUnparseFlag(OutputMode mode) {
    146 //    switch (mode) {
    147 //      case kPlainText: return "plaintext";
    148 //      case kHtml: return "html";
    149 //    }
    150 //    return absl::StrCat(mode);
    151 //  }
    152 //
    153 // Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class
    154 // members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads
    155 // for a type should only be declared in the same file and namespace as said
    156 // type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a
    157 // given type will be discovered via Argument-Dependent Lookup (ADL).
    158 //
    159 // `AbslParseFlag()` may need, in turn, to parse simpler constituent types
    160 // using `absl::ParseFlag()`. For example, a custom struct `MyFlagType`
    161 // consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()`
    162 // overload for its `MyFlagType` like so:
    163 //
    164 // Example:
    165 //
    166 //   namespace my_flag_type {
    167 //
    168 //   struct MyFlagType {
    169 //     std::pair<int, std::string> my_flag_data;
    170 //   };
    171 //
    172 //   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
    173 //                      std::string* err);
    174 //
    175 //   std::string AbslUnparseFlag(const MyFlagType&);
    176 //
    177 //   // Within the implementation, `AbslParseFlag()` will, in turn invoke
    178 //   // `absl::ParseFlag()` on its constituent `int` and `std::string` types
    179 //   // (which have built-in Abseil flag support).
    180 //
    181 //   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
    182 //                      std::string* err) {
    183 //     std::pair<absl::string_view, absl::string_view> tokens =
    184 //         absl::StrSplit(text, ',');
    185 //     if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err))
    186 //         return false;
    187 //     if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err))
    188 //         return false;
    189 //     return true;
    190 //   }
    191 //
    192 //   // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on
    193 //   // the constituent types.
    194 //   std::string AbslUnparseFlag(const MyFlagType& flag) {
    195 //     return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first),
    196 //                         ",",
    197 //                         absl::UnparseFlag(flag.my_flag_data.second));
    198 //   }
    199 #ifndef ABSL_FLAGS_MARSHALLING_H_
    200 #define ABSL_FLAGS_MARSHALLING_H_
    201 
    202 #include "absl/base/config.h"
    203 #include "absl/numeric/int128.h"
    204 
    205 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
    206 #include <optional>
    207 #endif
    208 #include <string>
    209 #include <vector>
    210 
    211 #include "absl/strings/string_view.h"
    212 #include "absl/types/optional.h"
    213 
    214 namespace absl {
    215 ABSL_NAMESPACE_BEGIN
    216 
    217 // Forward declaration to be used inside composable flag parse/unparse
    218 // implementations
    219 template <typename T>
    220 inline bool ParseFlag(absl::string_view input, T* dst, std::string* error);
    221 template <typename T>
    222 inline std::string UnparseFlag(const T& v);
    223 
    224 namespace flags_internal {
    225 
    226 // Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.
    227 bool AbslParseFlag(absl::string_view, bool*, std::string*);
    228 bool AbslParseFlag(absl::string_view, short*, std::string*);           // NOLINT
    229 bool AbslParseFlag(absl::string_view, unsigned short*, std::string*);  // NOLINT
    230 bool AbslParseFlag(absl::string_view, int*, std::string*);             // NOLINT
    231 bool AbslParseFlag(absl::string_view, unsigned int*, std::string*);    // NOLINT
    232 bool AbslParseFlag(absl::string_view, long*, std::string*);            // NOLINT
    233 bool AbslParseFlag(absl::string_view, unsigned long*, std::string*);   // NOLINT
    234 bool AbslParseFlag(absl::string_view, long long*, std::string*);       // NOLINT
    235 bool AbslParseFlag(absl::string_view, unsigned long long*,             // NOLINT
    236                   std::string*);
    237 bool AbslParseFlag(absl::string_view, absl::int128*, std::string*);    // NOLINT
    238 bool AbslParseFlag(absl::string_view, absl::uint128*, std::string*);   // NOLINT
    239 bool AbslParseFlag(absl::string_view, float*, std::string*);
    240 bool AbslParseFlag(absl::string_view, double*, std::string*);
    241 bool AbslParseFlag(absl::string_view, std::string*, std::string*);
    242 bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*);
    243 
    244 template <typename T>
    245 bool AbslParseFlag(absl::string_view text, absl::optional<T>* f,
    246                   std::string* err) {
    247  if (text.empty()) {
    248    *f = absl::nullopt;
    249    return true;
    250  }
    251  T value;
    252  if (!absl::ParseFlag(text, &value, err)) return false;
    253 
    254  *f = std::move(value);
    255  return true;
    256 }
    257 
    258 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
    259 template <typename T>
    260 bool AbslParseFlag(absl::string_view text, std::optional<T>* f,
    261                   std::string* err) {
    262  if (text.empty()) {
    263    *f = std::nullopt;
    264    return true;
    265  }
    266  T value;
    267  if (!absl::ParseFlag(text, &value, err)) return false;
    268 
    269  *f = std::move(value);
    270  return true;
    271 }
    272 #endif
    273 
    274 template <typename T>
    275 bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) {
    276  // Comment on next line provides a good compiler error message if T
    277  // does not have AbslParseFlag(absl::string_view, T*, std::string*).
    278  return AbslParseFlag(input, dst, err);  // Is T missing AbslParseFlag?
    279 }
    280 
    281 // Strings and std:: containers do not have the same overload resolution
    282 // considerations as fundamental types. Naming these 'AbslUnparseFlag' means we
    283 // can avoid the need for additional specializations of Unparse (below).
    284 std::string AbslUnparseFlag(absl::string_view v);
    285 std::string AbslUnparseFlag(const std::vector<std::string>&);
    286 
    287 template <typename T>
    288 std::string AbslUnparseFlag(const absl::optional<T>& f) {
    289  return f.has_value() ? absl::UnparseFlag(*f) : "";
    290 }
    291 
    292 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
    293 template <typename T>
    294 std::string AbslUnparseFlag(const std::optional<T>& f) {
    295  return f.has_value() ? absl::UnparseFlag(*f) : "";
    296 }
    297 #endif
    298 
    299 template <typename T>
    300 std::string Unparse(const T& v) {
    301  // Comment on next line provides a good compiler error message if T does not
    302  // have UnparseFlag.
    303  return AbslUnparseFlag(v);  // Is T missing AbslUnparseFlag?
    304 }
    305 
    306 // Overloads for builtin types.
    307 std::string Unparse(bool v);
    308 std::string Unparse(short v);               // NOLINT
    309 std::string Unparse(unsigned short v);      // NOLINT
    310 std::string Unparse(int v);                 // NOLINT
    311 std::string Unparse(unsigned int v);        // NOLINT
    312 std::string Unparse(long v);                // NOLINT
    313 std::string Unparse(unsigned long v);       // NOLINT
    314 std::string Unparse(long long v);           // NOLINT
    315 std::string Unparse(unsigned long long v);  // NOLINT
    316 std::string Unparse(absl::int128 v);
    317 std::string Unparse(absl::uint128 v);
    318 std::string Unparse(float v);
    319 std::string Unparse(double v);
    320 
    321 }  // namespace flags_internal
    322 
    323 // ParseFlag()
    324 //
    325 // Parses a string value into a flag value of type `T`. Do not add overloads of
    326 // this function for your type directly; instead, add an `AbslParseFlag()`
    327 // free function as documented above.
    328 //
    329 // Some implementations of `AbslParseFlag()` for types which consist of other,
    330 // constituent types which already have Abseil flag support, may need to call
    331 // `absl::ParseFlag()` on those consituent string values. (See above.)
    332 template <typename T>
    333 inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) {
    334  return flags_internal::InvokeParseFlag(input, dst, error);
    335 }
    336 
    337 // UnparseFlag()
    338 //
    339 // Unparses a flag value of type `T` into a string value. Do not add overloads
    340 // of this function for your type directly; instead, add an `AbslUnparseFlag()`
    341 // free function as documented above.
    342 //
    343 // Some implementations of `AbslUnparseFlag()` for types which consist of other,
    344 // constituent types which already have Abseil flag support, may want to call
    345 // `absl::UnparseFlag()` on those constituent types. (See above.)
    346 template <typename T>
    347 inline std::string UnparseFlag(const T& v) {
    348  return flags_internal::Unparse(v);
    349 }
    350 
    351 // Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's
    352 // definition because it is layered below flags.  See proper documentation in
    353 // base/log_severity.h.
    354 enum class LogSeverity : int;
    355 bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*);
    356 std::string AbslUnparseFlag(absl::LogSeverity);
    357 
    358 ABSL_NAMESPACE_END
    359 }  // namespace absl
    360 
    361 #endif  // ABSL_FLAGS_MARSHALLING_H_