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
]));
125 bool BoolFromEnv(const char* flag
, bool default_val
) {
126 const std::string env_var
= FlagToEnvVar(flag
);
127 const char* const value_str
= getenv(env_var
.c_str());
128 return value_str
== nullptr ? default_val
: IsTruthyFlagValue(value_str
);
132 int32_t Int32FromEnv(const char* flag
, int32_t default_val
) {
133 const std::string env_var
= FlagToEnvVar(flag
);
134 const char* const value_str
= getenv(env_var
.c_str());
135 int32_t value
= default_val
;
136 if (value_str
== nullptr ||
137 !ParseInt32(std::string("Environment variable ") + env_var
, value_str
,
145 double DoubleFromEnv(const char* flag
, double default_val
) {
146 const std::string env_var
= FlagToEnvVar(flag
);
147 const char* const value_str
= getenv(env_var
.c_str());
148 double value
= default_val
;
149 if (value_str
== nullptr ||
150 !ParseDouble(std::string("Environment variable ") + env_var
, value_str
,
158 const char* StringFromEnv(const char* flag
, const char* default_val
) {
159 const std::string env_var
= FlagToEnvVar(flag
);
160 const char* const value
= getenv(env_var
.c_str());
161 return value
== nullptr ? default_val
: value
;
165 std::map
<std::string
, std::string
> KvPairsFromEnv(
166 const char* flag
, std::map
<std::string
, std::string
> default_val
) {
167 const std::string env_var
= FlagToEnvVar(flag
);
168 const char* const value_str
= getenv(env_var
.c_str());
170 if (value_str
== nullptr) return default_val
;
172 std::map
<std::string
, std::string
> value
;
173 if (!ParseKvPairs("Environment variable " + env_var
, value_str
, &value
)) {
179 // Parses a string as a command line flag. The string should have
180 // the format "--flag=value". When def_optional is true, the "=value"
181 // part can be omitted.
183 // Returns the value of the flag, or nullptr if the parsing failed.
184 const char* ParseFlagValue(const char* str
, const char* flag
,
186 // str and flag must not be nullptr.
187 if (str
== nullptr || flag
== nullptr) return nullptr;
189 // The flag must start with "--".
190 const std::string flag_str
= std::string("--") + std::string(flag
);
191 const size_t flag_len
= flag_str
.length();
192 if (strncmp(str
, flag_str
.c_str(), flag_len
) != 0) return nullptr;
194 // Skips the flag name.
195 const char* flag_end
= str
+ flag_len
;
197 // When def_optional is true, it's OK to not have a "=value" part.
198 if (def_optional
&& (flag_end
[0] == '\0')) return flag_end
;
200 // If def_optional is true and there are more characters after the
201 // flag name, or if def_optional is false, there must be a '=' after
203 if (flag_end
[0] != '=') return nullptr;
205 // Returns the string after "=".
210 bool ParseBoolFlag(const char* str
, const char* flag
, bool* value
) {
211 // Gets the value of the flag as a string.
212 const char* const value_str
= ParseFlagValue(str
, flag
, true);
214 // Aborts if the parsing failed.
215 if (value_str
== nullptr) return false;
217 // Converts the string value to a bool.
218 *value
= IsTruthyFlagValue(value_str
);
223 bool ParseInt32Flag(const char* str
, const char* flag
, int32_t* value
) {
224 // Gets the value of the flag as a string.
225 const char* const value_str
= ParseFlagValue(str
, flag
, false);
227 // Aborts if the parsing failed.
228 if (value_str
== nullptr) return false;
230 // Sets *value to the value of the flag.
231 return ParseInt32(std::string("The value of flag --") + flag
, value_str
,
236 bool ParseDoubleFlag(const char* str
, const char* flag
, double* value
) {
237 // Gets the value of the flag as a string.
238 const char* const value_str
= ParseFlagValue(str
, flag
, false);
240 // Aborts if the parsing failed.
241 if (value_str
== nullptr) return false;
243 // Sets *value to the value of the flag.
244 return ParseDouble(std::string("The value of flag --") + flag
, value_str
,
249 bool ParseStringFlag(const char* str
, const char* flag
, std::string
* value
) {
250 // Gets the value of the flag as a string.
251 const char* const value_str
= ParseFlagValue(str
, flag
, false);
253 // Aborts if the parsing failed.
254 if (value_str
== nullptr) return false;
261 bool ParseKeyValueFlag(const char* str
, const char* flag
,
262 std::map
<std::string
, std::string
>* value
) {
263 const char* const value_str
= ParseFlagValue(str
, flag
, false);
265 if (value_str
== nullptr) return false;
267 for (const auto& kvpair
: StrSplit(value_str
, ',')) {
268 const auto kv
= StrSplit(kvpair
, '=');
269 if (kv
.size() != 2) return false;
270 value
->emplace(kv
[0], kv
[1]);
277 bool IsFlag(const char* str
, const char* flag
) {
278 return (ParseFlagValue(str
, flag
, true) != nullptr);
282 bool IsTruthyFlagValue(const std::string
& value
) {
283 if (value
.size() == 1) {
286 !(v
== '0' || v
== 'f' || v
== 'F' || v
== 'n' || v
== 'N');
288 if (!value
.empty()) {
289 std::string
value_lower(value
);
290 std::transform(value_lower
.begin(), value_lower
.end(), value_lower
.begin(),
291 [](char c
) { return static_cast<char>(::tolower(c
)); });
292 return !(value_lower
== "false" || value_lower
== "no" ||
293 value_lower
== "off");
298 } // end namespace benchmark