1 // Copyright 2015 Google Inc. All rights reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "commandlineflags.h"
26 #include "../src/string_util.h"
31 // Parses 'str' for a 32-bit signed integer. If successful, writes
32 // the result to *value and returns true; otherwise leaves *value
33 // unchanged and returns false.
34 bool ParseInt32(const std::string
& src_text
, const char* str
, int32_t* value
) {
35 // Parses the environment variable as a decimal integer.
37 const long long_value
= strtol(str
, &end
, 10); // NOLINT
39 // Has strtol() consumed all characters in the string?
41 // No - an invalid character was encountered.
42 std::cerr
<< src_text
<< " is expected to be a 32-bit integer, "
43 << "but actually has value \"" << str
<< "\".\n";
47 // Is the parsed value in the range of an Int32?
48 const int32_t result
= static_cast<int32_t>(long_value
);
49 if (long_value
== std::numeric_limits
<long>::max() ||
50 long_value
== std::numeric_limits
<long>::min() ||
51 // The parsed value overflows as a long. (strtol() returns
52 // LONG_MAX or LONG_MIN when the input overflows.)
54 // The parsed value overflows as an Int32.
56 std::cerr
<< src_text
<< " is expected to be a 32-bit integer, "
57 << "but actually has value \"" << str
<< "\", "
58 << "which overflows.\n";
66 // Parses 'str' for a double. If successful, writes the result to *value and
67 // returns true; otherwise leaves *value unchanged and returns false.
68 bool ParseDouble(const std::string
& src_text
, const char* str
, double* value
) {
69 // Parses the environment variable as a decimal integer.
71 const double double_value
= strtod(str
, &end
); // NOLINT
73 // Has strtol() consumed all characters in the string?
75 // No - an invalid character was encountered.
76 std::cerr
<< src_text
<< " is expected to be a double, "
77 << "but actually has value \"" << str
<< "\".\n";
81 *value
= double_value
;
85 // Parses 'str' into KV pairs. If successful, writes the result to *value and
86 // returns true; otherwise leaves *value unchanged and returns false.
87 bool ParseKvPairs(const std::string
& src_text
, const char* str
,
88 std::map
<std::string
, std::string
>* value
) {
89 std::map
<std::string
, std::string
> kvs
;
90 for (const auto& kvpair
: StrSplit(str
, ',')) {
91 const auto kv
= StrSplit(kvpair
, '=');
93 std::cerr
<< src_text
<< " is expected to be a comma-separated list of "
94 << "<key>=<value> strings, but actually has value \"" << str
98 if (!kvs
.emplace(kv
[0], kv
[1]).second
) {
99 std::cerr
<< src_text
<< " is expected to contain unique keys but key \""
100 << kv
[0] << "\" was repeated.\n";
109 // Returns the name of the environment variable corresponding to the
110 // given flag. For example, FlagToEnvVar("foo") will return
111 // "BENCHMARK_FOO" in the open-source version.
112 static std::string
FlagToEnvVar(const char* flag
) {
113 const std::string
flag_str(flag
);
116 for (size_t i
= 0; i
!= flag_str
.length(); ++i
)
117 env_var
+= static_cast<char>(::toupper(flag_str
.c_str()[i
]));
124 bool BoolFromEnv(const char* flag
, bool default_val
) {
125 const std::string env_var
= FlagToEnvVar(flag
);
126 const char* const value_str
= getenv(env_var
.c_str());
127 return value_str
== nullptr ? default_val
: IsTruthyFlagValue(value_str
);
130 int32_t Int32FromEnv(const char* flag
, int32_t default_val
) {
131 const std::string env_var
= FlagToEnvVar(flag
);
132 const char* const value_str
= getenv(env_var
.c_str());
133 int32_t value
= default_val
;
134 if (value_str
== nullptr ||
135 !ParseInt32(std::string("Environment variable ") + env_var
, value_str
,
142 double DoubleFromEnv(const char* flag
, double default_val
) {
143 const std::string env_var
= FlagToEnvVar(flag
);
144 const char* const value_str
= getenv(env_var
.c_str());
145 double value
= default_val
;
146 if (value_str
== nullptr ||
147 !ParseDouble(std::string("Environment variable ") + env_var
, value_str
,
154 const char* StringFromEnv(const char* flag
, const char* default_val
) {
155 const std::string env_var
= FlagToEnvVar(flag
);
156 const char* const value
= getenv(env_var
.c_str());
157 return value
== nullptr ? default_val
: value
;
160 std::map
<std::string
, std::string
> KvPairsFromEnv(
161 const char* flag
, std::map
<std::string
, std::string
> default_val
) {
162 const std::string env_var
= FlagToEnvVar(flag
);
163 const char* const value_str
= getenv(env_var
.c_str());
165 if (value_str
== nullptr) return default_val
;
167 std::map
<std::string
, std::string
> value
;
168 if (!ParseKvPairs("Environment variable " + env_var
, value_str
, &value
)) {
174 // Parses a string as a command line flag. The string should have
175 // the format "--flag=value". When def_optional is true, the "=value"
176 // part can be omitted.
178 // Returns the value of the flag, or nullptr if the parsing failed.
179 const char* ParseFlagValue(const char* str
, const char* flag
,
181 // str and flag must not be nullptr.
182 if (str
== nullptr || flag
== nullptr) return nullptr;
184 // The flag must start with "--".
185 const std::string flag_str
= std::string("--") + std::string(flag
);
186 const size_t flag_len
= flag_str
.length();
187 if (strncmp(str
, flag_str
.c_str(), flag_len
) != 0) return nullptr;
189 // Skips the flag name.
190 const char* flag_end
= str
+ flag_len
;
192 // When def_optional is true, it's OK to not have a "=value" part.
193 if (def_optional
&& (flag_end
[0] == '\0')) return flag_end
;
195 // If def_optional is true and there are more characters after the
196 // flag name, or if def_optional is false, there must be a '=' after
198 if (flag_end
[0] != '=') return nullptr;
200 // Returns the string after "=".
204 bool ParseBoolFlag(const char* str
, const char* flag
, bool* value
) {
205 // Gets the value of the flag as a string.
206 const char* const value_str
= ParseFlagValue(str
, flag
, true);
208 // Aborts if the parsing failed.
209 if (value_str
== nullptr) return false;
211 // Converts the string value to a bool.
212 *value
= IsTruthyFlagValue(value_str
);
216 bool ParseInt32Flag(const char* str
, const char* flag
, int32_t* value
) {
217 // Gets the value of the flag as a string.
218 const char* const value_str
= ParseFlagValue(str
, flag
, false);
220 // Aborts if the parsing failed.
221 if (value_str
== nullptr) return false;
223 // Sets *value to the value of the flag.
224 return ParseInt32(std::string("The value of flag --") + flag
, value_str
,
228 bool ParseDoubleFlag(const char* str
, const char* flag
, double* value
) {
229 // Gets the value of the flag as a string.
230 const char* const value_str
= ParseFlagValue(str
, flag
, false);
232 // Aborts if the parsing failed.
233 if (value_str
== nullptr) return false;
235 // Sets *value to the value of the flag.
236 return ParseDouble(std::string("The value of flag --") + flag
, value_str
,
240 bool ParseStringFlag(const char* str
, const char* flag
, std::string
* value
) {
241 // Gets the value of the flag as a string.
242 const char* const value_str
= ParseFlagValue(str
, flag
, false);
244 // Aborts if the parsing failed.
245 if (value_str
== nullptr) return false;
251 bool ParseKeyValueFlag(const char* str
, const char* flag
,
252 std::map
<std::string
, std::string
>* value
) {
253 const char* const value_str
= ParseFlagValue(str
, flag
, false);
255 if (value_str
== nullptr) return false;
257 for (const auto& kvpair
: StrSplit(value_str
, ',')) {
258 const auto kv
= StrSplit(kvpair
, '=');
259 if (kv
.size() != 2) return false;
260 value
->emplace(kv
[0], kv
[1]);
266 bool IsFlag(const char* str
, const char* flag
) {
267 return (ParseFlagValue(str
, flag
, true) != nullptr);
270 bool IsTruthyFlagValue(const std::string
& value
) {
271 if (value
.size() == 1) {
274 !(v
== '0' || v
== 'f' || v
== 'F' || v
== 'n' || v
== 'N');
275 } else if (!value
.empty()) {
276 std::string
value_lower(value
);
277 std::transform(value_lower
.begin(), value_lower
.end(), value_lower
.begin(),
278 [](char c
) { return static_cast<char>(::tolower(c
)); });
279 return !(value_lower
== "false" || value_lower
== "no" ||
280 value_lower
== "off");
285 } // end namespace benchmark