benchmark/src/commandlineflags.cc
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14 
15 #include "commandlineflags.h"
16 
17 #include <algorithm>
18 #include <cctype>
19 #include <cstdlib>
20 #include <cstring>
21 #include <iostream>
22 #include <limits>
23 #include <map>
24 #include <utility>
25 
26 #include "../src/string_util.h"
27 
28 namespace benchmark {
29 namespace {
30 
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.
36  char* end = nullptr;
37  const long long_value = strtol(str, &end, 10); // NOLINT
38 
39  // Has strtol() consumed all characters in the string?
40  if (*end != '\0') {
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";
44  return false;
45  }
46 
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.)
53  result != long_value
54  // The parsed value overflows as an Int32.
55  ) {
56  std::cerr << src_text << " is expected to be a 32-bit integer, "
57  << "but actually has value \"" << str << "\", "
58  << "which overflows.\n";
59  return false;
60  }
61 
62  *value = result;
63  return true;
64 }
65 
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.
70  char* end = nullptr;
71  const double double_value = strtod(str, &end); // NOLINT
72 
73  // Has strtol() consumed all characters in the string?
74  if (*end != '\0') {
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";
78  return false;
79  }
80 
81  *value = double_value;
82  return true;
83 }
84 
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, '=');
92  if (kv.size() != 2) {
93  std::cerr << src_text << " is expected to be a comma-separated list of "
94  << "<key>=<value> strings, but actually has value \"" << str
95  << "\".\n";
96  return false;
97  }
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";
101  return false;
102  }
103  }
104 
105  *value = kvs;
106  return true;
107 }
108 
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);
114 
116  for (size_t i = 0; i != flag_str.length(); ++i)
117  env_var += static_cast<char>(::toupper(flag_str.c_str()[i]));
118 
119  return env_var;
120 }
121 
122 } // namespace
123 
124 bool BoolFromEnv(const char* flag, bool default_val) {
126  const char* const value_str = getenv(env_var.c_str());
127  return value_str == nullptr ? default_val : IsTruthyFlagValue(value_str);
128 }
129 
130 int32_t Int32FromEnv(const char* flag, int32_t default_val) {
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,
136  &value)) {
137  return default_val;
138  }
139  return value;
140 }
141 
142 double DoubleFromEnv(const char* flag, double default_val) {
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,
148  &value)) {
149  return default_val;
150  }
151  return value;
152 }
153 
154 const char* StringFromEnv(const char* flag, const char* default_val) {
156  const char* const value = getenv(env_var.c_str());
157  return value == nullptr ? default_val : value;
158 }
159 
160 std::map<std::string, std::string> KvPairsFromEnv(
161  const char* flag, std::map<std::string, std::string> default_val) {
163  const char* const value_str = getenv(env_var.c_str());
164 
165  if (value_str == nullptr) return default_val;
166 
167  std::map<std::string, std::string> value;
168  if (!ParseKvPairs("Environment variable " + env_var, value_str, &value)) {
169  return default_val;
170  }
171  return value;
172 }
173 
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.
177 //
178 // Returns the value of the flag, or nullptr if the parsing failed.
179 const char* ParseFlagValue(const char* str, const char* flag,
180  bool def_optional) {
181  // str and flag must not be nullptr.
182  if (str == nullptr || flag == nullptr) return nullptr;
183 
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;
188 
189  // Skips the flag name.
190  const char* flag_end = str + flag_len;
191 
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;
194 
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
197  // the flag name.
198  if (flag_end[0] != '=') return nullptr;
199 
200  // Returns the string after "=".
201  return flag_end + 1;
202 }
203 
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);
207 
208  // Aborts if the parsing failed.
209  if (value_str == nullptr) return false;
210 
211  // Converts the string value to a bool.
212  *value = IsTruthyFlagValue(value_str);
213  return true;
214 }
215 
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);
219 
220  // Aborts if the parsing failed.
221  if (value_str == nullptr) return false;
222 
223  // Sets *value to the value of the flag.
224  return ParseInt32(std::string("The value of flag --") + flag, value_str,
225  value);
226 }
227 
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);
231 
232  // Aborts if the parsing failed.
233  if (value_str == nullptr) return false;
234 
235  // Sets *value to the value of the flag.
236  return ParseDouble(std::string("The value of flag --") + flag, value_str,
237  value);
238 }
239 
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);
243 
244  // Aborts if the parsing failed.
245  if (value_str == nullptr) return false;
246 
247  *value = value_str;
248  return true;
249 }
250 
252  const char* str, const char* flag,
253  std::map<std::string, std::string>* value) {
254  const char* const value_str = ParseFlagValue(str, flag, false);
255 
256  if (value_str == nullptr) return false;
257 
258  for (const auto& kvpair : StrSplit(value_str, ',')) {
259  const auto kv = StrSplit(kvpair, '=');
260  if (kv.size() != 2) return false;
261  value->emplace(kv[0], kv[1]);
262  }
263 
264  return true;
265 }
266 
267 bool IsFlag(const char* str, const char* flag) {
268  return (ParseFlagValue(str, flag, true) != nullptr);
269 }
270 
272  if (value.size() == 1) {
273  char v = value[0];
274  return isalnum(v) &&
275  !(v == '0' || v == 'f' || v == 'F' || v == 'n' || v == 'N');
276  } else if (!value.empty()) {
277  std::string value_lower(value);
278  std::transform(value_lower.begin(), value_lower.end(), value_lower.begin(),
279  [](char c) { return static_cast<char>(::tolower(c)); });
280  return !(value_lower == "false" || value_lower == "no" ||
281  value_lower == "off");
282  } else
283  return true;
284 }
285 
286 } // end namespace benchmark
xds_interop_client.str
str
Definition: xds_interop_client.py:487
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
flag
uint32_t flag
Definition: ssl_versions.cc:162
env_var
Definition: win/process.c:40
benchmark
Definition: bm_alarm.cc:55
benchmark::Int32FromEnv
int32_t Int32FromEnv(const char *flag, int32_t default_val)
Definition: benchmark/src/commandlineflags.cc:130
benchmark::KvPairsFromEnv
std::map< std::string, std::string > KvPairsFromEnv(const char *flag, std::map< std::string, std::string > default_val)
Definition: benchmark/src/commandlineflags.cc:160
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
benchmark::ParseInt32
bool ParseInt32(const std::string &src_text, const char *str, int32_t *value)
Definition: bloaty/third_party/protobuf/third_party/benchmark/src/commandlineflags.cc:27
benchmark::BoolFromEnv
bool BoolFromEnv(const char *flag, bool default_val)
Definition: benchmark/src/commandlineflags.cc:124
benchmark::StringFromEnv
const char * StringFromEnv(const char *flag, const char *default_val)
Definition: benchmark/src/commandlineflags.cc:154
benchmark::ParseDoubleFlag
bool ParseDoubleFlag(const char *str, const char *flag, double *value)
Definition: benchmark/src/commandlineflags.cc:228
benchmark::ParseStringFlag
bool ParseStringFlag(const char *str, const char *flag, std::string *value)
Definition: benchmark/src/commandlineflags.cc:240
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
benchmark::IsTruthyFlagValue
bool IsTruthyFlagValue(const std::string &value)
Definition: benchmark/src/commandlineflags.cc:271
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
benchmark::FlagToEnvVar
static std::string FlagToEnvVar(const char *flag)
Definition: bloaty/third_party/protobuf/third_party/benchmark/src/commandlineflags.cc:81
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
min
#define min(a, b)
Definition: qsort.h:83
benchmark::ParseDouble
bool ParseDouble(const std::string &src_text, const char *str, double *value)
Definition: bloaty/third_party/protobuf/third_party/benchmark/src/commandlineflags.cc:61
value
const char * value
Definition: hpack_parser_table.cc:165
benchmark::StrSplit
std::vector< std::string > StrSplit(const std::string &str, char delim)
Definition: benchmark/src/string_util.cc:166
benchmark::ParseFlagValue
const char * ParseFlagValue(const char *str, const char *flag, bool def_optional)
Definition: benchmark/src/commandlineflags.cc:179
commandlineflags.h
benchmark::ParseBoolFlag
bool ParseBoolFlag(const char *str, const char *flag, bool *value)
Definition: benchmark/src/commandlineflags.cc:204
benchmark::DoubleFromEnv
double DoubleFromEnv(const char *flag, double default_val)
Definition: benchmark/src/commandlineflags.cc:142
benchmark::ParseKeyValueFlag
bool ParseKeyValueFlag(const char *str, const char *flag, std::map< std::string, std::string > *value)
Definition: benchmark/src/commandlineflags.cc:251
benchmark::IsFlag
bool IsFlag(const char *str, const char *flag)
Definition: benchmark/src/commandlineflags.cc:267
benchmark::ParseInt32Flag
bool ParseInt32Flag(const char *str, const char *flag, int32_t *value)
Definition: benchmark/src/commandlineflags.cc:216
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
getenv
#define getenv(ptr)
Definition: ares_private.h:106
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:51