More documentation around Configuration/ConfigDefinition

pull/1186/head
Stephen Shelton 4 years ago
parent 8352de7bd4
commit 8160c13458
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -77,7 +77,7 @@ Configuration::generateINIConfig(bool useValues)
visitDefinitions(section, [&](const std::string& name, const ConfigDefinition_ptr& def) {
if (useValues and def->numFound > 0)
{
oss << name << "=" << def->writeValue(false) << "\n";
oss << name << "=" << def->valueAsString(false) << "\n";
}
else
{

@ -13,7 +13,10 @@
namespace llarp
{
/// non-templated base class for all config definition types.
/// A base class for specifying config options and their constraints. The basic to/from string
/// 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
{
ConfigDefinitionBase(std::string section_,
@ -24,17 +27,25 @@ namespace llarp
virtual
~ConfigDefinitionBase() {}
/// subclasses should provide their default value as a string
/// Subclasses should provide their default value as a string
///
/// @return the option's default value represented as a string
virtual std::string
defaultValueAsString() = 0;
/// subclasses should parse and store the provided input
/// Subclasses should parse and store the provided input
///
/// @param input is the string input to interpret
virtual void
parseValue(const std::string& input) = 0;
/// subclasess should write their parsed value (not default value) as a string
/// Subclasess should write their parsed value as a string, optionally falling back to any
/// specified default if `useDefault` is true.
///
/// @param useDefault should specify whether to fallback to default when possible
/// @return the option's value as a string
virtual std::string
writeValue(bool useDefault) = 0;
valueAsString(bool useDefault) = 0;
std::string section;
std::string name;
@ -43,9 +54,21 @@ namespace llarp
size_t numFound = 0;
};
/// The primary type-aware implementation of ConfigDefinitionBase, 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.
template<typename T>
struct ConfigDefinition : public ConfigDefinitionBase
{
/// Constructor. Arguments are passed directly to ConfigDefinitionBase. Also accepts a default
/// value, which is used in the following situations:
///
/// 1) as the return value for getValue() if there is no parsed value and required==false
/// 2) as the output in defaultValueAsString(), used to generate config files
/// 3) as the output in valueAsString(), used to generate config files
ConfigDefinition(std::string section_,
std::string name_,
bool required_,
@ -56,6 +79,10 @@ namespace llarp
{
}
/// Returns the parsed value, if available. Otherwise, provides the default value if the option
/// is not required. Otherwise, returns an empty optional.
///
/// @return an optional with the parsed value, the default value, or no value.
nonstd::optional<T>
getValue() const
{
@ -68,7 +95,7 @@ namespace llarp
}
std::string
defaultValueAsString()
defaultValueAsString() override
{
std::ostringstream oss;
if (defaultValue.has_value())
@ -78,7 +105,7 @@ namespace llarp
}
void
parseValue(const std::string& input)
parseValue(const std::string& input) override
{
if (not multiValued and parsedValue.has_value())
{
@ -102,7 +129,7 @@ namespace llarp
}
std::string
writeValue(bool useDefault)
valueAsString(bool useDefault) override
{
std::ostringstream oss;
if (parsedValue.has_value())
@ -126,15 +153,46 @@ namespace llarp
// 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
/// their constraints and an optional set defining overrides of those values (e.g. the results
/// of a parsed config file).
/// A Configuration holds an ordered set of ConfigDefinitions defining the allowable values and
/// their constraints (specified through calls to addConfigOption()).
///
/// 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
/// 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
/// with defaults and optionally fields which have a specified value (values provided through
/// calls to addConfigValue()).
struct Configuration {
SectionMap m_definitions;
/// 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.
///
/// 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
/// @return `*this` for chaining calls
/// @throws std::invalid_argument if the option already exists
Configuration&
addConfigOption(ConfigDefinition_ptr def);
/// Specify a config value for the given section and name. The value should be a valid string
/// representing the type used by the option (e.g. the type provided when addConfigOption() was
/// called).
///
/// If the specified option doesn't exist, an exception will be thrown. Otherwise, the option's
/// parsedValue() will be invoked, and should throw an exception if the string can't be parsed.
///
/// @param section is the section this value resides in
/// @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&
addConfigValue(string_view section,
string_view name,

Loading…
Cancel
Save