From 76cddf9d25383cd1774f9365aff0e52a876f2b1f Mon Sep 17 00:00:00 2001 From: vargheseg <vargheseg@users.noreply.github.com> Date: Thu, 11 Apr 2019 14:56:11 +0200 Subject: [PATCH] Introduced class ModuleList ModuleList serves as a container for VariableGroups. The VariableGroups mirror xml modules in the config file. --- Modules/include/ConfigReader.h | 6 ++ Modules/src/ConfigReader.cc | 151 +++++++++++++++++++++++---------- 2 files changed, 114 insertions(+), 43 deletions(-) diff --git a/Modules/include/ConfigReader.h b/Modules/include/ConfigReader.h index 05f8038c..b8478a80 100644 --- a/Modules/include/ConfigReader.h +++ b/Modules/include/ConfigReader.h @@ -13,6 +13,7 @@ namespace ChimeraTK { struct ArrayFunctorFill; struct FunctorSetValues; struct FunctorSetValuesArray; + class ModuleList; /** Generic module to read an XML config file and provide the defined values as * constant variables. The config file should look like this: @@ -45,6 +46,7 @@ namespace ChimeraTK { ConfigReader(EntityOwner* owner, const std::string& name, const std::string& fileName, const std::unordered_set<std::string>& tags = {}); + ~ConfigReader() override; void mainLoop() override {} void prepare() override; @@ -56,9 +58,12 @@ namespace ChimeraTK { const T& get(const std::string& variableName) const; protected: + /** File name */ std::string _fileName; + std::unique_ptr<ModuleList> _moduleList; + /** throw a parsing error with more information */ void parsingError(const std::string& message); @@ -118,6 +123,7 @@ namespace ChimeraTK { template<typename T> const std::vector<T>& get_impl(const std::string& variableName, std::vector<T>*) const; + friend struct FunctorFill; friend struct ArrayFunctorFill; friend struct FunctorSetValues; diff --git a/Modules/src/ConfigReader.cc b/Modules/src/ConfigReader.cc index 57159d85..8de8b8cd 100644 --- a/Modules/src/ConfigReader.cc +++ b/Modules/src/ConfigReader.cc @@ -1,6 +1,7 @@ #include <libxml++/libxml++.h> #include "ConfigReader.h" +#include<iostream> namespace ChimeraTK { @@ -14,6 +15,9 @@ void prefix(std::string s, List& varList){ } } +std::string parent(std::string flattened_name); +std::string leaf(std::string flattened_name); + struct Variable { std::string name; std::string type; @@ -58,62 +62,78 @@ private: std::map<size_t, std::string> gettArrayValues(const xmlpp::Element * element); }; +class ModuleList { + std::unordered_map<std::string, ChimeraTK::VariableGroup> map_; + ChimeraTK::Module* owner_; - /*********************************************************************************************************************/ +public: + ModuleList(ChimeraTK::Module* o):owner_(o){} + ChimeraTK::Module *lookup(std::string flattened_module_name); + ChimeraTK::Module *get(std::string flattened_name); +}; - /** Functor to fill variableMap */ - struct FunctorFill { - FunctorFill(ConfigReader* owner, const std::string& type, const std::string& name, const std::string& value, - bool& processed) - : _owner(owner), _type(type), _name(name), _value(value), _processed(processed) {} +/*********************************************************************************************************************/ - template<typename PAIR> - void operator()(PAIR&) const { - // extract the user type from the pair - typedef typename PAIR::first_type T; +/** Functor to fill variableMap */ +struct FunctorFill { + FunctorFill(ConfigReader *owner, const std::string &type, + const std::string &name, const std::string &value, + bool &processed) + : _owner(owner), _type(type), _name(name), _value(value), + _processed(processed) {} - // skip this type, if not matching the type string in the config file - if(_type != boost::fusion::at_key<T>(_owner->typeMap)) return; + template <typename PAIR> void operator()(PAIR &) const { + // extract the user type from the pair + typedef typename PAIR::first_type T; - _owner->createVar<T>(_name, _value); - _processed = true; - } + // skip this type, if not matching the type string in the config file + if (_type != boost::fusion::at_key<T>(_owner->typeMap)) + return; - ConfigReader* _owner; - const std::string &_type, &_name, &_value; - bool& _processed; // must be a non-const reference, since we want to return - // this to the caller + _owner->createVar<T>(_name, _value); + _processed = true; + } + + ConfigReader *_owner; + const std::string &_type, &_name, &_value; + bool &_processed; // must be a non-const reference, since we want to return + // this to the caller - typedef boost::fusion::pair<std::string, ConfigReader::Var<std::string>> StringPair; + typedef boost::fusion::pair<std::string, ConfigReader::Var<std::string>> + StringPair; }; /*********************************************************************************************************************/ /** Functor to fill variableMap for arrays */ struct ArrayFunctorFill { - ArrayFunctorFill(ConfigReader* owner, const std::string& type, const std::string& name, - const std::map<size_t, std::string>& values, bool& processed) - : _owner(owner), _type(type), _name(name), _values(values), _processed(processed) {} - - template<typename PAIR> - void operator()(PAIR&) const { + ArrayFunctorFill(ConfigReader *owner, const std::string &type, + const std::string &name, + const std::map<size_t, std::string> &values, + bool &processed) + : _owner(owner), _type(type), _name(name), _values(values), + _processed(processed) {} + + template <typename PAIR> void operator()(PAIR &) const { // extract the user type from the pair typedef typename PAIR::first_type T; // skip this type, if not matching the type string in the config file - if(_type != boost::fusion::at_key<T>(_owner->typeMap)) return; + if (_type != boost::fusion::at_key<T>(_owner->typeMap)) + return; _owner->createArray<T>(_name, _values); _processed = true; } - ConfigReader* _owner; + ConfigReader *_owner; const std::string &_type, &_name; - const std::map<size_t, std::string>& _values; - bool& _processed; // must be a non-const reference, since we want to return + const std::map<size_t, std::string> &_values; + bool &_processed; // must be a non-const reference, since we want to return // this to the caller - typedef boost::fusion::pair<std::string, ConfigReader::Var<std::string>> StringPair; + typedef boost::fusion::pair<std::string, ConfigReader::Var<std::string>> + StringPair; }; /*********************************************************************************************************************/ @@ -134,8 +154,11 @@ private: } // place the variable onto the vector + auto moduleName = parent(name); + auto varName = leaf(name); + auto varOwner = _moduleList->lookup(moduleName); std::map<std::string, ConfigReader::Var<T>>& theMap = boost::fusion::at_key<T>(variableMap.table); - theMap.emplace(std::make_pair(name, ConfigReader::Var<T>(this, name, convertedValue))); + theMap.emplace(std::make_pair(name, ConfigReader::Var<T>(varOwner, varName, convertedValue))); } /*********************************************************************************************************************/ @@ -143,9 +166,11 @@ private: template<> void ConfigReader::createVar<std::string>(const std::string& name, const std::string& value) { // place the variable onto the vector - std::map<std::string, ConfigReader::Var<std::string>>& theMap = - boost::fusion::at_key<std::string>(variableMap.table); - theMap.emplace(std::make_pair(name, ConfigReader::Var<std::string>(this, name, value))); + auto moduleName = parent(name); + auto varName = leaf(name); + auto varOwner = _moduleList->lookup(moduleName); + std::map<std::string, ConfigReader::Var<std::string>>& theMap = boost::fusion::at_key<std::string>(variableMap.table); + theMap.emplace(std::make_pair(name, ConfigReader::Var<std::string>(varOwner, varName, value))); } /*********************************************************************************************************************/ @@ -183,8 +208,12 @@ private: } // place the variable onto the vector + auto module_name = parent(name); + auto array_name = leaf(name); + auto arrayOwner = _moduleList->lookup(module_name); + std::map<std::string, ConfigReader::Array<T>>& theMap = boost::fusion::at_key<T>(arrayMap.table); - theMap.emplace(std::make_pair(name, ConfigReader::Array<T>(this, name, Tvalues))); + theMap.emplace(std::make_pair( name, ConfigReader::Array<T>(arrayOwner, array_name, Tvalues))); } /*********************************************************************************************************************/ @@ -208,16 +237,19 @@ private: } // place the variable onto the vector - std::map<std::string, ConfigReader::Array<std::string>>& theMap = - boost::fusion::at_key<std::string>(arrayMap.table); - theMap.emplace(std::make_pair(name, ConfigReader::Array<std::string>(this, name, Tvalues))); + auto module_name = parent(name); + auto array_name = leaf(name); + auto arrayOwner = _moduleList->lookup(module_name); + + std::map<std::string, ConfigReader::Array<std::string>>& theMap = boost::fusion::at_key<std::string>(arrayMap.table); + theMap.emplace(std::make_pair( name, ConfigReader::Array<std::string>(arrayOwner, array_name, Tvalues))); } /*********************************************************************************************************************/ ConfigReader::ConfigReader(EntityOwner* owner, const std::string& name, const std::string& fileName, const std::unordered_set<std::string>& tags) : ApplicationModule(owner, name, "Configuration read from file '" + fileName + "'", false, tags), - _fileName(fileName) { + _fileName(fileName), _moduleList(std::make_unique<ModuleList>(this)) { auto fillVariableMap = [this](const Variable &var) { bool processed{false}; @@ -254,6 +286,7 @@ private: } } + ConfigReader::~ConfigReader() = default; /********************************************************************************************************************/ void ConfigReader::parsingError(const std::string& message) { @@ -315,6 +348,37 @@ private: /*********************************************************************************************************************/ + ChimeraTK::Module *ModuleList::lookup(std::string flattened_module_name) { + return get(flattened_module_name); + } + + ChimeraTK::Module *ModuleList::get(std::string flattened_name) { + if (flattened_name == "") { + return owner_; + } + auto e = map_.find(flattened_name); + + if (e == map_.end()) { + auto module_name = leaf(flattened_name); + auto owner = get(parent(flattened_name)); + + map_[flattened_name] = ChimeraTK::VariableGroup(owner, module_name, ""); + return &map_[flattened_name]; + } + return &e->second; + } + + std::string parent(std::string flattened_name) { + auto pos = flattened_name.find_last_of('/'); + pos = (pos == std::string::npos) ? 0 : pos; + return flattened_name.substr(0, pos); + } + + std::string leaf(std::string flattened_name) { + auto pos = flattened_name.find_last_of('/'); + return flattened_name.substr(pos + 1, flattened_name.size()); + } + std::unique_ptr<VariableList> ConfigParser::getVariableList() { if (variableList_ == nullptr) { std::tie(variableList_, arrayList_) = parse(); @@ -340,9 +404,10 @@ std::tuple<std::unique_ptr<VariableList>, std::unique_ptr<ArrayList>> ConfigPars std::tuple<std::unique_ptr<VariableList>, std::unique_ptr<ArrayList>> ConfigParser::parseModule(const xmlpp::Element * element) { - auto module_name = (element->get_name() == "configuration")? - "": - element->get_name() + "/"; + auto module_name = (element->get_name() == "configuration") + ? "" + : element->get_attribute("name")->get_value() + "/"; + auto v = std::make_unique<VariableList>(); auto a = std::make_unique<ArrayList>(); -- GitLab