aboutsummaryrefslogtreecommitdiff
path: root/src/commandlineflags.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/commandlineflags.cc')
-rw-r--r--src/commandlineflags.cc76
1 files changed, 73 insertions, 3 deletions
diff --git a/src/commandlineflags.cc b/src/commandlineflags.cc
index 0648fe3..dcb4149 100644
--- a/src/commandlineflags.cc
+++ b/src/commandlineflags.cc
@@ -20,6 +20,10 @@
#include <cstring>
#include <iostream>
#include <limits>
+#include <map>
+#include <utility>
+
+#include "../src/string_util.h"
namespace benchmark {
namespace {
@@ -78,6 +82,30 @@ bool ParseDouble(const std::string& src_text, const char* str, double* value) {
return true;
}
+// Parses 'str' into KV pairs. If successful, writes the result to *value and
+// returns true; otherwise leaves *value unchanged and returns false.
+bool ParseKvPairs(const std::string& src_text, const char* str,
+ std::map<std::string, std::string>* value) {
+ std::map<std::string, std::string> kvs;
+ for (const auto& kvpair : StrSplit(str, ',')) {
+ const auto kv = StrSplit(kvpair, '=');
+ if (kv.size() != 2) {
+ std::cerr << src_text << " is expected to be a comma-separated list of "
+ << "<key>=<value> strings, but actually has value \"" << str
+ << "\".\n";
+ return false;
+ }
+ if (!kvs.emplace(kv[0], kv[1]).second) {
+ std::cerr << src_text << " is expected to contain unique keys but key \""
+ << kv[0] << "\" was repeated.\n";
+ return false;
+ }
+ }
+
+ *value = kvs;
+ return true;
+}
+
// Returns the name of the environment variable corresponding to the
// given flag. For example, FlagToEnvVar("foo") will return
// "BENCHMARK_FOO" in the open-source version.
@@ -93,12 +121,14 @@ static std::string FlagToEnvVar(const char* flag) {
} // namespace
+BENCHMARK_EXPORT
bool BoolFromEnv(const char* flag, bool default_val) {
const std::string env_var = FlagToEnvVar(flag);
const char* const value_str = getenv(env_var.c_str());
return value_str == nullptr ? default_val : IsTruthyFlagValue(value_str);
}
+BENCHMARK_EXPORT
int32_t Int32FromEnv(const char* flag, int32_t default_val) {
const std::string env_var = FlagToEnvVar(flag);
const char* const value_str = getenv(env_var.c_str());
@@ -111,6 +141,7 @@ int32_t Int32FromEnv(const char* flag, int32_t default_val) {
return value;
}
+BENCHMARK_EXPORT
double DoubleFromEnv(const char* flag, double default_val) {
const std::string env_var = FlagToEnvVar(flag);
const char* const value_str = getenv(env_var.c_str());
@@ -123,12 +154,28 @@ double DoubleFromEnv(const char* flag, double default_val) {
return value;
}
+BENCHMARK_EXPORT
const char* StringFromEnv(const char* flag, const char* default_val) {
const std::string env_var = FlagToEnvVar(flag);
const char* const value = getenv(env_var.c_str());
return value == nullptr ? default_val : value;
}
+BENCHMARK_EXPORT
+std::map<std::string, std::string> KvPairsFromEnv(
+ const char* flag, std::map<std::string, std::string> default_val) {
+ const std::string env_var = FlagToEnvVar(flag);
+ const char* const value_str = getenv(env_var.c_str());
+
+ if (value_str == nullptr) return default_val;
+
+ std::map<std::string, std::string> value;
+ if (!ParseKvPairs("Environment variable " + env_var, value_str, &value)) {
+ return default_val;
+ }
+ return value;
+}
+
// Parses a string as a command line flag. The string should have
// the format "--flag=value". When def_optional is true, the "=value"
// part can be omitted.
@@ -159,6 +206,7 @@ const char* ParseFlagValue(const char* str, const char* flag,
return flag_end + 1;
}
+BENCHMARK_EXPORT
bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, true);
@@ -171,6 +219,7 @@ bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
return true;
}
+BENCHMARK_EXPORT
bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, false);
@@ -183,6 +232,7 @@ bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
value);
}
+BENCHMARK_EXPORT
bool ParseDoubleFlag(const char* str, const char* flag, double* value) {
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, false);
@@ -195,6 +245,7 @@ bool ParseDoubleFlag(const char* str, const char* flag, double* value) {
value);
}
+BENCHMARK_EXPORT
bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
// Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, false);
@@ -206,23 +257,42 @@ bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
return true;
}
+BENCHMARK_EXPORT
+bool ParseKeyValueFlag(const char* str, const char* flag,
+ std::map<std::string, std::string>* value) {
+ const char* const value_str = ParseFlagValue(str, flag, false);
+
+ if (value_str == nullptr) return false;
+
+ for (const auto& kvpair : StrSplit(value_str, ',')) {
+ const auto kv = StrSplit(kvpair, '=');
+ if (kv.size() != 2) return false;
+ value->emplace(kv[0], kv[1]);
+ }
+
+ return true;
+}
+
+BENCHMARK_EXPORT
bool IsFlag(const char* str, const char* flag) {
return (ParseFlagValue(str, flag, true) != nullptr);
}
+BENCHMARK_EXPORT
bool IsTruthyFlagValue(const std::string& value) {
if (value.size() == 1) {
char v = value[0];
return isalnum(v) &&
!(v == '0' || v == 'f' || v == 'F' || v == 'n' || v == 'N');
- } else if (!value.empty()) {
+ }
+ if (!value.empty()) {
std::string value_lower(value);
std::transform(value_lower.begin(), value_lower.end(), value_lower.begin(),
[](char c) { return static_cast<char>(::tolower(c)); });
return !(value_lower == "false" || value_lower == "no" ||
value_lower == "off");
- } else
- return true;
+ }
+ return true;
}
} // end namespace benchmark