diff --git a/src/io/parser/parameter_registry.cc b/src/io/parser/parameter_registry.cc index 264ef1822..ead59bdca 100644 --- a/src/io/parser/parameter_registry.cc +++ b/src/io/parser/parameter_registry.cc @@ -1,152 +1,152 @@ /** * @file parameter_registry.cc * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Nov 19 2015 * * @brief Parameter Registry and derived classes implementation * * @section LICENSE * * Copyright (©) 2014, 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "parameter_registry.hh" /* -------------------------------------------------------------------------- */ namespace akantu { Parameter::Parameter() : name(""), description(""), param_type(_pat_internal) {} /* -------------------------------------------------------------------------- */ Parameter::Parameter(std::string name, std::string description, ParameterAccessType param_type) : name(name), description(description), param_type(param_type) {} /* -------------------------------------------------------------------------- */ bool Parameter::isWritable() const { return param_type & _pat_writable; } /* -------------------------------------------------------------------------- */ bool Parameter::isReadable() const { return param_type & _pat_readable; } /* -------------------------------------------------------------------------- */ bool Parameter::isInternal() const { return param_type & _pat_internal; } /* -------------------------------------------------------------------------- */ bool Parameter::isParsable() const { return param_type & _pat_parsable; } /* -------------------------------------------------------------------------- */ void Parameter::setAccessType(ParameterAccessType ptype) { this->param_type = ptype; } /* -------------------------------------------------------------------------- */ void Parameter::printself(std::ostream & stream) const { stream << " "; if (isInternal()) stream << "iii"; else { if (isReadable()) stream << "r"; else stream << "-"; if (isWritable()) stream << "w"; else stream << "-"; if (isParsable()) stream << "p"; else stream << "-"; } stream << " "; std::stringstream sstr; sstr << name; UInt width = std::max(int(10 - sstr.str().length()), 0); sstr.width(width); if (description != "") { sstr << " [" << description << "]"; } stream << sstr.str(); width = std::max(int(50 - sstr.str().length()), 0); stream.width(width); stream << " : "; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ ParameterRegistry::ParameterRegistry() : consisder_sub(true) { } /* -------------------------------------------------------------------------- */ ParameterRegistry::~ParameterRegistry() { std::map::iterator it, end; for (it = params.begin(); it != params.end(); ++it) { delete it->second; it->second = NULL; } this->params.clear(); } /* -------------------------------------------------------------------------- */ void ParameterRegistry::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; Parameters::const_iterator it; for (it = params.begin(); it != params.end(); ++it) { stream << space; it->second->printself(stream); } SubRegisteries::const_iterator sub_it; for (sub_it = sub_registries.begin(); sub_it != sub_registries.end(); ++sub_it) { stream << space << "Registry [" << std::endl; sub_it->second->printself(stream, indent + 1); stream << space << "]"; } } /* -------------------------------------------------------------------------- */ void ParameterRegistry::registerSubRegistry(const ID & id, ParameterRegistry & registry) { sub_registries[id] = ®istry; } /* -------------------------------------------------------------------------- */ void ParameterRegistry::setParameterAccessType(const std::string & name, ParameterAccessType ptype) { Parameters::iterator it = params.find(name); if (it == params.end()) - AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); + AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this)); Parameter & param = *(it->second); param.setAccessType(ptype); } } // akantu diff --git a/src/io/parser/parameter_registry.hh b/src/io/parser/parameter_registry.hh index 60d4c56b4..913b81f80 100644 --- a/src/io/parser/parameter_registry.hh +++ b/src/io/parser/parameter_registry.hh @@ -1,202 +1,217 @@ /** * @file parameter_registry.hh * * @author Nicolas Richart * * @date creation: Thu Aug 09 2012 * @date last modification: Thu Dec 17 2015 * * @brief Interface of the parameter registry * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PARAMETER_REGISTRY_HH__ #define __AKANTU_PARAMETER_REGISTRY_HH__ namespace akantu { class ParserParameter; } namespace akantu { /* -------------------------------------------------------------------------- */ /// Defines the access modes of parsable parameters enum ParameterAccessType { _pat_internal = 0x0001, _pat_writable = 0x0010, _pat_readable = 0x0100, _pat_modifiable = 0x0110, //<_pat_readable | _pat_writable, _pat_parsable = 0x1000, _pat_parsmod = 0x1110 //< _pat_parsable | _pat_modifiable }; /// Bit-wise operator between access modes inline ParameterAccessType operator|(const ParameterAccessType & a, const ParameterAccessType & b) { ParameterAccessType tmp = ParameterAccessType(UInt(a) | UInt(b)); return tmp; } /* -------------------------------------------------------------------------- */ template class ParameterTyped; /** * Interface for the Parameter */ class Parameter { public: Parameter(); Parameter(std::string name, std::string description, ParameterAccessType param_type); virtual ~Parameter() = default; /* ------------------------------------------------------------------------ */ bool isInternal() const; bool isWritable() const; bool isReadable() const; bool isParsable() const; void setAccessType(ParameterAccessType ptype); /* ------------------------------------------------------------------------ */ template void set(const V & value); virtual void setAuto(const ParserParameter & param); template T & get(); template const T & get() const; virtual inline operator Real() const { throw std::bad_cast(); }; template inline operator T() const; /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream) const; + virtual const std::type_info& type() const = 0; protected: /// Returns const instance of templated sub-class ParameterTyped template const ParameterTyped & getParameterTyped() const; /// Returns instance of templated sub-class ParameterTyped template ParameterTyped & getParameterTyped(); protected: /// Name of parameter std::string name; private: /// Description of parameter std::string description; /// Type of access ParameterAccessType param_type; }; /* -------------------------------------------------------------------------- */ /* Typed Parameter */ /* -------------------------------------------------------------------------- */ /** * Type parameter transfering a ParserParameter (string: string) to a typed * parameter in the memory of the p */ template class ParameterTyped : public Parameter { public: ParameterTyped(std::string name, std::string description, ParameterAccessType param_type, T & param); /* ------------------------------------------------------------------------ */ template void setTyped(const V & value); void setAuto(const ParserParameter & param); T & getTyped(); const T & getTyped() const; virtual void printself(std::ostream & stream) const; inline operator Real() const; + + inline const std::type_info& type() const override { return typeid(T); } private: /// Value of parameter T & param; }; /* -------------------------------------------------------------------------- */ /* Parsable Interface */ /* -------------------------------------------------------------------------- */ /// Defines interface for classes to manipulate parsable parameters class ParameterRegistry { public: ParameterRegistry(); virtual ~ParameterRegistry(); /* ------------------------------------------------------------------------ */ /// Add parameter to the params map template void registerParam(std::string name, T & variable, ParameterAccessType type, - const std::string description = ""); + const std::string & description = ""); /// Add parameter to the params map (with default value) template void registerParam(std::string name, T & variable, const T & default_value, ParameterAccessType type, - const std::string description = ""); + const std::string & description = ""); /*------------------------------------------------------------------------- */ protected: void registerSubRegistry(const ID & id, ParameterRegistry & registry); /* ------------------------------------------------------------------------ */ public: /// Set value to a parameter (with possible different type) template void setMixed(const std::string & name, const V & value); /// Set value to a parameter template void set(const std::string & name, const T & value); /// Get value of a parameter inline const Parameter & get(const std::string & name) const; + std::vector listParameters() const { + std::vector params; + for(auto & pair : this->params) params.push_back(pair.first); + return params; + } + + std::vector listSubRegisteries() const { + std::vector subs; + for(auto & pair : this->sub_registries) subs.push_back(pair.first); + return subs; + } + protected: template T & get(const std::string & name); protected: void setParameterAccessType(const std::string & name, ParameterAccessType ptype); /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream, int indent) const; protected: /// Parameters map typedef std::map Parameters; Parameters params; /// list of sub-registries typedef std::map SubRegisteries; SubRegisteries sub_registries; /// should accessor check in sub registries bool consisder_sub; }; } // akantu #include "parameter_registry_tmpl.hh" #endif /* __AKANTU_PARAMETER_REGISTRY_HH__ */ diff --git a/src/io/parser/parameter_registry_tmpl.hh b/src/io/parser/parameter_registry_tmpl.hh index 0a3bf0458..38f58e3be 100644 --- a/src/io/parser/parameter_registry_tmpl.hh +++ b/src/io/parser/parameter_registry_tmpl.hh @@ -1,324 +1,346 @@ /** * @file parameter_registry_tmpl.hh * * @author Nicolas Richart * * @date creation: Thu Aug 09 2012 * @date last modification: Fri Mar 27 2015 * * @brief implementation of the templated part of ParameterRegistry class and * the derivated ones * * @section LICENSE * * Copyright (©) 2010-2012, 2014, 2015 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_error.hh" +#include "parameter_registry.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ +#include #include /* -------------------------------------------------------------------------- */ +#ifndef __AKANTU_PARAMETER_REGISTRY_TMPL_HH__ +#define __AKANTU_PARAMETER_REGISTRY_TMPL_HH__ + namespace akantu { namespace debug { class ParameterException : public Exception { public: ParameterException(const std::string & name, const std::string & message) : Exception(message), name(name) {} const std::string & name; }; class ParameterUnexistingException : public ParameterException { public: - ParameterUnexistingException(const std::string & name) + ParameterUnexistingException(const std::string & name, + const ParameterRegistry & registery) : ParameterException(name, "Parameter " + name + - " does not exists in this scope") {} + " does not exists in this scope") { + auto && params = registery.listParameters(); + this->_info = + std::accumulate(params.begin(), params.end(), + this->_info + "\n Possible parameters are: ", + [](auto && str, auto && param) { + static auto first = true; + auto && ret = str + (first ? " " : ", ") + param; + first = false; + return ret; + }); + } }; class ParameterAccessRightException : public ParameterException { public: ParameterAccessRightException(const std::string & name, const std::string & perm) : ParameterException(name, "Parameter " + name + " is not " + perm) {} }; class ParameterWrongTypeException : public ParameterException { public: ParameterWrongTypeException(const std::string name, - const std::string & type) - : ParameterException(name, - "Parameter " + name + " is not of type " + type) {} + const std::type_info & wrong_type, + const std::type_info & type) + : ParameterException(name, "Parameter " + name + + " type error, cannot convert " + + debug::demangle(type.name()) + " to " + + debug::demangle(wrong_type.name())) {} }; } // namespace debug /* -------------------------------------------------------------------------- */ template const ParameterTyped & Parameter::getParameterTyped() const { try { const ParameterTyped & tmp = dynamic_cast &>(*this); return tmp; } catch (std::bad_cast &) { - AKANTU_CUSTOM_EXCEPTION(debug::ParameterWrongTypeException( - name, debug::demangle(typeid(T).name()))); + AKANTU_CUSTOM_EXCEPTION( + debug::ParameterWrongTypeException(name, typeid(T), this->type())); } } /* -------------------------------------------------------------------------- */ template ParameterTyped & Parameter::getParameterTyped() { try { ParameterTyped & tmp = dynamic_cast &>(*this); return tmp; - } catch (...) { - AKANTU_CUSTOM_EXCEPTION(debug::ParameterWrongTypeException( - name, debug::demangle(typeid(T).name()))); + } catch (std::bad_cast &) { + AKANTU_CUSTOM_EXCEPTION( + debug::ParameterWrongTypeException(name, typeid(T), this->type())); } } /* ------------------------------------------------------------------------ */ template void Parameter::set(const V & value) { if (!(isWritable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "writable")); ParameterTyped & typed_param = getParameterTyped(); typed_param.setTyped(value); } /* ------------------------------------------------------------------------ */ inline void Parameter::setAuto(__attribute__((unused)) const ParserParameter & value) { if (!(isParsable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "parsable")); } /* -------------------------------------------------------------------------- */ template const T & Parameter::get() const { if (!(isReadable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "readable")); const ParameterTyped & typed_param = getParameterTyped(); return typed_param.getTyped(); } /* -------------------------------------------------------------------------- */ template T & Parameter::get() { ParameterTyped & typed_param = getParameterTyped(); if (!(isReadable()) || !(this->isWritable())) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "accessible")); return typed_param.getTyped(); } /* -------------------------------------------------------------------------- */ template inline Parameter::operator T() const { return this->get(); } /* -------------------------------------------------------------------------- */ template ParameterTyped::ParameterTyped(std::string name, std::string description, ParameterAccessType param_type, T & param) : Parameter(name, description, param_type), param(param) {} /* -------------------------------------------------------------------------- */ template template void ParameterTyped::setTyped(const V & value) { param = value; } /* -------------------------------------------------------------------------- */ template inline void ParameterTyped::setAuto(const ParserParameter & value) { Parameter::setAuto(value); param = static_cast(value); } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped::setAuto(const ParserParameter & value) { Parameter::setAuto(value); param = value.getValue(); } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped>::setAuto(const ParserParameter & in_param) { Parameter::setAuto(in_param); Vector tmp = in_param; for (UInt i = 0; i < param.size(); ++i) { param(i) = tmp(i); } } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped>::setAuto(const ParserParameter & in_param) { Parameter::setAuto(in_param); Matrix tmp = in_param; for (UInt i = 0; i < param.rows(); ++i) { for (UInt j = 0; j < param.cols(); ++j) { param(i, j) = tmp(i, j); } } } /* -------------------------------------------------------------------------- */ template const T & ParameterTyped::getTyped() const { return param; } /* -------------------------------------------------------------------------- */ template T & ParameterTyped::getTyped() { return param; } /* -------------------------------------------------------------------------- */ template inline void ParameterTyped::printself(std::ostream & stream) const { Parameter::printself(stream); stream << param << std::endl; } /* -------------------------------------------------------------------------- */ template <> inline void ParameterTyped::printself(std::ostream & stream) const { Parameter::printself(stream); stream << std::boolalpha << param << std::endl; } /* -------------------------------------------------------------------------- */ template void ParameterRegistry::registerParam(std::string name, T & variable, ParameterAccessType type, - const std::string description) { + const std::string & description) { std::map::iterator it = params.find(name); if (it != params.end()) AKANTU_CUSTOM_EXCEPTION(debug::ParameterException( name, "Parameter named " + name + " already registered.")); ParameterTyped * param = new ParameterTyped(name, description, type, variable); params[name] = param; } /* -------------------------------------------------------------------------- */ template void ParameterRegistry::registerParam(std::string name, T & variable, const T & default_value, ParameterAccessType type, - const std::string description) { + const std::string & description) { variable = default_value; registerParam(name, variable, type, description); } /* -------------------------------------------------------------------------- */ template void ParameterRegistry::setMixed(const std::string & name, const V & value) { std::map::iterator it = params.find(name); if (it == params.end()) { if (consisder_sub) { for (SubRegisteries::iterator it = sub_registries.begin(); it != sub_registries.end(); ++it) { it->second->setMixed(name, value); } } else { - AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); + AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this)); } } else { Parameter & param = *(it->second); param.set(value); } } /* -------------------------------------------------------------------------- */ template void ParameterRegistry::set(const std::string & name, const T & value) { this->template setMixed(name, value); } /* -------------------------------------------------------------------------- */ template T & ParameterRegistry::get(const std::string & name) { Parameters::iterator it = params.find(name); if (it == params.end()) { if (consisder_sub) { for (SubRegisteries::iterator it = sub_registries.begin(); it != sub_registries.end(); ++it) { try { return it->second->get(name); } catch (...) { } } } // nothing was found not even in sub registries AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); } Parameter & param = *(it->second); return param.get(); } /* -------------------------------------------------------------------------- */ const Parameter & ParameterRegistry::get(const std::string & name) const { Parameters::const_iterator it = params.find(name); if (it == params.end()) { if (consisder_sub) { for (SubRegisteries::const_iterator it = sub_registries.begin(); it != sub_registries.end(); ++it) { try { return it->second->get(name); } catch (...) { } } } // nothing was found not even in sub registries - AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name)); + AKANTU_CUSTOM_EXCEPTION(debug::ParameterUnexistingException(name, *this)); } Parameter & param = *(it->second); return param; } /* -------------------------------------------------------------------------- */ namespace { namespace details { template struct CastHelper { static R convert(const T &) { throw std::bad_cast(); } }; template struct CastHelper::value>> { static R convert(const T & val) { return val; } }; } // namespace details } // namespace template inline ParameterTyped::operator Real() const { if (not isReadable()) AKANTU_CUSTOM_EXCEPTION( debug::ParameterAccessRightException(name, "accessible")); return details::CastHelper::convert(param); } } // namespace akantu + +#endif /* __AKANTU_PARAMETER_REGISTRY_TMPL_HH__ */