|
||||
File indexing completed on 2025-01-18 09:27:17
0001 // 0002 // Copyright 2019 The Abseil Authors. 0003 // 0004 // Licensed under the Apache License, Version 2.0 (the "License"); 0005 // you may not use this file except in compliance with the License. 0006 // You may obtain a copy of the License at 0007 // 0008 // https://www.apache.org/licenses/LICENSE-2.0 0009 // 0010 // Unless required by applicable law or agreed to in writing, software 0011 // distributed under the License is distributed on an "AS IS" BASIS, 0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 // See the License for the specific language governing permissions and 0014 // limitations under the License. 0015 // 0016 // ----------------------------------------------------------------------------- 0017 // File: marshalling.h 0018 // ----------------------------------------------------------------------------- 0019 // 0020 // This header file defines the API for extending Abseil flag support to 0021 // custom types, and defines the set of overloads for fundamental types. 0022 // 0023 // Out of the box, the Abseil flags library supports the following types: 0024 // 0025 // * `bool` 0026 // * `int16_t` 0027 // * `uint16_t` 0028 // * `int32_t` 0029 // * `uint32_t` 0030 // * `int64_t` 0031 // * `uint64_t` 0032 // * `float` 0033 // * `double` 0034 // * `std::string` 0035 // * `std::vector<std::string>` 0036 // * `std::optional<T>` 0037 // * `absl::LogSeverity` (provided natively for layering reasons) 0038 // 0039 // Note that support for integral types is implemented using overloads for 0040 // variable-width fundamental types (`short`, `int`, `long`, etc.). However, 0041 // you should prefer the fixed-width integral types (`int32_t`, `uint64_t`, 0042 // etc.) we've noted above within flag definitions. 0043 // 0044 // In addition, several Abseil libraries provide their own custom support for 0045 // Abseil flags. Documentation for these formats is provided in the type's 0046 // `AbslParseFlag()` definition. 0047 // 0048 // The Abseil time library provides the following support for civil time values: 0049 // 0050 // * `absl::CivilSecond` 0051 // * `absl::CivilMinute` 0052 // * `absl::CivilHour` 0053 // * `absl::CivilDay` 0054 // * `absl::CivilMonth` 0055 // * `absl::CivilYear` 0056 // 0057 // and also provides support for the following absolute time values: 0058 // 0059 // * `absl::Duration` 0060 // * `absl::Time` 0061 // 0062 // Additional support for Abseil types will be noted here as it is added. 0063 // 0064 // You can also provide your own custom flags by adding overloads for 0065 // `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See 0066 // below.) 0067 // 0068 // ----------------------------------------------------------------------------- 0069 // Optional Flags 0070 // ----------------------------------------------------------------------------- 0071 // 0072 // The Abseil flags library supports flags of type `std::optional<T>` where 0073 // `T` is a type of one of the supported flags. We refer to this flag type as 0074 // an "optional flag." An optional flag is either "valueless", holding no value 0075 // of type `T` (indicating that the flag has not been set) or a value of type 0076 // `T`. The valueless state in C++ code is represented by a value of 0077 // `std::nullopt` for the optional flag. 0078 // 0079 // Using `std::nullopt` as an optional flag's default value allows you to check 0080 // whether such a flag was ever specified on the command line: 0081 // 0082 // if (absl::GetFlag(FLAGS_foo).has_value()) { 0083 // // flag was set on command line 0084 // } else { 0085 // // flag was not passed on command line 0086 // } 0087 // 0088 // Using an optional flag in this manner avoids common workarounds for 0089 // indicating such an unset flag (such as using sentinel values to indicate this 0090 // state). 0091 // 0092 // An optional flag also allows a developer to pass a flag in an "unset" 0093 // valueless state on the command line, allowing the flag to later be set in 0094 // binary logic. An optional flag's valueless state is indicated by the special 0095 // notation of passing the value as an empty string through the syntax `--flag=` 0096 // or `--flag ""`. 0097 // 0098 // $ binary_with_optional --flag_in_unset_state= 0099 // $ binary_with_optional --flag_in_unset_state "" 0100 // 0101 // Note: as a result of the above syntax requirements, an optional flag cannot 0102 // be set to a `T` of any value which unparses to the empty string. 0103 // 0104 // ----------------------------------------------------------------------------- 0105 // Adding Type Support for Abseil Flags 0106 // ----------------------------------------------------------------------------- 0107 // 0108 // To add support for your user-defined type, add overloads of `AbslParseFlag()` 0109 // and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T` 0110 // is a class type, these functions can be friend function definitions. These 0111 // overloads must be added to the same namespace where the type is defined, so 0112 // that they can be discovered by Argument-Dependent Lookup (ADL). 0113 // 0114 // Example: 0115 // 0116 // namespace foo { 0117 // 0118 // enum OutputMode { kPlainText, kHtml }; 0119 // 0120 // // AbslParseFlag converts from a string to OutputMode. 0121 // // Must be in same namespace as OutputMode. 0122 // 0123 // // Parses an OutputMode from the command line flag value `text`. Returns 0124 // // `true` and sets `*mode` on success; returns `false` and sets `*error` 0125 // // on failure. 0126 // bool AbslParseFlag(absl::string_view text, 0127 // OutputMode* mode, 0128 // std::string* error) { 0129 // if (text == "plaintext") { 0130 // *mode = kPlainText; 0131 // return true; 0132 // } 0133 // if (text == "html") { 0134 // *mode = kHtml; 0135 // return true; 0136 // } 0137 // *error = "unknown value for enumeration"; 0138 // return false; 0139 // } 0140 // 0141 // // AbslUnparseFlag converts from an OutputMode to a string. 0142 // // Must be in same namespace as OutputMode. 0143 // 0144 // // Returns a textual flag value corresponding to the OutputMode `mode`. 0145 // std::string AbslUnparseFlag(OutputMode mode) { 0146 // switch (mode) { 0147 // case kPlainText: return "plaintext"; 0148 // case kHtml: return "html"; 0149 // } 0150 // return absl::StrCat(mode); 0151 // } 0152 // 0153 // Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class 0154 // members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads 0155 // for a type should only be declared in the same file and namespace as said 0156 // type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a 0157 // given type will be discovered via Argument-Dependent Lookup (ADL). 0158 // 0159 // `AbslParseFlag()` may need, in turn, to parse simpler constituent types 0160 // using `absl::ParseFlag()`. For example, a custom struct `MyFlagType` 0161 // consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()` 0162 // overload for its `MyFlagType` like so: 0163 // 0164 // Example: 0165 // 0166 // namespace my_flag_type { 0167 // 0168 // struct MyFlagType { 0169 // std::pair<int, std::string> my_flag_data; 0170 // }; 0171 // 0172 // bool AbslParseFlag(absl::string_view text, MyFlagType* flag, 0173 // std::string* err); 0174 // 0175 // std::string AbslUnparseFlag(const MyFlagType&); 0176 // 0177 // // Within the implementation, `AbslParseFlag()` will, in turn invoke 0178 // // `absl::ParseFlag()` on its constituent `int` and `std::string` types 0179 // // (which have built-in Abseil flag support). 0180 // 0181 // bool AbslParseFlag(absl::string_view text, MyFlagType* flag, 0182 // std::string* err) { 0183 // std::pair<absl::string_view, absl::string_view> tokens = 0184 // absl::StrSplit(text, ','); 0185 // if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err)) 0186 // return false; 0187 // if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err)) 0188 // return false; 0189 // return true; 0190 // } 0191 // 0192 // // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on 0193 // // the constituent types. 0194 // std::string AbslUnparseFlag(const MyFlagType& flag) { 0195 // return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first), 0196 // ",", 0197 // absl::UnparseFlag(flag.my_flag_data.second)); 0198 // } 0199 #ifndef ABSL_FLAGS_MARSHALLING_H_ 0200 #define ABSL_FLAGS_MARSHALLING_H_ 0201 0202 #include "absl/base/config.h" 0203 #include "absl/numeric/int128.h" 0204 0205 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL) 0206 #include <optional> 0207 #endif 0208 #include <string> 0209 #include <vector> 0210 0211 #include "absl/strings/string_view.h" 0212 #include "absl/types/optional.h" 0213 0214 namespace absl { 0215 ABSL_NAMESPACE_BEGIN 0216 0217 // Forward declaration to be used inside composable flag parse/unparse 0218 // implementations 0219 template <typename T> 0220 inline bool ParseFlag(absl::string_view input, T* dst, std::string* error); 0221 template <typename T> 0222 inline std::string UnparseFlag(const T& v); 0223 0224 namespace flags_internal { 0225 0226 // Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types. 0227 bool AbslParseFlag(absl::string_view, bool*, std::string*); 0228 bool AbslParseFlag(absl::string_view, short*, std::string*); // NOLINT 0229 bool AbslParseFlag(absl::string_view, unsigned short*, std::string*); // NOLINT 0230 bool AbslParseFlag(absl::string_view, int*, std::string*); // NOLINT 0231 bool AbslParseFlag(absl::string_view, unsigned int*, std::string*); // NOLINT 0232 bool AbslParseFlag(absl::string_view, long*, std::string*); // NOLINT 0233 bool AbslParseFlag(absl::string_view, unsigned long*, std::string*); // NOLINT 0234 bool AbslParseFlag(absl::string_view, long long*, std::string*); // NOLINT 0235 bool AbslParseFlag(absl::string_view, unsigned long long*, // NOLINT 0236 std::string*); 0237 bool AbslParseFlag(absl::string_view, absl::int128*, std::string*); // NOLINT 0238 bool AbslParseFlag(absl::string_view, absl::uint128*, std::string*); // NOLINT 0239 bool AbslParseFlag(absl::string_view, float*, std::string*); 0240 bool AbslParseFlag(absl::string_view, double*, std::string*); 0241 bool AbslParseFlag(absl::string_view, std::string*, std::string*); 0242 bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*); 0243 0244 template <typename T> 0245 bool AbslParseFlag(absl::string_view text, absl::optional<T>* f, 0246 std::string* err) { 0247 if (text.empty()) { 0248 *f = absl::nullopt; 0249 return true; 0250 } 0251 T value; 0252 if (!absl::ParseFlag(text, &value, err)) return false; 0253 0254 *f = std::move(value); 0255 return true; 0256 } 0257 0258 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL) 0259 template <typename T> 0260 bool AbslParseFlag(absl::string_view text, std::optional<T>* f, 0261 std::string* err) { 0262 if (text.empty()) { 0263 *f = std::nullopt; 0264 return true; 0265 } 0266 T value; 0267 if (!absl::ParseFlag(text, &value, err)) return false; 0268 0269 *f = std::move(value); 0270 return true; 0271 } 0272 #endif 0273 0274 template <typename T> 0275 bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { 0276 // Comment on next line provides a good compiler error message if T 0277 // does not have AbslParseFlag(absl::string_view, T*, std::string*). 0278 return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag? 0279 } 0280 0281 // Strings and std:: containers do not have the same overload resolution 0282 // considerations as fundamental types. Naming these 'AbslUnparseFlag' means we 0283 // can avoid the need for additional specializations of Unparse (below). 0284 std::string AbslUnparseFlag(absl::string_view v); 0285 std::string AbslUnparseFlag(const std::vector<std::string>&); 0286 0287 template <typename T> 0288 std::string AbslUnparseFlag(const absl::optional<T>& f) { 0289 return f.has_value() ? absl::UnparseFlag(*f) : ""; 0290 } 0291 0292 #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL) 0293 template <typename T> 0294 std::string AbslUnparseFlag(const std::optional<T>& f) { 0295 return f.has_value() ? absl::UnparseFlag(*f) : ""; 0296 } 0297 #endif 0298 0299 template <typename T> 0300 std::string Unparse(const T& v) { 0301 // Comment on next line provides a good compiler error message if T does not 0302 // have UnparseFlag. 0303 return AbslUnparseFlag(v); // Is T missing AbslUnparseFlag? 0304 } 0305 0306 // Overloads for builtin types. 0307 std::string Unparse(bool v); 0308 std::string Unparse(short v); // NOLINT 0309 std::string Unparse(unsigned short v); // NOLINT 0310 std::string Unparse(int v); // NOLINT 0311 std::string Unparse(unsigned int v); // NOLINT 0312 std::string Unparse(long v); // NOLINT 0313 std::string Unparse(unsigned long v); // NOLINT 0314 std::string Unparse(long long v); // NOLINT 0315 std::string Unparse(unsigned long long v); // NOLINT 0316 std::string Unparse(absl::int128 v); 0317 std::string Unparse(absl::uint128 v); 0318 std::string Unparse(float v); 0319 std::string Unparse(double v); 0320 0321 } // namespace flags_internal 0322 0323 // ParseFlag() 0324 // 0325 // Parses a string value into a flag value of type `T`. Do not add overloads of 0326 // this function for your type directly; instead, add an `AbslParseFlag()` 0327 // free function as documented above. 0328 // 0329 // Some implementations of `AbslParseFlag()` for types which consist of other, 0330 // constituent types which already have Abseil flag support, may need to call 0331 // `absl::ParseFlag()` on those consituent string values. (See above.) 0332 template <typename T> 0333 inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) { 0334 return flags_internal::InvokeParseFlag(input, dst, error); 0335 } 0336 0337 // UnparseFlag() 0338 // 0339 // Unparses a flag value of type `T` into a string value. Do not add overloads 0340 // of this function for your type directly; instead, add an `AbslUnparseFlag()` 0341 // free function as documented above. 0342 // 0343 // Some implementations of `AbslUnparseFlag()` for types which consist of other, 0344 // constituent types which already have Abseil flag support, may want to call 0345 // `absl::UnparseFlag()` on those constituent types. (See above.) 0346 template <typename T> 0347 inline std::string UnparseFlag(const T& v) { 0348 return flags_internal::Unparse(v); 0349 } 0350 0351 // Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's 0352 // definition because it is layered below flags. See proper documentation in 0353 // base/log_severity.h. 0354 enum class LogSeverity : int; 0355 bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*); 0356 std::string AbslUnparseFlag(absl::LogSeverity); 0357 0358 ABSL_NAMESPACE_END 0359 } // namespace absl 0360 0361 #endif // ABSL_FLAGS_MARSHALLING_H_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |