From 1b19314278befef469ad078d83334492348a32ed Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Tue, 17 Mar 2020 15:17:35 -0600 Subject: [PATCH] Implement Configuration::generateDefaultConfig(), maintain insertion order --- llarp/config/definition.cpp | 113 ++++++++++++++++++++++-------------- llarp/config/definition.hpp | 11 ++++ test/CMakeLists.txt | 1 + 3 files changed, 81 insertions(+), 44 deletions(-) diff --git a/llarp/config/definition.cpp b/llarp/config/definition.cpp index d1b8eb59a..410578b6e 100644 --- a/llarp/config/definition.cpp +++ b/llarp/config/definition.cpp @@ -1,29 +1,11 @@ #include +#include #include namespace llarp { -/// utility functions for visiting each section/definition -/// -using SectionVisitor = std::function; -void visitSections(const SectionMap& sections, SectionVisitor visitor) -{ - for (const auto& pair : sections) - { - visitor(pair.first, pair.second); - } -}; -using DefVisitor = std::function; -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( - const_cast(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( + const_cast(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 diff --git a/llarp/config/definition.hpp b/llarp/config/definition.hpp index d765a16c3..cea993a44 100644 --- a/llarp/config/definition.hpp +++ b/llarp/config/definition.hpp @@ -8,6 +8,7 @@ #include #include #include +#include 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 visitSections(SectionVisitor visitor) const; + + using DefVisitor = std::function; + void visitDefinitions(const std::string& section, DefVisitor visitor) const; + + // track insertion order + std::vector m_sectionOrdering; + std::unordered_map> m_definitionOrdering; }; } // namespace llarp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d788fd16d..9246a6256 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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)