diff --git a/stuff/configcontainer.hh b/stuff/configcontainer.hh new file mode 100644 index 0000000000000000000000000000000000000000..95142732b6ba64f0e61734981b043b80f038808c --- /dev/null +++ b/stuff/configcontainer.hh @@ -0,0 +1,146 @@ +#ifndef DUNE_STUFF_CONFIGCONTAINER_HH_INCLUDED +#define DUNE_STUFF_CONFIGCONTAINER_HH_INCLUDED + +#include <dune/stuff/deprecated.hh> // ensure DUNE_DEPRECATED is defined properly + +#include "logging.hh" +#include "filesystem.hh" +#include "misc.hh" +#include "validation.hh" + +#include <boost/format.hpp> + +#include <dune/common/parametertree.hh> +#include <dune/common/parametertreeparser.hh> +#include <dune/common/exceptions.hh> + +namespace Stuff { + +class ConfigContainer +{ +private: + template <typename T, class Validator> + T getValidValue(std::string name, T def, const ValidatorInterface<T, Validator> validator) + { + T val = tree_.get(name, def); + if (validator(val)) + return val; + std::stringstream ss; + validator.print(ss); + DUNE_THROW(Dune::ParameterInvalid, ss.str()); + } + +public: + ConfigContainer(const Dune::ParameterTree& tree) + : warning_output_(false) + , tree_(tree) + { + } + + ConfigContainer() + : warning_output_(true) + { + } + + void readCommandLine(int argc, char** argv) + { + if (argc < 2) { + boost::format usage("usage: %s parameter.file *[section.key:override-value]"); + DUNE_THROW(Dune::Exception, (usage % argv[0]).str()); + } + Dune::ParameterTreeParser::readINITree(argv[1], tree_); + for (int i = 1; i < argc; ++i) { + auto tokens = Stuff::stringTokenize(argv[i], ":"); + if (tokens.size() > 2) + tree_[tokens[0]] = tokens[1]; + } + } // ReadCommandLine + + /** \brief passthrough to underlying Dune::Parameter + * \param useDbgStream + * needs to be set to false when using this function in Logging::Create, + * otherwise an assertion will will cause streams aren't available yet + **/ + template <typename T> + T get(std::string name, T def, bool useDbgStream = true) + { + return get(name, def, Stuff::ValidateAny<T>(), useDbgStream); + } + + //! hack around the "string" is no string issue + std::string get(std::string name, const char* def, bool useDbgStream = true) + { + return get(name, std::string(def), Stuff::ValidateAny<std::string>(), useDbgStream); + } + + template <typename T, class Validator> + T get(std::string name, T def, const ValidatorInterface<T, Validator> validator, + bool UNUSED_UNLESS_DEBUG(useDbgStream) = true) + { + if (not validator(def)) + DUNE_THROW(Dune::ParameterInvalid, "default value invalid"); +#ifndef NDEBUG + if (warning_output_ && !tree_.hasKey(name)) { + if (useDbgStream) + Logger().Dbg() << "WARNING: using default value for parameter \"" << name << "\"" << std::endl; + else + std::cerr << "WARNING: using default value for parameter \"" << name << "\"" << std::endl; + } +#endif // ifndef NDEBUG + try { + return getValidValue(name, def, validator); + } catch (Dune::ParameterInvalid& p) { + std::cerr << boost::format("Parameter %s invalid: %s\n") % name % p.what(); + } + return def; + } // getParam + + //! hack around the "string" is no string issue + template <class Validator> + std::string get(std::string name, const char* def, const ValidatorInterface<std::string, Validator> validator, + bool useDbgStream = true) + { + return get<std::string, Validator>(name, def, validator, useDbgStream); + } + +private: + bool warning_output_; + Dune::ParameterTree tree_; +}; + +// ! global ConfigContainer instance +ConfigContainer& Config() +{ + static ConfigContainer parameters; + return parameters; +} + +} // end namespace Stuff +#endif // DUNE_STUFF_CONFIGCONTAINER_HH_INCLUDED +/** Copyright (c) 2012, Rene Milk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those + * of the authors and should not be interpreted as representing official policies, + * either expressed or implied, of the FreeBSD Project. + **/ diff --git a/stuff/validation.hh b/stuff/validation.hh new file mode 100644 index 0000000000000000000000000000000000000000..3d97e1603b4052d33d95e10bc1e5d94a4d202de5 --- /dev/null +++ b/stuff/validation.hh @@ -0,0 +1,182 @@ +#ifndef DUNE_STUFF_VALIDATION_HH +#define DUNE_STUFF_VALIDATION_HH + +#include <ostream> +#include <string> +#include <boost/format.hpp> + +#include "misc.hh" + +namespace Stuff { + +/** \brief Base class for all Validators + * the idea is from dune-fem, only our class is an actual interface + **/ +template <class T, class Derived> +class ValidatorInterface +{ +public: + bool operator()(const T& value) const + { + return asImp()(value); + } + + std::string msg() const + { + return asImp().msg(); + } + void print(std::ostream& out) const + { + out << asImp().msg(); + } + +protected: + inline const Derived& asImp() const + { + return static_cast<const Derived&>(*this); + } + + inline Derived& asImp() + { + return static_cast<Derived&>(*this); + } +}; + +// ! a class usable as a default validator +template <class T> +class ValidateAny : public Stuff::ValidatorInterface<T, ValidateAny<T>> +{ + typedef ValidateAny<T> ThisType; + typedef ValidatorInterface<T, ThisType> BaseType; + +public: + inline ValidateAny() + { + } + inline ValidateAny(const ThisType&) + { + } + + inline bool operator()(const T&) const + { + return true; + } + + std::string msg() const + { + return "ValidateAny: all values should be valid... \n\n"; + } +}; + +// ! validates arg iff in given list +template <class T, class ListImp = std::vector<T>> +class ValidateInList : public Stuff::ValidatorInterface<T, ValidateInList<T, ListImp>> +{ + typedef ValidateInList<T, ListImp> ThisType; + typedef ValidatorInterface<T, ThisType> BaseType; + typedef ListImp ListType; + ListType valid_list_; + +public: + ValidateInList(const ListType& valid_list) + : valid_list_(valid_list) + { + } + + inline bool operator()(const T& val) const + { + return std::find(valid_list_.begin(), valid_list_.end(), val) != valid_list_.end(); + } + + std::string msg() const + { + return "ValidateInList: checked Parameter was not in valid list\n\n"; + } +}; + +//! validate arg iff less than value, obviously +template <class T> +class ValidateLess : public ValidatorInterface<T, ValidateLess<T>> +{ +public: + ValidateLess(const T& max) + : max_(max) + { + } + inline bool operator()(const T& val) const + { + return val < max_; + } + + std::string msg() const + { + return (boost::format("given value was invalid: not less than %s") % toString(max_)).str(); + } + +private: + const T max_; +}; + +//! validate iff not Validator(arg) +template <class T, class Validator> +class ValidateInverse : public ValidatorInterface<T, ValidateInverse<T, Validator>> +{ +public: + ValidateInverse(const Validator validator = Validator()) + : validator_(validator) + { + } + inline bool operator()(const T& val) const + { + return !validator_(val); + } + + std::string msg() const + { + return "Inverse condition failed"; + } + +private: + const Validator validator_; +}; + +//! validate arg iff arg \in [min,max] +template <class T> +class ValidateInterval : public ValidatorInterface<T, ValidateInterval<T>> +{ +public: + ValidateInterval(const T& min, const T& max) + : min_(min) + , max_(max) + { + } + + inline bool operator()(const T& val) const + { + return min_(val) && ValidateInverse<T, ValidateLess<T>>(val)(max_); + } + + std::string msg() const + { + return "given value was invalid: value not in given interval"; + } + +private: + const ValidateInverse<T, ValidateLess<T>> min_; + const T max_; +}; + +template <class T> +struct ValidateNone : public ValidateInverse<T, ValidateAny<T>> +{ +}; + +} // end namesapce Stuff + +template <class T, class Validator> +std::ostream operator<<(std::ostream& out, const Stuff::ValidatorInterface<T, Validator>& validator) +{ + return out << validator.msg(); +} + +#endif // DUNE_STUFF_VALIDATION_HH