mirror of https://github.com/oxen-io/lokinet
Rename config classes for clarity
ConfigDefinition -> OptionDefiniton Configuration -> ConfigDefinition
This commit is contained in:
parent
f250b7adcb
commit
a8671cf9c7
|
@ -40,7 +40,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
RouterConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
RouterConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
constexpr int DefaultJobQueueSize = 1024 * 8;
|
||||
constexpr auto DefaultNetId = "lokinet";
|
||||
|
@ -137,7 +137,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
NetworkConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
NetworkConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -160,7 +160,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
NetdbConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
NetdbConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -170,7 +170,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
DnsConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
DnsConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -217,7 +217,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
LinksConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
LinksConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -238,7 +238,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
ConnectConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
ConnectConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -254,7 +254,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
ServicesConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
ServicesConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -268,7 +268,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
ApiConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
ApiConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -286,7 +286,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
LokidConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
LokidConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -316,7 +316,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
BootstrapConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
BootstrapConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -334,7 +334,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
LoggingConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
LoggingConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -361,7 +361,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
SnappConfig::defineConfigOptions(Configuration& conf, const ConfigGenParameters& params)
|
||||
SnappConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
|
@ -435,7 +435,7 @@ namespace llarp
|
|||
params.isRelay = isRelay;
|
||||
params.defaultDataDir = std::move(defaultDataDir);
|
||||
|
||||
Configuration conf;
|
||||
ConfigDefinition conf;
|
||||
initializeConfig(conf, params);
|
||||
|
||||
ConfigParser parser;
|
||||
|
@ -467,7 +467,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
Config::initializeConfig(Configuration& conf, const ConfigGenParameters& params)
|
||||
Config::initializeConfig(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
// TODO: this seems like a random place to put this, should this be closer
|
||||
// to main() ?
|
||||
|
@ -562,7 +562,7 @@ namespace llarp
|
|||
params.isRelay = false;
|
||||
params.defaultDataDir = std::move(defaultDataDir);
|
||||
|
||||
llarp::Configuration def;
|
||||
llarp::ConfigDefinition def;
|
||||
initializeConfig(def, params);
|
||||
|
||||
// router
|
||||
|
@ -703,7 +703,7 @@ namespace llarp
|
|||
params.isRelay = true;
|
||||
params.defaultDataDir = std::move(defaultDataDir);
|
||||
|
||||
llarp::Configuration def;
|
||||
llarp::ConfigDefinition def;
|
||||
initializeConfig(def, params);
|
||||
|
||||
// lokid
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace llarp
|
|||
size_t m_JobQueueSize;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct NetworkConfig
|
||||
|
@ -64,7 +64,7 @@ namespace llarp
|
|||
FreehandOptions m_options;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct NetdbConfig
|
||||
|
@ -72,7 +72,7 @@ namespace llarp
|
|||
std::string m_nodedbDir;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct DnsConfig
|
||||
|
@ -80,7 +80,7 @@ namespace llarp
|
|||
FreehandOptions m_options;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct LinksConfig
|
||||
|
@ -100,7 +100,7 @@ namespace llarp
|
|||
std::vector<LinkInfo> m_InboundLinks;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct ConnectConfig
|
||||
|
@ -108,14 +108,14 @@ namespace llarp
|
|||
std::vector<std::string> routers;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct ServicesConfig
|
||||
{
|
||||
std::vector< std::pair< std::string, std::string > > services;
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct ApiConfig
|
||||
|
@ -124,7 +124,7 @@ namespace llarp
|
|||
std::string m_rpcBindAddr;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct LokidConfig
|
||||
|
@ -137,14 +137,14 @@ namespace llarp
|
|||
std::string lokidRPCPassword;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct BootstrapConfig
|
||||
{
|
||||
std::vector< std::string > routers;
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct LoggingConfig
|
||||
|
@ -163,7 +163,7 @@ namespace llarp
|
|||
std::string m_logFile;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct SnappConfig
|
||||
|
@ -179,7 +179,7 @@ namespace llarp
|
|||
std::string m_mapAddr;
|
||||
|
||||
void
|
||||
defineConfigOptions(Configuration& conf, const ConfigGenParameters& params);
|
||||
defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
};
|
||||
|
||||
struct Config
|
||||
|
@ -198,7 +198,7 @@ namespace llarp
|
|||
|
||||
// Initialize config definition
|
||||
void
|
||||
initializeConfig(Configuration& conf, const ConfigGenParameters& params);
|
||||
initializeConfig(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
|
||||
// Load a config from the given file
|
||||
bool
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace llarp
|
||||
{
|
||||
|
||||
ConfigDefinitionBase::ConfigDefinitionBase(std::string section_,
|
||||
OptionDefinitionBase::OptionDefinitionBase(std::string section_,
|
||||
std::string name_,
|
||||
bool required_)
|
||||
: section(section_)
|
||||
|
@ -15,8 +15,8 @@ ConfigDefinitionBase::ConfigDefinitionBase(std::string section_,
|
|||
{
|
||||
}
|
||||
|
||||
Configuration&
|
||||
Configuration::defineOption(ConfigDefinition_ptr def)
|
||||
ConfigDefinition&
|
||||
ConfigDefinition::defineOption(OptionDefinition_ptr def)
|
||||
{
|
||||
auto sectionItr = m_definitions.find(def->section);
|
||||
if (sectionItr == m_definitions.end())
|
||||
|
@ -33,8 +33,8 @@ Configuration::defineOption(ConfigDefinition_ptr def)
|
|||
return *this;
|
||||
}
|
||||
|
||||
Configuration&
|
||||
Configuration::addConfigValue(string_view section, string_view name, string_view value)
|
||||
ConfigDefinition&
|
||||
ConfigDefinition::addConfigValue(string_view section, string_view name, string_view value)
|
||||
{
|
||||
auto secItr = m_definitions.find(std::string(section));
|
||||
if (secItr == m_definitions.end())
|
||||
|
@ -57,14 +57,14 @@ Configuration::addConfigValue(string_view section, string_view name, string_view
|
|||
if (defItr == sectionDefinitions.end())
|
||||
throw std::invalid_argument(stringify("no declared option [", section, "]:", name));
|
||||
|
||||
ConfigDefinition_ptr& definition = defItr->second;
|
||||
OptionDefinition_ptr& definition = defItr->second;
|
||||
definition->parseValue(std::string(value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
Configuration::addUndeclaredHandler(const std::string& section, UndeclaredValueHandler handler)
|
||||
ConfigDefinition::addUndeclaredHandler(const std::string& section, UndeclaredValueHandler handler)
|
||||
{
|
||||
auto itr = m_undeclaredHandlers.find(section);
|
||||
if (itr != m_undeclaredHandlers.end())
|
||||
|
@ -74,7 +74,7 @@ Configuration::addUndeclaredHandler(const std::string& section, UndeclaredValueH
|
|||
}
|
||||
|
||||
void
|
||||
Configuration::removeUndeclaredHandler(const std::string& section)
|
||||
ConfigDefinition::removeUndeclaredHandler(const std::string& section)
|
||||
{
|
||||
auto itr = m_undeclaredHandlers.find(section);
|
||||
if (itr != m_undeclaredHandlers.end())
|
||||
|
@ -82,11 +82,11 @@ Configuration::removeUndeclaredHandler(const std::string& section)
|
|||
}
|
||||
|
||||
void
|
||||
Configuration::validateRequiredFields()
|
||||
ConfigDefinition::validateRequiredFields()
|
||||
{
|
||||
visitSections([&](const std::string& section, const DefinitionMap&)
|
||||
{
|
||||
visitDefinitions(section, [&](const std::string&, const ConfigDefinition_ptr& def)
|
||||
visitDefinitions(section, [&](const std::string&, const OptionDefinition_ptr& def)
|
||||
{
|
||||
if (def->required and def->numFound < 1)
|
||||
{
|
||||
|
@ -94,18 +94,18 @@ Configuration::validateRequiredFields()
|
|||
"[", section, "]:", def->name, " is required but missing"));
|
||||
}
|
||||
|
||||
// should be handled earlier in ConfigDefinition::parseValue()
|
||||
// should be handled earlier in OptionDefinition::parseValue()
|
||||
assert(def->numFound <= 1 or def->multiValued);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Configuration::acceptAllOptions()
|
||||
ConfigDefinition::acceptAllOptions()
|
||||
{
|
||||
visitSections([&](const std::string& section, const DefinitionMap&)
|
||||
{
|
||||
visitDefinitions(section, [&](const std::string&, const ConfigDefinition_ptr& def)
|
||||
visitDefinitions(section, [&](const std::string&, const OptionDefinition_ptr& def)
|
||||
{
|
||||
def->tryAccept();
|
||||
});
|
||||
|
@ -113,14 +113,14 @@ Configuration::acceptAllOptions()
|
|||
}
|
||||
|
||||
void
|
||||
Configuration::addSectionComment(const std::string& section,
|
||||
ConfigDefinition::addSectionComment(const std::string& section,
|
||||
std::string comment)
|
||||
{
|
||||
m_sectionComments[section].push_back(std::move(comment));
|
||||
}
|
||||
|
||||
void
|
||||
Configuration::addOptionComment(const std::string& section,
|
||||
ConfigDefinition::addOptionComment(const std::string& section,
|
||||
const std::string& name,
|
||||
std::string comment)
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ Configuration::addOptionComment(const std::string& section,
|
|||
}
|
||||
|
||||
std::string
|
||||
Configuration::generateINIConfig(bool useValues)
|
||||
ConfigDefinition::generateINIConfig(bool useValues)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
|
@ -147,7 +147,7 @@ Configuration::generateINIConfig(bool useValues)
|
|||
|
||||
oss << "[" << section << "]\n";
|
||||
|
||||
visitDefinitions(section, [&](const std::string& name, const ConfigDefinition_ptr& def) {
|
||||
visitDefinitions(section, [&](const std::string& name, const OptionDefinition_ptr& def) {
|
||||
oss << "\n";
|
||||
|
||||
// TODO: as above, this will create empty objects
|
||||
|
@ -177,8 +177,8 @@ Configuration::generateINIConfig(bool useValues)
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
const ConfigDefinition_ptr&
|
||||
Configuration::lookupDefinitionOrThrow(string_view section, string_view name) const
|
||||
const OptionDefinition_ptr&
|
||||
ConfigDefinition::lookupDefinitionOrThrow(string_view section, string_view name) const
|
||||
{
|
||||
const auto sectionItr = m_definitions.find(std::string(section));
|
||||
if (sectionItr == m_definitions.end())
|
||||
|
@ -192,14 +192,14 @@ Configuration::lookupDefinitionOrThrow(string_view section, string_view name) co
|
|||
return definitionItr->second;
|
||||
}
|
||||
|
||||
ConfigDefinition_ptr&
|
||||
Configuration::lookupDefinitionOrThrow(string_view section, string_view name)
|
||||
OptionDefinition_ptr&
|
||||
ConfigDefinition::lookupDefinitionOrThrow(string_view section, string_view name)
|
||||
{
|
||||
return const_cast<ConfigDefinition_ptr&>(
|
||||
const_cast<const Configuration*>(this)->lookupDefinitionOrThrow(section, name));
|
||||
return const_cast<OptionDefinition_ptr&>(
|
||||
const_cast<const ConfigDefinition*>(this)->lookupDefinitionOrThrow(section, name));
|
||||
}
|
||||
|
||||
void Configuration::visitSections(SectionVisitor visitor) const
|
||||
void ConfigDefinition::visitSections(SectionVisitor visitor) const
|
||||
{
|
||||
for (const std::string& section : m_sectionOrdering)
|
||||
{
|
||||
|
@ -208,7 +208,7 @@ void Configuration::visitSections(SectionVisitor visitor) const
|
|||
visitor(section, itr->second);
|
||||
}
|
||||
};
|
||||
void Configuration::visitDefinitions(const std::string& section, DefVisitor visitor) const
|
||||
void ConfigDefinition::visitDefinitions(const std::string& section, DefVisitor visitor) const
|
||||
{
|
||||
const auto& defs = m_definitions.at(section);
|
||||
const auto& defOrdering = m_definitionOrdering.at(section);
|
||||
|
|
|
@ -17,14 +17,14 @@ namespace llarp
|
|||
/// type functions are provided pure-virtual. The type-aware implementations which implement these
|
||||
/// functions are templated classes. One reason for providing a non-templated base class is so
|
||||
/// that they can all be mixed into the same containers (albiet as pointers).
|
||||
struct ConfigDefinitionBase
|
||||
struct OptionDefinitionBase
|
||||
{
|
||||
ConfigDefinitionBase(std::string section_,
|
||||
OptionDefinitionBase(std::string section_,
|
||||
std::string name_,
|
||||
bool required_);
|
||||
|
||||
virtual
|
||||
~ConfigDefinitionBase() {}
|
||||
~OptionDefinitionBase() {}
|
||||
|
||||
/// Subclasses should provide their default value as a string
|
||||
///
|
||||
|
@ -46,7 +46,7 @@ namespace llarp
|
|||
virtual std::string
|
||||
valueAsString(bool useDefault) = 0;
|
||||
|
||||
/// Subclassess should call their acceptor, if present. See ConfigDefinition for more details.
|
||||
/// Subclassess should call their acceptor, if present. See OptionDefinition for more details.
|
||||
///
|
||||
/// @throws if the acceptor throws or the option is required but missing
|
||||
virtual void tryAccept() const = 0;
|
||||
|
@ -58,16 +58,16 @@ namespace llarp
|
|||
size_t numFound = 0;
|
||||
};
|
||||
|
||||
/// The primary type-aware implementation of ConfigDefinitionBase, this templated class allows
|
||||
/// The primary type-aware implementation of OptionDefinitionBase, this templated class allows
|
||||
/// for implementations which can use the std::ostringstream and std::istringstream for to/from
|
||||
/// string functionality.
|
||||
///
|
||||
/// Note that types (T) used as template parameters here must be used verbatim when calling
|
||||
/// Configuration::getConfigValue(). Similar types such as uint32_t and int32_t cannot be mixed.
|
||||
/// ConfigDefinition::getConfigValue(). Similar types such as uint32_t and int32_t cannot be mixed.
|
||||
template<typename T>
|
||||
struct ConfigDefinition : public ConfigDefinitionBase
|
||||
struct OptionDefinition : public OptionDefinitionBase
|
||||
{
|
||||
/// Constructor. Arguments are passed directly to ConfigDefinitionBase.
|
||||
/// Constructor. Arguments are passed directly to OptionDefinitionBase.
|
||||
///
|
||||
/// @param defaultValue_ is used in the following situations:
|
||||
/// 1) as the return value for getValue() if there is no parsed value and required==false
|
||||
|
@ -77,12 +77,12 @@ namespace llarp
|
|||
/// @param acceptor_ is an optional function whose purpose is to both validate the parsed
|
||||
/// input and internalize it (e.g. copy it for runtime use). The acceptor should throw
|
||||
/// an exception with a useful message if it is not acceptable.
|
||||
ConfigDefinition(std::string section_,
|
||||
OptionDefinition(std::string section_,
|
||||
std::string name_,
|
||||
bool required_,
|
||||
nonstd::optional<T> defaultValue_,
|
||||
std::function<void(T)> acceptor_ = nullptr)
|
||||
: ConfigDefinitionBase(section_, name_, required_)
|
||||
: OptionDefinitionBase(section_, name_, required_)
|
||||
, defaultValue(defaultValue_)
|
||||
, acceptor(acceptor_)
|
||||
{
|
||||
|
@ -181,49 +181,49 @@ namespace llarp
|
|||
= std::function<void(string_view section, string_view name, string_view value)>;
|
||||
|
||||
|
||||
using ConfigDefinition_ptr = std::unique_ptr<ConfigDefinitionBase>;
|
||||
using OptionDefinition_ptr = std::unique_ptr<OptionDefinitionBase>;
|
||||
|
||||
// map of k:v pairs
|
||||
using DefinitionMap = std::unordered_map<std::string, ConfigDefinition_ptr>;
|
||||
using DefinitionMap = std::unordered_map<std::string, OptionDefinition_ptr>;
|
||||
|
||||
// map of section-name to map-of-definitions
|
||||
using SectionMap = std::unordered_map<std::string, DefinitionMap>;
|
||||
|
||||
/// A Configuration holds an ordered set of ConfigDefinitions defining the allowable values and
|
||||
/// A ConfigDefinition holds an ordered set of OptionDefinitions defining the allowable values and
|
||||
/// their constraints (specified through calls to defineOption()).
|
||||
///
|
||||
/// The layout and grouping of the config options are modelled after the INI file format; each
|
||||
/// option has a name and is grouped under a section. Duplicate option names are allowed only if
|
||||
/// they exist in a different section. The configuration can be serialized in the INI file format
|
||||
/// they exist in a different section. The ConfigDefinition can be serialized in the INI file format
|
||||
/// using the generateINIConfig() function.
|
||||
///
|
||||
/// Configured values (e.g. those encountered when parsing a file) can be provided through calls
|
||||
/// to addConfigValue(). These take a std::string as a value, which is automatically parsed.
|
||||
///
|
||||
/// The Configuration can be used to print out a full config string (or file), including fields
|
||||
/// The ConfigDefinition can be used to print out a full config string (or file), including fields
|
||||
/// with defaults and optionally fields which have a specified value (values provided through
|
||||
/// calls to addConfigValue()).
|
||||
struct Configuration {
|
||||
struct ConfigDefinition {
|
||||
|
||||
/// Spefify the parameters and type of a configuration option. The parameters are members of
|
||||
/// ConfigDefinitionBase; the type is inferred from ConfigDefinition's template parameter T.
|
||||
/// OptionDefinitionBase; the type is inferred from OptionDefinition's template parameter T.
|
||||
///
|
||||
/// This function should be called for every option that this Configuration supports, and should
|
||||
/// be done before any other interractions involving that option.
|
||||
///
|
||||
/// @param def should be a unique_ptr to a valid subclass of ConfigDefinitionBase
|
||||
/// @param def should be a unique_ptr to a valid subclass of OptionDefinitionBase
|
||||
/// @return `*this` for chaining calls
|
||||
/// @throws std::invalid_argument if the option already exists
|
||||
Configuration&
|
||||
defineOption(ConfigDefinition_ptr def);
|
||||
ConfigDefinition&
|
||||
defineOption(OptionDefinition_ptr def);
|
||||
|
||||
/// Convenience function which calls defineOption with a ConfigDefinition of the specified type
|
||||
/// and with parameters passed through to ConfigDefinition's constructor.
|
||||
/// Convenience function which calls defineOption with a OptionDefinition of the specified type
|
||||
/// and with parameters passed through to OptionDefinition's constructor.
|
||||
template<typename T, typename... Params>
|
||||
Configuration&
|
||||
ConfigDefinition&
|
||||
defineOption(Params&&... args)
|
||||
{
|
||||
return defineOption(std::make_unique<ConfigDefinition<T>>(args...));
|
||||
return defineOption(std::make_unique<OptionDefinition<T>>(args...));
|
||||
}
|
||||
|
||||
/// Specify a config value for the given section and name. The value should be a valid string
|
||||
|
@ -237,7 +237,7 @@ namespace llarp
|
|||
/// @param name is the name of the value
|
||||
/// @return `*this` for chaining calls
|
||||
/// @throws if the option doesn't exist or the provided string isn't parseable
|
||||
Configuration&
|
||||
ConfigDefinition&
|
||||
addConfigValue(string_view section,
|
||||
string_view name,
|
||||
string_view value);
|
||||
|
@ -256,9 +256,9 @@ namespace llarp
|
|||
template<typename T>
|
||||
nonstd::optional<T> getConfigValue(string_view section, string_view name)
|
||||
{
|
||||
ConfigDefinition_ptr& definition = lookupDefinitionOrThrow(section, name);
|
||||
OptionDefinition_ptr& definition = lookupDefinitionOrThrow(section, name);
|
||||
|
||||
auto derived = dynamic_cast<const ConfigDefinition<T>*>(definition.get());
|
||||
auto derived = dynamic_cast<const OptionDefinition<T>*>(definition.get());
|
||||
if (not derived)
|
||||
throw std::invalid_argument(stringify("", typeid(T).name(),
|
||||
" is the incorrect type for [", section, "]:", name));
|
||||
|
@ -333,13 +333,13 @@ namespace llarp
|
|||
|
||||
private:
|
||||
|
||||
ConfigDefinition_ptr& lookupDefinitionOrThrow(string_view section, string_view name);
|
||||
const ConfigDefinition_ptr& lookupDefinitionOrThrow(string_view section, string_view name) const;
|
||||
OptionDefinition_ptr& lookupDefinitionOrThrow(string_view section, string_view name);
|
||||
const OptionDefinition_ptr& lookupDefinitionOrThrow(string_view section, string_view name) const;
|
||||
|
||||
using SectionVisitor = std::function<void(const std::string&, const DefinitionMap&)>;
|
||||
void visitSections(SectionVisitor visitor) const;
|
||||
|
||||
using DefVisitor = std::function<void(const std::string&, const ConfigDefinition_ptr&)>;
|
||||
using DefVisitor = std::function<void(const std::string&, const OptionDefinition_ptr&)>;
|
||||
void visitDefinitions(const std::string& section, DefVisitor visitor) const;
|
||||
|
||||
SectionMap m_definitions;
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
using llarp::string_view;
|
||||
|
||||
TEST_CASE("ConfigDefinition int parse test", "[config]")
|
||||
TEST_CASE("OptionDefinition int parse test", "[config]")
|
||||
{
|
||||
llarp::ConfigDefinition<int> def("foo", "bar", false, 42);
|
||||
llarp::OptionDefinition<int> def("foo", "bar", false, 42);
|
||||
|
||||
CHECK(def.getValue() == 42);
|
||||
CHECK(def.numFound == 0);
|
||||
|
@ -21,9 +21,9 @@ TEST_CASE("ConfigDefinition int parse test", "[config]")
|
|||
CHECK(def.defaultValueAsString() == "42");
|
||||
}
|
||||
|
||||
TEST_CASE("ConfigDefinition string parse test", "[config]")
|
||||
TEST_CASE("OptionDefinition string parse test", "[config]")
|
||||
{
|
||||
llarp::ConfigDefinition<std::string> def("foo", "bar", false, "test");
|
||||
llarp::OptionDefinition<std::string> def("foo", "bar", false, "test");
|
||||
|
||||
CHECK(def.getValue() == "test");
|
||||
CHECK(def.defaultValueAsString() == "test");
|
||||
|
@ -33,10 +33,10 @@ TEST_CASE("ConfigDefinition string parse test", "[config]")
|
|||
CHECK(def.numFound == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("ConfigDefinition multiple parses test", "[config]")
|
||||
TEST_CASE("OptionDefinition multiple parses test", "[config]")
|
||||
{
|
||||
{
|
||||
llarp::ConfigDefinition<int> def("foo", "bar", false, 8);
|
||||
llarp::OptionDefinition<int> def("foo", "bar", false, 8);
|
||||
def.multiValued = true;
|
||||
|
||||
CHECK_NOTHROW(def.parseValue("9"));
|
||||
|
@ -50,7 +50,7 @@ TEST_CASE("ConfigDefinition multiple parses test", "[config]")
|
|||
}
|
||||
|
||||
{
|
||||
llarp::ConfigDefinition<int> def("foo", "baz", false, 4);
|
||||
llarp::OptionDefinition<int> def("foo", "baz", false, 4);
|
||||
|
||||
CHECK_NOTHROW(def.parseValue("3"));
|
||||
CHECK(def.getValue() == 3);
|
||||
|
@ -63,10 +63,10 @@ TEST_CASE("ConfigDefinition multiple parses test", "[config]")
|
|||
|
||||
}
|
||||
|
||||
TEST_CASE("ConfigDefinition acceptor test", "[config]")
|
||||
TEST_CASE("OptionDefinition acceptor test", "[config]")
|
||||
{
|
||||
int test = -1;
|
||||
llarp::ConfigDefinition<int> def("foo", "bar", false, 42, [&](int arg) {
|
||||
llarp::OptionDefinition<int> def("foo", "bar", false, 42, [&](int arg) {
|
||||
test = arg;
|
||||
});
|
||||
|
||||
|
@ -78,9 +78,9 @@ TEST_CASE("ConfigDefinition acceptor test", "[config]")
|
|||
CHECK(test == 43);
|
||||
}
|
||||
|
||||
TEST_CASE("ConfigDefinition acceptor throws test", "[config]")
|
||||
TEST_CASE("OptionDefinition acceptor throws test", "[config]")
|
||||
{
|
||||
llarp::ConfigDefinition<int> def("foo", "bar", false, 42, [&](int arg) {
|
||||
llarp::OptionDefinition<int> def("foo", "bar", false, 42, [&](int arg) {
|
||||
(void)arg;
|
||||
throw std::runtime_error("FAIL");
|
||||
});
|
||||
|
@ -88,10 +88,10 @@ TEST_CASE("ConfigDefinition acceptor throws test", "[config]")
|
|||
REQUIRE_THROWS_WITH(def.tryAccept(), "FAIL");
|
||||
}
|
||||
|
||||
TEST_CASE("ConfigDefinition tryAccept missing option test", "[config]")
|
||||
TEST_CASE("OptionDefinition tryAccept missing option test", "[config]")
|
||||
{
|
||||
int unset = -1;
|
||||
llarp::ConfigDefinition<int> def("foo", "bar", true, 1, [&](int arg) {
|
||||
llarp::OptionDefinition<int> def("foo", "bar", true, 1, [&](int arg) {
|
||||
(void)arg;
|
||||
unset = 0; // should never be called
|
||||
});
|
||||
|
@ -100,10 +100,10 @@ TEST_CASE("ConfigDefinition tryAccept missing option test", "[config]")
|
|||
"cannot call tryAccept() on [foo]:bar when required but no value available");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration basic add/get test", "[config]")
|
||||
TEST_CASE("ConfigDefinition basic add/get test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
llarp::ConfigDefinition config;
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"router",
|
||||
"threads",
|
||||
false,
|
||||
|
@ -119,13 +119,13 @@ TEST_CASE("Configuration basic add/get test", "[config]")
|
|||
CHECK(config.getConfigValue<int>("router", "threads") == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration missing def test", "[config]")
|
||||
TEST_CASE("ConfigDefinition missing def test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
CHECK_THROWS(config.addConfigValue("foo", "bar", "5"));
|
||||
CHECK_THROWS(config.getConfigValue<int>("foo", "bar") == 5);
|
||||
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"quux",
|
||||
"bar",
|
||||
false,
|
||||
|
@ -134,10 +134,10 @@ TEST_CASE("Configuration missing def test", "[config]")
|
|||
CHECK_THROWS(config.addConfigValue("foo", "bar", "5"));
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration required test", "[config]")
|
||||
TEST_CASE("ConfigDefinition required test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
llarp::ConfigDefinition config;
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"router",
|
||||
"threads",
|
||||
true,
|
||||
|
@ -150,15 +150,15 @@ TEST_CASE("Configuration required test", "[config]")
|
|||
CHECK_NOTHROW(config.validateRequiredFields());
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration section test", "[config]")
|
||||
TEST_CASE("ConfigDefinition section test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
llarp::ConfigDefinition config;
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo",
|
||||
"bar",
|
||||
true,
|
||||
1));
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"goo",
|
||||
"bar",
|
||||
true,
|
||||
|
@ -176,17 +176,17 @@ TEST_CASE("Configuration section test", "[config]")
|
|||
CHECK(config.getConfigValue<int>("goo", "bar") == 6);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration acceptAllOptions test", "[config]")
|
||||
TEST_CASE("ConfigDefinition acceptAllOptions test", "[config]")
|
||||
{
|
||||
int fooBar = -1;
|
||||
std::string fooBaz = "";
|
||||
|
||||
llarp::Configuration config;
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
llarp::ConfigDefinition config;
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", false, 1, [&](int arg) {
|
||||
fooBar = arg;
|
||||
}));
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<std::string>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<std::string>>(
|
||||
"foo", "baz", false, "no", [&](std::string arg) {
|
||||
fooBaz = arg;
|
||||
}));
|
||||
|
@ -199,10 +199,10 @@ TEST_CASE("Configuration acceptAllOptions test", "[config]")
|
|||
CHECK(fooBaz == "yes");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration acceptAllOptions exception propagation test", "[config]")
|
||||
TEST_CASE("ConfigDefinition acceptAllOptions exception propagation test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
llarp::ConfigDefinition config;
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", false, 1, [&](int arg) {
|
||||
(void)arg;
|
||||
throw std::runtime_error("FAIL");
|
||||
|
@ -211,16 +211,16 @@ TEST_CASE("Configuration acceptAllOptions exception propagation test", "[config]
|
|||
REQUIRE_THROWS_WITH(config.acceptAllOptions(), "FAIL");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration defineOptions passthrough test", "[config]")
|
||||
TEST_CASE("ConfigDefinition defineOptions passthrough test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
config.defineOption<int>("foo", "bar", false, 1);
|
||||
CHECK(config.getConfigValue<int>("foo", "bar") == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration undeclared definition basic test", "[config]")
|
||||
TEST_CASE("ConfigDefinition undeclared definition basic test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
bool invoked = false;
|
||||
|
||||
|
@ -237,9 +237,9 @@ TEST_CASE("Configuration undeclared definition basic test", "[config]")
|
|||
CHECK(invoked);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration undeclared add more than once test", "[config]")
|
||||
TEST_CASE("ConfigDefinition undeclared add more than once test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
std::string calledBy = "";
|
||||
|
||||
|
@ -257,9 +257,9 @@ TEST_CASE("Configuration undeclared add more than once test", "[config]")
|
|||
CHECK(calledBy == "a");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration undeclared add/remove test", "[config]")
|
||||
TEST_CASE("ConfigDefinition undeclared add/remove test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
std::string calledBy = "";
|
||||
|
||||
|
@ -291,9 +291,9 @@ TEST_CASE("Configuration undeclared add/remove test", "[config]")
|
|||
CHECK(calledBy == "b");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration undeclared handler exception propagation test", "[config]")
|
||||
TEST_CASE("ConfigDefinition undeclared handler exception propagation test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addUndeclaredHandler("foo", [](string_view, string_view, string_view) {
|
||||
throw std::runtime_error("FAIL");
|
||||
|
@ -302,9 +302,9 @@ TEST_CASE("Configuration undeclared handler exception propagation test", "[confi
|
|||
REQUIRE_THROWS_WITH(config.addConfigValue("foo", "bar", "val"), "FAIL");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration undeclared handler wrong section", "[config]")
|
||||
TEST_CASE("ConfigDefinition undeclared handler wrong section", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addUndeclaredHandler("foo", [](string_view, string_view, string_view) {
|
||||
throw std::runtime_error("FAIL");
|
||||
|
@ -313,9 +313,9 @@ TEST_CASE("Configuration undeclared handler wrong section", "[config]")
|
|||
REQUIRE_THROWS_WITH(config.addConfigValue("argle", "bar", "val"), "no declared section [argle]");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration undeclared handler duplicate names", "[config]")
|
||||
TEST_CASE("ConfigDefinition undeclared handler duplicate names", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
int count = 0;
|
||||
|
||||
|
@ -330,9 +330,9 @@ TEST_CASE("Configuration undeclared handler duplicate names", "[config]")
|
|||
REQUIRE(count == 3);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration AssignmentAcceptor", "[config]")
|
||||
TEST_CASE("ConfigDefinition AssignmentAcceptor", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
int val = -1;
|
||||
config.defineOption<int>("foo", "bar", false, 2, llarp::AssignmentAcceptor(val));
|
||||
|
|
|
@ -2,22 +2,22 @@
|
|||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Configuration simple generate test", "[config]")
|
||||
TEST_CASE("ConfigDefinition simple generate test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "baz", false, 2));
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<std::string>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<std::string>>(
|
||||
"foo", "quux", true, "hello"));
|
||||
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"argle", "bar", true, 3));
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"argle", "baz", false, 4));
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<std::string>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<std::string>>(
|
||||
"argle", "quux", true, "the quick brown fox"));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
@ -41,11 +41,11 @@ quux=the quick brown fox
|
|||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration useValue test", "[config]")
|
||||
TEST_CASE("ConfigDefinition useValue test", "[config]")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
constexpr auto expected = "[foo]\n\nbar=1\n";
|
||||
|
@ -61,13 +61,13 @@ TEST_CASE("Configuration useValue test", "[config]")
|
|||
CHECK(config.generateINIConfig(true) == expectedWhenValueProvided);
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration section comments test")
|
||||
TEST_CASE("ConfigDefinition section comments test")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addSectionComment("foo", "test comment");
|
||||
config.addSectionComment("foo", "test comment 2");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
@ -80,13 +80,13 @@ bar=1
|
|||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration option comments test")
|
||||
TEST_CASE("ConfigDefinition option comments test")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addOptionComment("foo", "bar", "test comment 1");
|
||||
config.addOptionComment("foo", "bar", "test comment 2");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
@ -99,16 +99,16 @@ bar=1
|
|||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration empty comments test")
|
||||
TEST_CASE("ConfigDefinition empty comments test")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addSectionComment("foo", "section comment");
|
||||
config.addSectionComment("foo", "");
|
||||
|
||||
config.addOptionComment("foo", "bar", "option comment");
|
||||
config.addOptionComment("foo", "bar", "");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
@ -123,18 +123,18 @@ bar=1
|
|||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration multi option comments")
|
||||
TEST_CASE("ConfigDefinition multi option comments")
|
||||
{
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addSectionComment("foo", "foo section comment");
|
||||
|
||||
config.addOptionComment("foo", "bar", "foo bar option comment");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "bar", true, 1));
|
||||
|
||||
config.addOptionComment("foo", "baz", "foo baz option comment");
|
||||
config.defineOption(std::make_unique<llarp::ConfigDefinition<int>>(
|
||||
config.defineOption(std::make_unique<llarp::OptionDefinition<int>>(
|
||||
"foo", "baz", true, 1));
|
||||
|
||||
std::string output = config.generateINIConfig();
|
||||
|
@ -150,10 +150,10 @@ baz=1
|
|||
)raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Configuration should print comments for missing keys")
|
||||
TEST_CASE("ConfigDefinition should print comments for missing keys")
|
||||
{
|
||||
// TODO: this currently fails: how to implement?
|
||||
llarp::Configuration config;
|
||||
llarp::ConfigDefinition config;
|
||||
|
||||
config.addSectionComment("foo", "foo section comment");
|
||||
config.addOptionComment("foo", "bar", "foo bar option comment");
|
||||
|
|
Loading…
Reference in New Issue