/** * \copyright * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or * http://www.opengeosys.org/project/license * */ #include "ConfigTreeNew.h" #include <logog/include/logog.hpp> namespace BaseLib { //! Wraps a pair of iterators for use as a range in range-based for-loops. template<typename Iterator> class Range { public: explicit Range(Iterator begin, Iterator end) : _begin(begin), _end(end) {} Iterator begin() const { return _begin; } Iterator end() const { return _end; } private: Iterator _begin; Iterator _end; }; template<typename T> T ConfigTreeNew:: getConfParam(std::string const& param) const { if (auto p = getConfParamOptional<T>(param)) return *p; error("Key <" + param + "> has not been found"); } template<typename T> T ConfigTreeNew:: getConfParam(std::string const& param, T const& default_value) const { if (auto p = getConfParamOptional<T>(param)) return *p; return default_value; } template<typename T> boost::optional<T> ConfigTreeNew:: getConfParamOptional(std::string const& param) const { checkUnique(param); if (auto p = getConfSubtreeOptional(param)) return p->getValue<T>(); return boost::none; } template<typename T> Range<ConfigTreeNew::ValueIterator<T> > ConfigTreeNew:: getConfParamList(std::string const& param) const { checkUnique(param); markVisited<T>(param, false, true); auto p = _tree->equal_range(param); return Range<ValueIterator<T> >( ValueIterator<T>(p.first, param, *this), ValueIterator<T>(p.second, param, *this)); } template<typename T> T ConfigTreeNew:: peekConfParam(std::string const& param) const { checkKeyname(param); if (auto p =_tree->get_child_optional(param)) { try { return p->get_value<T>(); } catch (boost::property_tree::ptree_bad_data) { error("Value for key <" + param + "> `" + shortString(p->data()) + "' not convertible to the desired type."); } } else { error("Key <" + param + "> has not been found"); } } template<typename T> void ConfigTreeNew:: checkConfParam(std::string const& param, T const& value) const { if (getConfParam<T>(param) != value) { error("The value of key <" + param + "> is not the expected one."); } } template<typename Ch> void ConfigTreeNew:: checkConfParam(std::string const& param, Ch const* value) const { if (getConfParam<std::string>(param) != value) { error("The value of key <" + param + "> is not the expected one."); } } template<typename T> T ConfigTreeNew:: getValue() const { // TODO test this if (_have_read_data) { error("The data of this subtree has already been read."); } _have_read_data = true; if (auto v = _tree->get_value_optional<T>()) { return *v; } else { error("Value `" + shortString(_tree->data()) + "' is not convertible to the desired type."); } } template<typename T> T ConfigTreeNew:: getAttribute(std::string const& attr) const { checkUniqueAttr(attr); markVisited<T>(attr, true); if (auto attrs = _tree->get_child_optional("<xmlattr>")) { if (auto a = attrs->get_child_optional(attr)) { if (auto v = a->get_value_optional<T>()) { return *v; } else { error("Value for XML attribute \"" + attr + "\" `" + shortString(a->data()) + "' not convertible to the desired type."); } } else { error("No XML attribute named \"" + attr + "\""); } } else { error("This parameter has no XML attributes"); } } template<typename T> ConfigTreeNew::CountType& ConfigTreeNew:: markVisited(std::string const& key, bool const is_attr, bool const peek_only) const { auto const type = std::type_index(typeid(T)); auto p = _visited_params.emplace(std::make_pair(is_attr, key), CountType{peek_only ? 0 : 1, type}); if (!p.second) { // no insertion happened auto& v = p.first->second; if (v.type == type) { if (!peek_only) ++v.count; } else { error("There already was an attempt to obtain key <" + key + "> with type \"" + v.type.name() + "\" (now: \"" + type.name() + "\")."); } } return p.first->second; } }