00001 // 00002 // Copyright 2019 The Abseil Authors. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // https://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // 00016 // ----------------------------------------------------------------------------- 00017 // File: marshalling.h 00018 // ----------------------------------------------------------------------------- 00019 // 00020 // This header file defines the API for extending Abseil flag support to 00021 // custom types, and defines the set of overloads for fundamental types. 00022 // 00023 // Out of the box, the Abseil flags library supports the following types: 00024 // 00025 // * `bool` 00026 // * `int16_t` 00027 // * `uint16_t` 00028 // * `int32_t` 00029 // * `uint32_t` 00030 // * `int64_t` 00031 // * `uint64_t` 00032 // * `float` 00033 // * `double` 00034 // * `std::string` 00035 // * `std::vector<std::string>` 00036 // 00037 // Note that support for integral types is implemented using overloads for 00038 // variable-width fundamental types (`short`, `int`, `long`, etc.). However, 00039 // you should prefer the fixed-width integral types (`int32_t`, `uint64_t`, 00040 // etc.) we've noted above within flag definitions. 00041 00042 // 00043 // In addition, several Abseil libraries provide their own custom support for 00044 // Abseil flags. 00045 // 00046 // The Abseil time library provides the following support for civil time values: 00047 // 00048 // * `absl::CivilSecond` 00049 // * `absl::CivilMinute` 00050 // * `absl::CivilHour` 00051 // * `absl::CivilDay` 00052 // * `absl::CivilMonth` 00053 // * `absl::CivilYear` 00054 // 00055 // and also provides support for the following absolute time values: 00056 // 00057 // * `absl::Duration` 00058 // * `absl::Time` 00059 // 00060 // Additional support for Abseil types will be noted here as it is added. 00061 // 00062 // You can also provide your own custom flags by adding overloads for 00063 // `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See 00064 // below.) 00065 // 00066 // ----------------------------------------------------------------------------- 00067 // Adding Type Support for Abseil Flags 00068 // ----------------------------------------------------------------------------- 00069 // 00070 // To add support for your user-defined type, add overloads of `AbslParseFlag()` 00071 // and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T` 00072 // is a class type, these functions can be friend function definitions. These 00073 // overloads must be added to the same namespace where the type is defined, so 00074 // that they can be discovered by Argument-Dependent Lookup (ADL). 00075 // 00076 // Example: 00077 // 00078 // namespace foo { 00079 // 00080 // enum OutputMode { kPlainText, kHtml }; 00081 // 00082 // // AbslParseFlag converts from a string to OutputMode. 00083 // // Must be in same namespace as OutputMode. 00084 // 00085 // // Parses an OutputMode from the command line flag value `text. Returns 00086 // // `true` and sets `*mode` on success; returns `false` and sets `*error` 00087 // // on failure. 00088 // bool AbslParseFlag(absl::string_view text, 00089 // OutputMode* mode, 00090 // std::string* error) { 00091 // if (text == "plaintext") { 00092 // *mode = kPlainText; 00093 // return true; 00094 // } 00095 // if (text == "html") { 00096 // *mode = kHtml; 00097 // return true; 00098 // } 00099 // *error = "unknown value for enumeration"; 00100 // return false; 00101 // } 00102 // 00103 // // AbslUnparseFlag converts from an OutputMode to a string. 00104 // // Must be in same namespace as OutputMode. 00105 // 00106 // // Returns a textual flag value corresponding to the OutputMode `mode`. 00107 // std::string AbslUnparseFlag(OutputMode mode) { 00108 // switch (mode) { 00109 // case kPlainText: return "plaintext"; 00110 // case kHtml: return "html"; 00111 // default: return SimpleItoa(mode); 00112 // } 00113 // } 00114 // 00115 // Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class 00116 // members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads 00117 // for a type should only be declared in the same file and namespace as said 00118 // type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a 00119 // given type will be discovered via Argument-Dependent Lookup (ADL). 00120 // 00121 // `AbslParseFlag()` may need, in turn, to parse simpler constituent types 00122 // using `absl::ParseFlag()`. For example, a custom struct `MyFlagType` 00123 // consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()` 00124 // overload for its `MyFlagType` like so: 00125 // 00126 // Example: 00127 // 00128 // namespace my_flag_type { 00129 // 00130 // struct MyFlagType { 00131 // std::pair<int, std::string> my_flag_data; 00132 // }; 00133 // 00134 // bool AbslParseFlag(absl::string_view text, MyFlagType* flag, 00135 // std::string* err); 00136 // 00137 // std::string AbslUnparseFlag(const MyFlagType&); 00138 // 00139 // // Within the implementation, `AbslParseFlag()` will, in turn invoke 00140 // // `absl::ParseFlag()` on its constituent `int` and `std::string` types 00141 // // (which have built-in Abseil flag support. 00142 // 00143 // bool AbslParseFlag(absl::string_view text, MyFlagType* flag, 00144 // std::string* err) { 00145 // std::pair<absl::string_view, absl::string_view> tokens = 00146 // absl::StrSplit(text, ','); 00147 // if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err)) 00148 // return false; 00149 // if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err)) 00150 // return false; 00151 // return true; 00152 // } 00153 // 00154 // // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on 00155 // // the constituent types. 00156 // std::string AbslUnparseFlag(const MyFlagType& flag) { 00157 // return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first), 00158 // ",", 00159 // absl::UnparseFlag(flag.my_flag_data.second)); 00160 // } 00161 #ifndef ABSL_FLAGS_MARSHALLING_H_ 00162 #define ABSL_FLAGS_MARSHALLING_H_ 00163 00164 #include <string> 00165 #include <vector> 00166 00167 #include "absl/strings/string_view.h" 00168 00169 namespace absl { 00170 namespace flags_internal { 00171 00172 // Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types. 00173 bool AbslParseFlag(absl::string_view, bool*, std::string*); 00174 bool AbslParseFlag(absl::string_view, short*, std::string*); // NOLINT 00175 bool AbslParseFlag(absl::string_view, unsigned short*, std::string*); // NOLINT 00176 bool AbslParseFlag(absl::string_view, int*, std::string*); // NOLINT 00177 bool AbslParseFlag(absl::string_view, unsigned int*, std::string*); // NOLINT 00178 bool AbslParseFlag(absl::string_view, long*, std::string*); // NOLINT 00179 bool AbslParseFlag(absl::string_view, unsigned long*, std::string*); // NOLINT 00180 bool AbslParseFlag(absl::string_view, long long*, std::string*); // NOLINT 00181 bool AbslParseFlag(absl::string_view, unsigned long long*, 00182 std::string*); // NOLINT 00183 bool AbslParseFlag(absl::string_view, float*, std::string*); 00184 bool AbslParseFlag(absl::string_view, double*, std::string*); 00185 bool AbslParseFlag(absl::string_view, std::string*, std::string*); 00186 bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*); 00187 00188 struct GlobalStringADLGuard { 00189 explicit GlobalStringADLGuard(std::string* p) : ptr(p) {} 00190 operator std::string*() { return ptr; } // NOLINT 00191 std::string* ptr; 00192 }; 00193 00194 template <typename T> 00195 bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { 00196 // Comment on next line provides a good compiler error message if T 00197 // does not have AbslParseFlag(absl::string_view, T*, std::string*). 00198 return AbslParseFlag( // Is T missing AbslParseFlag? 00199 input, dst, GlobalStringADLGuard(err)); 00200 } 00201 00202 // Strings and std:: containers do not have the same overload resolution 00203 // considerations as fundamental types. Naming these 'AbslUnparseFlag' means we 00204 // can avoid the need for additional specializations of Unparse (below). 00205 std::string AbslUnparseFlag(absl::string_view v); 00206 std::string AbslUnparseFlag(const std::vector<std::string>&); 00207 00208 template <typename T> 00209 std::string Unparse(const T& v) { 00210 // Comment on next line provides a good compiler error message if T does not 00211 // have UnparseFlag. 00212 return AbslUnparseFlag(v); // Is T missing AbslUnparseFlag? 00213 } 00214 00215 // Overloads for builtin types. 00216 std::string Unparse(bool v); 00217 std::string Unparse(short v); // NOLINT 00218 std::string Unparse(unsigned short v); // NOLINT 00219 std::string Unparse(int v); // NOLINT 00220 std::string Unparse(unsigned int v); // NOLINT 00221 std::string Unparse(long v); // NOLINT 00222 std::string Unparse(unsigned long v); // NOLINT 00223 std::string Unparse(long long v); // NOLINT 00224 std::string Unparse(unsigned long long v); // NOLINT 00225 std::string Unparse(float v); 00226 std::string Unparse(double v); 00227 00228 } // namespace flags_internal 00229 00230 // ParseFlag() 00231 // 00232 // Parses a string value into a flag value of type `T`. Do not add overloads of 00233 // this function for your type directly; instead, add an `AbslParseFlag()` 00234 // free function as documented above. 00235 // 00236 // Some implementations of `AbslParseFlag()` for types which consist of other, 00237 // constituent types which already have Abseil flag support, may need to call 00238 // `absl::ParseFlag()` on those consituent string values. (See above.) 00239 template <typename T> 00240 inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) { 00241 return flags_internal::InvokeParseFlag(input, dst, error); 00242 } 00243 00244 // UnparseFlag() 00245 // 00246 // Unparses a flag value of type `T` into a string value. Do not add overloads 00247 // of this function for your type directly; instead, add an `AbslUnparseFlag()` 00248 // free function as documented above. 00249 // 00250 // Some implementations of `AbslUnparseFlag()` for types which consist of other, 00251 // constituent types which already have Abseil flag support, may want to call 00252 // `absl::UnparseFlag()` on those constituent types. (See above.) 00253 template <typename T> 00254 inline std::string UnparseFlag(const T& v) { 00255 return flags_internal::Unparse(v); 00256 } 00257 00258 } // namespace absl 00259 00260 #endif // ABSL_FLAGS_MARSHALLING_H_