Implement Configuration::generateDefaultConfig(), maintain insertion order

pull/1186/head
Stephen Shelton 4 years ago
parent 7dacc30862
commit 1b19314278
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -1,29 +1,11 @@
#include <config/definition.hpp>
#include <sstream>
#include <stdexcept>
namespace llarp
{
/// utility functions for visiting each section/definition
///
using SectionVisitor = std::function<void(const std::string&, const DefinitionMap&)>;
void visitSections(const SectionMap& sections, SectionVisitor visitor)
{
for (const auto& pair : sections)
{
visitor(pair.first, pair.second);
}
};
using DefVisitor = std::function<void(const std::string&, const ConfigDefinition_ptr&)>;
void visitDefinitions(const DefinitionMap& defs, DefVisitor visitor)
{
for (const auto& pair : defs)
{
visitor(pair.first, pair.second);
}
};
ConfigDefinitionBase::ConfigDefinitionBase(std::string section_,
std::string name_,
bool required_,
@ -38,11 +20,16 @@ ConfigDefinitionBase::ConfigDefinitionBase(std::string section_,
Configuration&
Configuration::addDefinition(ConfigDefinition_ptr def)
{
auto sectionItr = m_definitions.find(def->section);
if (sectionItr == m_definitions.end())
m_sectionOrdering.push_back(def->section);
auto& sectionDefinitions = m_definitions[def->section];
if (sectionDefinitions.find(def->name) != sectionDefinitions.end())
throw std::invalid_argument(stringify("definition for [",
def->section, "]:", def->name, " already exists"));
m_definitionOrdering[def->section].push_back(def->name);
sectionDefinitions[def->name] = std::move(def);
return *this;
@ -57,33 +44,11 @@ Configuration::addConfigValue(string_view section, string_view name, string_view
return *this;
}
const ConfigDefinition_ptr&
Configuration::lookupDefinitionOrThrow(string_view section, string_view name) const
{
const auto sectionItr = m_definitions.find(std::string(section));
if (sectionItr == m_definitions.end())
throw std::invalid_argument(stringify("No config section ", section));
auto& sectionDefinitions = sectionItr->second;
const auto definitionItr = sectionDefinitions.find(std::string(name));
if (definitionItr == sectionDefinitions.end())
throw std::invalid_argument(stringify("No config item ", name, " within section ", section));
return definitionItr->second;
}
ConfigDefinition_ptr&
Configuration::lookupDefinitionOrThrow(string_view section, string_view name)
{
return const_cast<ConfigDefinition_ptr&>(
const_cast<const Configuration*>(this)->lookupDefinitionOrThrow(section, name));
}
void
Configuration::validate()
{
visitSections(m_definitions, [&](const std::string& section, const DefinitionMap& defs) {
visitDefinitions(defs, [&](const std::string&, const ConfigDefinition_ptr& def) {
visitSections([&](const std::string& section, const DefinitionMap&) {
visitDefinitions(section, [&](const std::string&, const ConfigDefinition_ptr& def) {
if (def->required and def->numFound < 1)
{
throw std::invalid_argument(stringify(
@ -99,7 +64,24 @@ Configuration::validate()
std::string
Configuration::generateDefaultConfig()
{
return "Implement me!";
std::ostringstream oss;
int sectionsVisited = 0;
visitSections([&](const std::string& section, const DefinitionMap&) {
if (sectionsVisited > 0)
oss << "\n";
oss << "[" << section << "]\n";
visitDefinitions(section, [&](const std::string& name, const ConfigDefinition_ptr& def) {
oss << name << "=" << def->defaultValueAsString() << "\n";
});
sectionsVisited++;
});
return oss.str();
}
std::string
@ -108,5 +90,48 @@ Configuration::generateOverridenConfig()
return "Implement me!";
}
const ConfigDefinition_ptr&
Configuration::lookupDefinitionOrThrow(string_view section, string_view name) const
{
const auto sectionItr = m_definitions.find(std::string(section));
if (sectionItr == m_definitions.end())
throw std::invalid_argument(stringify("No config section ", section));
auto& sectionDefinitions = sectionItr->second;
const auto definitionItr = sectionDefinitions.find(std::string(name));
if (definitionItr == sectionDefinitions.end())
throw std::invalid_argument(stringify("No config item ", name, " within section ", section));
return definitionItr->second;
}
ConfigDefinition_ptr&
Configuration::lookupDefinitionOrThrow(string_view section, string_view name)
{
return const_cast<ConfigDefinition_ptr&>(
const_cast<const Configuration*>(this)->lookupDefinitionOrThrow(section, name));
}
void Configuration::visitSections(SectionVisitor visitor) const
{
for (const std::string& section : m_sectionOrdering)
{
const auto itr = m_definitions.find(section);
assert(itr != m_definitions.end());
visitor(section, itr->second);
}
};
void Configuration::visitDefinitions(const std::string& section, DefVisitor visitor) const
{
const auto& defs = m_definitions.at(section);
const auto& defOrdering = m_definitionOrdering.at(section);
for (const std::string& name : defOrdering)
{
const auto itr = defs.find(name);
assert(itr != defs.end());
visitor(name, itr->second);
}
};
} // namespace llarp

@ -8,6 +8,7 @@
#include <sstream>
#include <stdexcept>
#include <unordered_map>
#include <vector>
namespace llarp
{
@ -173,6 +174,16 @@ namespace llarp
ConfigDefinition_ptr& lookupDefinitionOrThrow(string_view section, string_view name);
const ConfigDefinition_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&)>;
void visitDefinitions(const std::string& section, DefVisitor visitor) const;
// track insertion order
std::vector<std::string> m_sectionOrdering;
std::unordered_map<std::string, std::vector<std::string>> m_definitionOrdering;
};
} // namespace llarp

@ -82,6 +82,7 @@ add_executable(${CATCH_EXE}
util/test_llarp_util_str.cpp
util/test_llarp_util_decaying_hashset.cpp
config/test_llarp_config_definition.cpp
config/test_llarp_config_output.cpp
check_main.cpp)
target_link_libraries(${CATCH_EXE} PUBLIC ${STATIC_LIB} Catch2::Catch2)

Loading…
Cancel
Save