/*+ ARES/HADES/BORG Package -- ./libLSS/tools/ptree_proxy.hpp Copyright (C) 2020 Guilhem Lavaux Copyright (C) 2009-2020 Jens Jasche Additional contributions from: Guilhem Lavaux (2023) +*/ #pragma once #ifndef __LIBLSS_PTREE_PROXY_HPP # define __LIBLSS_PTREE_PROXY_HPP # include # include # include "libLSS/tools/ptree_translators.hpp" # include # include namespace LibLSS { class PropertyProxy { protected: typedef boost::variant PropertyType; virtual PropertyType real_get(std::string const &n, std::type_index v) const = 0; virtual PropertyType real_get(std::string const &n, PropertyType v) const = 0; virtual boost::optional real_get_optional(std::string const &n, std::type_index v) const = 0; public: PropertyProxy() {} ~PropertyProxy() {} template inline T get(std::string const &n) const { return boost::get(real_get(n, typeid(T))); } template inline T get(std::string const &n, T def_value) const { return boost::get(real_get(n, PropertyType(def_value))); } template inline boost::optional get_optional(std::string const &n) const { auto ret = real_get_optional(n, typeid(T)); if (!ret) return boost::optional(); else return boost::optional(boost::get(*ret)); } }; template class PropertyProxyPtree : public PropertyProxy { protected: typedef ptree PropertyTree; PropertyTree tree; std::map> getters; std::map< std::type_index, std::function(std::string const &)>> optional_getters; virtual boost::optional real_get_optional(std::string const &n, std::type_index ti) const { return optional_getters.find(ti)->second(n); } virtual PropertyType real_get(std::string const &n, std::type_index ti) const { return getters.find(ti)->second(n); } virtual PropertyType real_get(std::string const &n, PropertyType v) const { return boost::apply_visitor( [this, &n, &v](auto v_hint) { auto o = this->tree.template get_optional(n); if (o) return PropertyType(*o); return v; }, v); } template PropertyType implement_getter(std::string const &n) const { return this->tree.template get(n); } template boost::optional implement_optional_getter(std::string const &n) const { auto ret = this->tree.template get_optional(n); if (!ret) return boost::optional(); return boost::optional(*ret); } template inline void setup_getters(boost::variant) { getters[typeid(U)] = std::bind( &PropertyProxyPtree::implement_getter, this, std::placeholders::_1); optional_getters[typeid(U)] = std::bind( &PropertyProxyPtree::implement_optional_getter, this, std::placeholders::_1); } template inline void setup_getters(boost::variant) { getters[typeid(U)] = std::bind( &PropertyProxyPtree::implement_getter, this, std::placeholders::_1); optional_getters[typeid(U)] = std::bind( &PropertyProxyPtree::implement_optional_getter, this, std::placeholders::_1); setup_getters(boost::variant()); } public: PropertyProxyPtree(PropertyTree &tree_) : tree(tree_) { setup_getters(PropertyType()); } PropertyProxyPtree(boost::optional tree_) { if (tree_) tree = *tree_; setup_getters(PropertyType()); } ~PropertyProxyPtree() {} }; template auto make_proxy_property_tree(T &tree_) { return PropertyProxyPtree(tree_); } template auto make_proxy_property_tree(boost::optional tree_) { return PropertyProxyPtree(tree_); } } // namespace LibLSS #endif // ARES TAG: num_authors = 1 // ARES TAG: name(0) = Guilhem Lavaux // ARES TAG: year(0) = 2020 // ARES TAG: email(0) = guilhem.lavaux@iap.fr