Changeset View
Changeset View
Standalone View
Standalone View
src/util.cpp
Show First 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | static inline std::pair<bool, std::string> GetArg(const ArgsManager &am, | ||||
return found_result; | return found_result; | ||||
} | } | ||||
}; | }; | ||||
/** | /** | ||||
* Interpret -nofoo as if the user supplied -foo=0. | * Interpret -nofoo as if the user supplied -foo=0. | ||||
* | * | ||||
* This method also tracks when the -no form was supplied, and treats "-foo" as | * This method also tracks when the -no form was supplied, and if so, checks | ||||
* a negated option when this happens. This can be later checked using the | * whether there was a double-negative (-nofoo=0 -> -foo=1). | ||||
* IsArgNegated() method. One use case for this is to have a way to disable | * | ||||
* options that are not normally boolean (e.g. using -nodebuglogfile to request | * If there was not a double negative, it removes the "no" from the key, and | ||||
* that debug log output is not sent to any file at all). | * returns true, indicating the caller should clear the args vector to indicate | ||||
* a negated option. | |||||
* | |||||
* If there was a double negative, it removes "no" from the key, sets the value | |||||
* to "1" and returns false. | |||||
* | |||||
* If there was no "no", it leaves key and value untouched and returns false. | |||||
* | |||||
* Where an option was negated can be later checked using the IsArgNegated() | |||||
* method. One use case for this is to have a way to disable options that are | |||||
* not normally boolean (e.g. using -nodebuglogfile to request that debug log | |||||
* output is not sent to any file at all). | |||||
*/ | */ | ||||
void ArgsManager::InterpretNegatedOption(std::string &key, std::string &val) { | static bool InterpretNegatedOption(std::string &key, std::string &val) { | ||||
if (key.substr(0, 3) == "-no") { | if (key.substr(0, 3) == "-no") { | ||||
bool bool_val = InterpretBool(val); | bool bool_val = InterpretBool(val); | ||||
key.erase(1, 2); | |||||
if (!bool_val) { | if (!bool_val) { | ||||
// Double negatives like -nofoo=0 are supported (but discouraged) | // Double negatives like -nofoo=0 are supported (but discouraged) | ||||
LogPrintf( | LogPrintf( | ||||
"Warning: parsed potentially confusing double-negative %s=%s\n", | "Warning: parsed potentially confusing double-negative %s=%s\n", | ||||
key, val); | key, val); | ||||
} | val = "1"; | ||||
key.erase(1, 2); | |||||
m_negated_args.insert(key); | |||||
val = bool_val ? "0" : "1"; | |||||
} else { | } else { | ||||
// In an invocation like "bitcoind -nofoo -foo" we want to unmark -foo | return true; | ||||
// as negated when we see the second option. | |||||
m_negated_args.erase(key); | |||||
} | } | ||||
} | } | ||||
return false; | |||||
} | |||||
void ArgsManager::ParseParameters(int argc, const char *const argv[]) { | void ArgsManager::ParseParameters(int argc, const char *const argv[]) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
m_override_args.clear(); | m_override_args.clear(); | ||||
m_negated_args.clear(); | |||||
for (int i = 1; i < argc; i++) { | for (int i = 1; i < argc; i++) { | ||||
std::string key(argv[i]); | std::string key(argv[i]); | ||||
std::string val; | std::string val; | ||||
size_t is_index = key.find('='); | size_t is_index = key.find('='); | ||||
if (is_index != std::string::npos) { | if (is_index != std::string::npos) { | ||||
val = key.substr(is_index + 1); | val = key.substr(is_index + 1); | ||||
key.erase(is_index); | key.erase(is_index); | ||||
Show All 9 Lines | #endif | ||||
break; | break; | ||||
} | } | ||||
// Transform --foo to -foo | // Transform --foo to -foo | ||||
if (key.length() > 1 && key[1] == '-') { | if (key.length() > 1 && key[1] == '-') { | ||||
key.erase(0, 1); | key.erase(0, 1); | ||||
} | } | ||||
// Transform -nofoo to -foo=0 | // Check for -nofoo | ||||
InterpretNegatedOption(key, val); | if (InterpretNegatedOption(key, val)) { | ||||
m_override_args[key].clear(); | |||||
} else { | |||||
m_override_args[key].push_back(val); | m_override_args[key].push_back(val); | ||||
} | } | ||||
} | } | ||||
} | |||||
std::vector<std::string> ArgsManager::GetArgs(const std::string &strArg) const { | std::vector<std::string> ArgsManager::GetArgs(const std::string &strArg) const { | ||||
std::vector<std::string> result = {}; | std::vector<std::string> result = {}; | ||||
// special case | |||||
if (IsArgNegated(strArg)) { | |||||
return result; | |||||
} | |||||
LOCK(cs_args); | LOCK(cs_args); | ||||
ArgsManagerHelper::AddArgs(result, m_override_args, strArg); | ArgsManagerHelper::AddArgs(result, m_override_args, strArg); | ||||
ArgsManagerHelper::AddArgs(result, m_config_args, strArg); | ArgsManagerHelper::AddArgs(result, m_config_args, strArg); | ||||
return result; | return result; | ||||
} | } | ||||
bool ArgsManager::IsArgSet(const std::string &strArg) const { | bool ArgsManager::IsArgSet(const std::string &strArg) const { | ||||
// special case | |||||
if (IsArgNegated(strArg)) { | |||||
return true; | |||||
} | |||||
return ArgsManagerHelper::GetArg(*this, strArg).first; | return ArgsManagerHelper::GetArg(*this, strArg).first; | ||||
} | } | ||||
bool ArgsManager::IsArgNegated(const std::string &strArg) const { | bool ArgsManager::IsArgNegated(const std::string &strArg) const { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
return m_negated_args.find(strArg) != m_negated_args.end(); | |||||
const auto &ov = m_override_args.find(strArg); | |||||
if (ov != m_override_args.end()) { | |||||
return ov->second.empty(); | |||||
} | |||||
const auto &cf = m_config_args.find(strArg); | |||||
if (cf != m_config_args.end()) { | |||||
return cf->second.empty(); | |||||
} | |||||
return false; | |||||
} | } | ||||
std::string ArgsManager::GetArg(const std::string &strArg, | std::string ArgsManager::GetArg(const std::string &strArg, | ||||
const std::string &strDefault) const { | const std::string &strDefault) const { | ||||
if (IsArgNegated(strArg)) { | |||||
return "0"; | |||||
} | |||||
std::pair<bool, std::string> found_res = | std::pair<bool, std::string> found_res = | ||||
ArgsManagerHelper::GetArg(*this, strArg); | ArgsManagerHelper::GetArg(*this, strArg); | ||||
if (found_res.first) { | if (found_res.first) { | ||||
return found_res.second; | return found_res.second; | ||||
} | } | ||||
return strDefault; | return strDefault; | ||||
} | } | ||||
int64_t ArgsManager::GetArg(const std::string &strArg, int64_t nDefault) const { | int64_t ArgsManager::GetArg(const std::string &strArg, int64_t nDefault) const { | ||||
if (IsArgNegated(strArg)) { | |||||
return 0; | |||||
} | |||||
std::pair<bool, std::string> found_res = | std::pair<bool, std::string> found_res = | ||||
ArgsManagerHelper::GetArg(*this, strArg); | ArgsManagerHelper::GetArg(*this, strArg); | ||||
if (found_res.first) { | if (found_res.first) { | ||||
return atoi64(found_res.second); | return atoi64(found_res.second); | ||||
} | } | ||||
return nDefault; | return nDefault; | ||||
} | } | ||||
bool ArgsManager::GetBoolArg(const std::string &strArg, bool fDefault) const { | bool ArgsManager::GetBoolArg(const std::string &strArg, bool fDefault) const { | ||||
if (IsArgNegated(strArg)) { | |||||
return false; | |||||
} | |||||
std::pair<bool, std::string> found_res = | std::pair<bool, std::string> found_res = | ||||
ArgsManagerHelper::GetArg(*this, strArg); | ArgsManagerHelper::GetArg(*this, strArg); | ||||
if (found_res.first) { | if (found_res.first) { | ||||
return InterpretBool(found_res.second); | return InterpretBool(found_res.second); | ||||
} | } | ||||
return fDefault; | return fDefault; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | void ArgsManager::ReadConfigStream(std::istream &stream) { | ||||
std::set<std::string> setOptions; | std::set<std::string> setOptions; | ||||
setOptions.insert("*"); | setOptions.insert("*"); | ||||
for (boost::program_options::detail::config_file_iterator | for (boost::program_options::detail::config_file_iterator | ||||
it(stream, setOptions), | it(stream, setOptions), | ||||
end; | end; | ||||
it != end; ++it) { | it != end; ++it) { | ||||
// Don't overwrite existing settings so command line settings override | |||||
// bitcoin.conf | |||||
std::string strKey = std::string("-") + it->string_key; | std::string strKey = std::string("-") + it->string_key; | ||||
std::string strValue = it->value[0]; | std::string strValue = it->value[0]; | ||||
InterpretNegatedOption(strKey, strValue); | if (InterpretNegatedOption(strKey, strValue)) { | ||||
m_config_args[strKey].clear(); | |||||
} else { | |||||
m_config_args[strKey].push_back(strValue); | m_config_args[strKey].push_back(strValue); | ||||
} | } | ||||
} | } | ||||
} | |||||
void ArgsManager::ReadConfigFile(const std::string &confPath) { | void ArgsManager::ReadConfigFile(const std::string &confPath) { | ||||
{ | { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
m_config_args.clear(); | m_config_args.clear(); | ||||
} | } | ||||
fs::ifstream stream(GetConfigFile(confPath)); | fs::ifstream stream(GetConfigFile(confPath)); | ||||
▲ Show 20 Lines • Show All 275 Lines • Show Last 20 Lines |