Changeset View
Changeset View
Standalone View
Standalone View
src/util.cpp
Show First 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static bool InterpretBool(const std::string &strValue) { | static bool InterpretBool(const std::string &strValue) { | ||||
if (strValue.empty()) { | if (strValue.empty()) { | ||||
return true; | return true; | ||||
} | } | ||||
return (atoi(strValue) != 0); | return (atoi(strValue) != 0); | ||||
} | } | ||||
/** Internal helper functions for ArgsManager */ | |||||
class ArgsManagerHelper { | |||||
public: | |||||
typedef std::map<std::string, std::vector<std::string>> MapArgs; | |||||
/** Find arguments in a map and add them to a vector */ | |||||
static inline void AddArgs(std::vector<std::string> &res, | |||||
const MapArgs &map_args, | |||||
const std::string &arg) { | |||||
auto it = map_args.find(arg); | |||||
if (it != map_args.end()) { | |||||
res.insert(res.end(), it->second.begin(), it->second.end()); | |||||
} | |||||
} | |||||
/** | |||||
* Return true/false if an argument is set in a map, and also | |||||
* return the first (or last) of the possibly multiple values it has | |||||
*/ | |||||
static inline std::pair<bool, std::string> | |||||
GetArgHelper(const MapArgs &map_args, const std::string &arg, | |||||
bool getLast = false) { | |||||
auto it = map_args.find(arg); | |||||
if (it == map_args.end() || it->second.empty()) { | |||||
return std::make_pair(false, std::string()); | |||||
} | |||||
if (getLast) { | |||||
return std::make_pair(true, it->second.back()); | |||||
} else { | |||||
return std::make_pair(true, it->second.front()); | |||||
} | |||||
} | |||||
/** | |||||
* Get the string value of an argument, returning a pair of a boolean | |||||
* indicating the argument was found, and the value for the argument | |||||
* if it was found (or the empty string if not found). | |||||
*/ | |||||
static inline std::pair<bool, std::string> GetArg(const ArgsManager &am, | |||||
const std::string &arg) { | |||||
LOCK(am.cs_args); | |||||
std::pair<bool, std::string> found_result(false, std::string()); | |||||
// We pass "true" to GetArgHelper in order to return the last | |||||
// argument value seen from the command line (so "bitcoind -foo=bar | |||||
// -foo=baz" gives GetArg(am,"foo")=={true,"baz"} | |||||
found_result = GetArgHelper(am.m_override_args, arg, true); | |||||
if (found_result.first) { | |||||
return found_result; | |||||
} | |||||
// But in contrast we return the first argument seen in a config file, | |||||
// so "foo=bar \n foo=baz" in the config file gives | |||||
// GetArg(am,"foo")={true,"bar"} | |||||
found_result = GetArgHelper(am.m_config_args, arg); | |||||
if (found_result.first) { | |||||
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 treats "-foo" as | ||||
* a negated option when this happens. This can be later checked using the | * a negated option when this happens. This can be later checked using the | ||||
* IsArgNegated() method. One use case for this is to have a way to disable | * 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 | * options that are not normally boolean (e.g. using -nodebuglogfile to request | ||||
* that debug log output is not sent to any file at all). | * that debug log output is not sent to any file at all). | ||||
Show All 14 Lines | if (key.substr(0, 3) == "-no") { | ||||
// In an invocation like "bitcoind -nofoo -foo" we want to unmark -foo | // In an invocation like "bitcoind -nofoo -foo" we want to unmark -foo | ||||
// as negated when we see the second option. | // as negated when we see the second option. | ||||
m_negated_args.erase(key); | m_negated_args.erase(key); | ||||
} | } | ||||
} | } | ||||
void ArgsManager::ParseParameters(int argc, const char *const argv[]) { | void ArgsManager::ParseParameters(int argc, const char *const argv[]) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
mapArgs.clear(); | m_override_args.clear(); | ||||
mapMultiArgs.clear(); | |||||
m_negated_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); | ||||
Show All 13 Lines | #endif | ||||
// 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 | // Transform -nofoo to -foo=0 | ||||
InterpretNegatedOption(key, val); | InterpretNegatedOption(key, val); | ||||
mapArgs[key] = val; | m_override_args[key].push_back(val); | ||||
mapMultiArgs[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 = {}; | |||||
LOCK(cs_args); | LOCK(cs_args); | ||||
auto it = mapMultiArgs.find(strArg); | ArgsManagerHelper::AddArgs(result, m_override_args, strArg); | ||||
if (it != mapMultiArgs.end()) { | ArgsManagerHelper::AddArgs(result, m_config_args, strArg); | ||||
return it->second; | return result; | ||||
} | |||||
return {}; | |||||
} | } | ||||
bool ArgsManager::IsArgSet(const std::string &strArg) const { | bool ArgsManager::IsArgSet(const std::string &strArg) const { | ||||
LOCK(cs_args); | return ArgsManagerHelper::GetArg(*this, strArg).first; | ||||
return mapArgs.count(strArg); | |||||
} | } | ||||
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(); | return m_negated_args.find(strArg) != m_negated_args.end(); | ||||
} | } | ||||
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 { | ||||
LOCK(cs_args); | std::pair<bool, std::string> found_res = | ||||
auto it = mapArgs.find(strArg); | ArgsManagerHelper::GetArg(*this, strArg); | ||||
if (it != mapArgs.end()) { | if (found_res.first) { | ||||
return it->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 { | ||||
LOCK(cs_args); | std::pair<bool, std::string> found_res = | ||||
auto it = mapArgs.find(strArg); | ArgsManagerHelper::GetArg(*this, strArg); | ||||
if (it != mapArgs.end()) { | if (found_res.first) { | ||||
return atoi64(it->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 { | ||||
LOCK(cs_args); | std::pair<bool, std::string> found_res = | ||||
auto it = mapArgs.find(strArg); | ArgsManagerHelper::GetArg(*this, strArg); | ||||
if (it != mapArgs.end()) { | if (found_res.first) { | ||||
return InterpretBool(it->second); | return InterpretBool(found_res.second); | ||||
} | } | ||||
return fDefault; | return fDefault; | ||||
} | } | ||||
bool ArgsManager::SoftSetArg(const std::string &strArg, | bool ArgsManager::SoftSetArg(const std::string &strArg, | ||||
const std::string &strValue) { | const std::string &strValue) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
if (IsArgSet(strArg)) { | if (IsArgSet(strArg)) { | ||||
Show All 9 Lines | bool ArgsManager::SoftSetBoolArg(const std::string &strArg, bool fValue) { | ||||
} else { | } else { | ||||
return SoftSetArg(strArg, std::string("0")); | return SoftSetArg(strArg, std::string("0")); | ||||
} | } | ||||
} | } | ||||
void ArgsManager::ForceSetArg(const std::string &strArg, | void ArgsManager::ForceSetArg(const std::string &strArg, | ||||
const std::string &strValue) { | const std::string &strValue) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
mapArgs[strArg] = strValue; | m_override_args[strArg] = {strValue}; | ||||
mapMultiArgs[strArg] = {strValue}; | |||||
} | } | ||||
/** | /** | ||||
* This function is only used for testing purpose so | * This function is only used for testing purpose so | ||||
* so we should not worry about element uniqueness and | * so we should not worry about element uniqueness and | ||||
* integrity of mapMultiArgs data structure | * integrity of mapMultiArgs data structure | ||||
*/ | */ | ||||
void ArgsManager::ForceSetMultiArg(const std::string &strArg, | void ArgsManager::ForceSetMultiArg(const std::string &strArg, | ||||
const std::string &strValue) { | const std::string &strValue) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
if (mapArgs.count(strArg) == 0) { | m_override_args[strArg].push_back(strValue); | ||||
mapArgs[strArg] = strValue; | |||||
} | |||||
mapMultiArgs[strArg].push_back(strValue); | |||||
} | } | ||||
void ArgsManager::ClearArg(const std::string &strArg) { | void ArgsManager::ClearArg(const std::string &strArg) { | ||||
LOCK(cs_args); | LOCK(cs_args); | ||||
mapArgs.erase(strArg); | m_override_args.erase(strArg); | ||||
mapMultiArgs.erase(strArg); | m_config_args.erase(strArg); | ||||
} | } | ||||
bool HelpRequested(const ArgsManager &args) { | bool HelpRequested(const ArgsManager &args) { | ||||
return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help"); | return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help"); | ||||
} | } | ||||
static const int screenWidth = 79; | static const int screenWidth = 79; | ||||
static const int optIndent = 2; | static const int optIndent = 2; | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | 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 | // Don't overwrite existing settings so command line settings override | ||||
// bitcoin.conf | // 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); | InterpretNegatedOption(strKey, strValue); | ||||
if (mapArgs.count(strKey) == 0) { | m_config_args[strKey].push_back(strValue); | ||||
mapArgs[strKey] = strValue; | |||||
} | |||||
mapMultiArgs[strKey].push_back(strValue); | |||||
} | } | ||||
} | } | ||||
void ArgsManager::ReadConfigFile(const std::string &confPath) { | void ArgsManager::ReadConfigFile(const std::string &confPath) { | ||||
{ | |||||
LOCK(cs_args); | |||||
m_config_args.clear(); | |||||
} | |||||
fs::ifstream stream(GetConfigFile(confPath)); | fs::ifstream stream(GetConfigFile(confPath)); | ||||
// ok to not have a config file | // ok to not have a config file | ||||
if (stream.good()) { | if (stream.good()) { | ||||
ReadConfigStream(stream); | ReadConfigStream(stream); | ||||
} | } | ||||
// If datadir is changed in .conf file: | // If datadir is changed in .conf file: | ||||
▲ Show 20 Lines • Show All 268 Lines • Show Last 20 Lines |