1cb93a386Sopenharmony_ci// 2cb93a386Sopenharmony_ci// Copyright 2019 The Abseil Authors. 3cb93a386Sopenharmony_ci// 4cb93a386Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 5cb93a386Sopenharmony_ci// you may not use this file except in compliance with the License. 6cb93a386Sopenharmony_ci// You may obtain a copy of the License at 7cb93a386Sopenharmony_ci// 8cb93a386Sopenharmony_ci// https://www.apache.org/licenses/LICENSE-2.0 9cb93a386Sopenharmony_ci// 10cb93a386Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 11cb93a386Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 12cb93a386Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cb93a386Sopenharmony_ci// See the License for the specific language governing permissions and 14cb93a386Sopenharmony_ci// limitations under the License. 15cb93a386Sopenharmony_ci// 16cb93a386Sopenharmony_ci// ----------------------------------------------------------------------------- 17cb93a386Sopenharmony_ci// File: marshalling.h 18cb93a386Sopenharmony_ci// ----------------------------------------------------------------------------- 19cb93a386Sopenharmony_ci// 20cb93a386Sopenharmony_ci// This header file defines the API for extending Abseil flag support to 21cb93a386Sopenharmony_ci// custom types, and defines the set of overloads for fundamental types. 22cb93a386Sopenharmony_ci// 23cb93a386Sopenharmony_ci// Out of the box, the Abseil flags library supports the following types: 24cb93a386Sopenharmony_ci// 25cb93a386Sopenharmony_ci// * `bool` 26cb93a386Sopenharmony_ci// * `int16_t` 27cb93a386Sopenharmony_ci// * `uint16_t` 28cb93a386Sopenharmony_ci// * `int32_t` 29cb93a386Sopenharmony_ci// * `uint32_t` 30cb93a386Sopenharmony_ci// * `int64_t` 31cb93a386Sopenharmony_ci// * `uint64_t` 32cb93a386Sopenharmony_ci// * `float` 33cb93a386Sopenharmony_ci// * `double` 34cb93a386Sopenharmony_ci// * `std::string` 35cb93a386Sopenharmony_ci// * `std::vector<std::string>` 36cb93a386Sopenharmony_ci// * `absl::LogSeverity` (provided natively for layering reasons) 37cb93a386Sopenharmony_ci// 38cb93a386Sopenharmony_ci// Note that support for integral types is implemented using overloads for 39cb93a386Sopenharmony_ci// variable-width fundamental types (`short`, `int`, `long`, etc.). However, 40cb93a386Sopenharmony_ci// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`, 41cb93a386Sopenharmony_ci// etc.) we've noted above within flag definitions. 42cb93a386Sopenharmony_ci// 43cb93a386Sopenharmony_ci// In addition, several Abseil libraries provide their own custom support for 44cb93a386Sopenharmony_ci// Abseil flags. Documentation for these formats is provided in the type's 45cb93a386Sopenharmony_ci// `AbslParseFlag()` definition. 46cb93a386Sopenharmony_ci// 47cb93a386Sopenharmony_ci// The Abseil time library provides the following support for civil time values: 48cb93a386Sopenharmony_ci// 49cb93a386Sopenharmony_ci// * `absl::CivilSecond` 50cb93a386Sopenharmony_ci// * `absl::CivilMinute` 51cb93a386Sopenharmony_ci// * `absl::CivilHour` 52cb93a386Sopenharmony_ci// * `absl::CivilDay` 53cb93a386Sopenharmony_ci// * `absl::CivilMonth` 54cb93a386Sopenharmony_ci// * `absl::CivilYear` 55cb93a386Sopenharmony_ci// 56cb93a386Sopenharmony_ci// and also provides support for the following absolute time values: 57cb93a386Sopenharmony_ci// 58cb93a386Sopenharmony_ci// * `absl::Duration` 59cb93a386Sopenharmony_ci// * `absl::Time` 60cb93a386Sopenharmony_ci// 61cb93a386Sopenharmony_ci// Additional support for Abseil types will be noted here as it is added. 62cb93a386Sopenharmony_ci// 63cb93a386Sopenharmony_ci// You can also provide your own custom flags by adding overloads for 64cb93a386Sopenharmony_ci// `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See 65cb93a386Sopenharmony_ci// below.) 66cb93a386Sopenharmony_ci// 67cb93a386Sopenharmony_ci// ----------------------------------------------------------------------------- 68cb93a386Sopenharmony_ci// Adding Type Support for Abseil Flags 69cb93a386Sopenharmony_ci// ----------------------------------------------------------------------------- 70cb93a386Sopenharmony_ci// 71cb93a386Sopenharmony_ci// To add support for your user-defined type, add overloads of `AbslParseFlag()` 72cb93a386Sopenharmony_ci// and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T` 73cb93a386Sopenharmony_ci// is a class type, these functions can be friend function definitions. These 74cb93a386Sopenharmony_ci// overloads must be added to the same namespace where the type is defined, so 75cb93a386Sopenharmony_ci// that they can be discovered by Argument-Dependent Lookup (ADL). 76cb93a386Sopenharmony_ci// 77cb93a386Sopenharmony_ci// Example: 78cb93a386Sopenharmony_ci// 79cb93a386Sopenharmony_ci// namespace foo { 80cb93a386Sopenharmony_ci// 81cb93a386Sopenharmony_ci// enum OutputMode { kPlainText, kHtml }; 82cb93a386Sopenharmony_ci// 83cb93a386Sopenharmony_ci// // AbslParseFlag converts from a string to OutputMode. 84cb93a386Sopenharmony_ci// // Must be in same namespace as OutputMode. 85cb93a386Sopenharmony_ci// 86cb93a386Sopenharmony_ci// // Parses an OutputMode from the command line flag value `text`. Returns 87cb93a386Sopenharmony_ci// // `true` and sets `*mode` on success; returns `false` and sets `*error` 88cb93a386Sopenharmony_ci// // on failure. 89cb93a386Sopenharmony_ci// bool AbslParseFlag(absl::string_view text, 90cb93a386Sopenharmony_ci// OutputMode* mode, 91cb93a386Sopenharmony_ci// std::string* error) { 92cb93a386Sopenharmony_ci// if (text == "plaintext") { 93cb93a386Sopenharmony_ci// *mode = kPlainText; 94cb93a386Sopenharmony_ci// return true; 95cb93a386Sopenharmony_ci// } 96cb93a386Sopenharmony_ci// if (text == "html") { 97cb93a386Sopenharmony_ci// *mode = kHtml; 98cb93a386Sopenharmony_ci// return true; 99cb93a386Sopenharmony_ci// } 100cb93a386Sopenharmony_ci// *error = "unknown value for enumeration"; 101cb93a386Sopenharmony_ci// return false; 102cb93a386Sopenharmony_ci// } 103cb93a386Sopenharmony_ci// 104cb93a386Sopenharmony_ci// // AbslUnparseFlag converts from an OutputMode to a string. 105cb93a386Sopenharmony_ci// // Must be in same namespace as OutputMode. 106cb93a386Sopenharmony_ci// 107cb93a386Sopenharmony_ci// // Returns a textual flag value corresponding to the OutputMode `mode`. 108cb93a386Sopenharmony_ci// std::string AbslUnparseFlag(OutputMode mode) { 109cb93a386Sopenharmony_ci// switch (mode) { 110cb93a386Sopenharmony_ci// case kPlainText: return "plaintext"; 111cb93a386Sopenharmony_ci// case kHtml: return "html"; 112cb93a386Sopenharmony_ci// } 113cb93a386Sopenharmony_ci// return absl::StrCat(mode); 114cb93a386Sopenharmony_ci// } 115cb93a386Sopenharmony_ci// 116cb93a386Sopenharmony_ci// Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class 117cb93a386Sopenharmony_ci// members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads 118cb93a386Sopenharmony_ci// for a type should only be declared in the same file and namespace as said 119cb93a386Sopenharmony_ci// type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a 120cb93a386Sopenharmony_ci// given type will be discovered via Argument-Dependent Lookup (ADL). 121cb93a386Sopenharmony_ci// 122cb93a386Sopenharmony_ci// `AbslParseFlag()` may need, in turn, to parse simpler constituent types 123cb93a386Sopenharmony_ci// using `absl::ParseFlag()`. For example, a custom struct `MyFlagType` 124cb93a386Sopenharmony_ci// consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()` 125cb93a386Sopenharmony_ci// overload for its `MyFlagType` like so: 126cb93a386Sopenharmony_ci// 127cb93a386Sopenharmony_ci// Example: 128cb93a386Sopenharmony_ci// 129cb93a386Sopenharmony_ci// namespace my_flag_type { 130cb93a386Sopenharmony_ci// 131cb93a386Sopenharmony_ci// struct MyFlagType { 132cb93a386Sopenharmony_ci// std::pair<int, std::string> my_flag_data; 133cb93a386Sopenharmony_ci// }; 134cb93a386Sopenharmony_ci// 135cb93a386Sopenharmony_ci// bool AbslParseFlag(absl::string_view text, MyFlagType* flag, 136cb93a386Sopenharmony_ci// std::string* err); 137cb93a386Sopenharmony_ci// 138cb93a386Sopenharmony_ci// std::string AbslUnparseFlag(const MyFlagType&); 139cb93a386Sopenharmony_ci// 140cb93a386Sopenharmony_ci// // Within the implementation, `AbslParseFlag()` will, in turn invoke 141cb93a386Sopenharmony_ci// // `absl::ParseFlag()` on its constituent `int` and `std::string` types 142cb93a386Sopenharmony_ci// // (which have built-in Abseil flag support). 143cb93a386Sopenharmony_ci// 144cb93a386Sopenharmony_ci// bool AbslParseFlag(absl::string_view text, MyFlagType* flag, 145cb93a386Sopenharmony_ci// std::string* err) { 146cb93a386Sopenharmony_ci// std::pair<absl::string_view, absl::string_view> tokens = 147cb93a386Sopenharmony_ci// absl::StrSplit(text, ','); 148cb93a386Sopenharmony_ci// if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err)) 149cb93a386Sopenharmony_ci// return false; 150cb93a386Sopenharmony_ci// if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err)) 151cb93a386Sopenharmony_ci// return false; 152cb93a386Sopenharmony_ci// return true; 153cb93a386Sopenharmony_ci// } 154cb93a386Sopenharmony_ci// 155cb93a386Sopenharmony_ci// // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on 156cb93a386Sopenharmony_ci// // the constituent types. 157cb93a386Sopenharmony_ci// std::string AbslUnparseFlag(const MyFlagType& flag) { 158cb93a386Sopenharmony_ci// return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first), 159cb93a386Sopenharmony_ci// ",", 160cb93a386Sopenharmony_ci// absl::UnparseFlag(flag.my_flag_data.second)); 161cb93a386Sopenharmony_ci// } 162cb93a386Sopenharmony_ci#ifndef ABSL_FLAGS_MARSHALLING_H_ 163cb93a386Sopenharmony_ci#define ABSL_FLAGS_MARSHALLING_H_ 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci#include <string> 166cb93a386Sopenharmony_ci#include <vector> 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci#include "absl/base/config.h" 169cb93a386Sopenharmony_ci#include "absl/strings/string_view.h" 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_cinamespace absl { 172cb93a386Sopenharmony_ciABSL_NAMESPACE_BEGIN 173cb93a386Sopenharmony_cinamespace flags_internal { 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci// Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types. 176cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, bool*, std::string*); 177cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, short*, std::string*); // NOLINT 178cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, unsigned short*, std::string*); // NOLINT 179cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, int*, std::string*); // NOLINT 180cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, unsigned int*, std::string*); // NOLINT 181cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, long*, std::string*); // NOLINT 182cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, unsigned long*, std::string*); // NOLINT 183cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, long long*, std::string*); // NOLINT 184cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, unsigned long long*, // NOLINT 185cb93a386Sopenharmony_ci std::string*); 186cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, float*, std::string*); 187cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, double*, std::string*); 188cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, std::string*, std::string*); 189cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*); 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_citemplate <typename T> 192cb93a386Sopenharmony_cibool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { 193cb93a386Sopenharmony_ci // Comment on next line provides a good compiler error message if T 194cb93a386Sopenharmony_ci // does not have AbslParseFlag(absl::string_view, T*, std::string*). 195cb93a386Sopenharmony_ci return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag? 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci// Strings and std:: containers do not have the same overload resolution 199cb93a386Sopenharmony_ci// considerations as fundamental types. Naming these 'AbslUnparseFlag' means we 200cb93a386Sopenharmony_ci// can avoid the need for additional specializations of Unparse (below). 201cb93a386Sopenharmony_cistd::string AbslUnparseFlag(absl::string_view v); 202cb93a386Sopenharmony_cistd::string AbslUnparseFlag(const std::vector<std::string>&); 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_citemplate <typename T> 205cb93a386Sopenharmony_cistd::string Unparse(const T& v) { 206cb93a386Sopenharmony_ci // Comment on next line provides a good compiler error message if T does not 207cb93a386Sopenharmony_ci // have UnparseFlag. 208cb93a386Sopenharmony_ci return AbslUnparseFlag(v); // Is T missing AbslUnparseFlag? 209cb93a386Sopenharmony_ci} 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci// Overloads for builtin types. 212cb93a386Sopenharmony_cistd::string Unparse(bool v); 213cb93a386Sopenharmony_cistd::string Unparse(short v); // NOLINT 214cb93a386Sopenharmony_cistd::string Unparse(unsigned short v); // NOLINT 215cb93a386Sopenharmony_cistd::string Unparse(int v); // NOLINT 216cb93a386Sopenharmony_cistd::string Unparse(unsigned int v); // NOLINT 217cb93a386Sopenharmony_cistd::string Unparse(long v); // NOLINT 218cb93a386Sopenharmony_cistd::string Unparse(unsigned long v); // NOLINT 219cb93a386Sopenharmony_cistd::string Unparse(long long v); // NOLINT 220cb93a386Sopenharmony_cistd::string Unparse(unsigned long long v); // NOLINT 221cb93a386Sopenharmony_cistd::string Unparse(float v); 222cb93a386Sopenharmony_cistd::string Unparse(double v); 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci} // namespace flags_internal 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci// ParseFlag() 227cb93a386Sopenharmony_ci// 228cb93a386Sopenharmony_ci// Parses a string value into a flag value of type `T`. Do not add overloads of 229cb93a386Sopenharmony_ci// this function for your type directly; instead, add an `AbslParseFlag()` 230cb93a386Sopenharmony_ci// free function as documented above. 231cb93a386Sopenharmony_ci// 232cb93a386Sopenharmony_ci// Some implementations of `AbslParseFlag()` for types which consist of other, 233cb93a386Sopenharmony_ci// constituent types which already have Abseil flag support, may need to call 234cb93a386Sopenharmony_ci// `absl::ParseFlag()` on those consituent string values. (See above.) 235cb93a386Sopenharmony_citemplate <typename T> 236cb93a386Sopenharmony_ciinline bool ParseFlag(absl::string_view input, T* dst, std::string* error) { 237cb93a386Sopenharmony_ci return flags_internal::InvokeParseFlag(input, dst, error); 238cb93a386Sopenharmony_ci} 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ci// UnparseFlag() 241cb93a386Sopenharmony_ci// 242cb93a386Sopenharmony_ci// Unparses a flag value of type `T` into a string value. Do not add overloads 243cb93a386Sopenharmony_ci// of this function for your type directly; instead, add an `AbslUnparseFlag()` 244cb93a386Sopenharmony_ci// free function as documented above. 245cb93a386Sopenharmony_ci// 246cb93a386Sopenharmony_ci// Some implementations of `AbslUnparseFlag()` for types which consist of other, 247cb93a386Sopenharmony_ci// constituent types which already have Abseil flag support, may want to call 248cb93a386Sopenharmony_ci// `absl::UnparseFlag()` on those constituent types. (See above.) 249cb93a386Sopenharmony_citemplate <typename T> 250cb93a386Sopenharmony_ciinline std::string UnparseFlag(const T& v) { 251cb93a386Sopenharmony_ci return flags_internal::Unparse(v); 252cb93a386Sopenharmony_ci} 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci// Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's 255cb93a386Sopenharmony_ci// definition because it is layered below flags. See proper documentation in 256cb93a386Sopenharmony_ci// base/log_severity.h. 257cb93a386Sopenharmony_cienum class LogSeverity : int; 258cb93a386Sopenharmony_cibool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*); 259cb93a386Sopenharmony_cistd::string AbslUnparseFlag(absl::LogSeverity); 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_ciABSL_NAMESPACE_END 262cb93a386Sopenharmony_ci} // namespace absl 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci#endif // ABSL_FLAGS_MARSHALLING_H_ 265