| /* |
| * Copyright Andrey Semashev 2007 - 2015. |
| * Distributed under the Boost Software License, Version 1.0. |
| * (See accompanying file LICENSE_1_0.txt or copy at |
| * http://www.boost.org/LICENSE_1_0.txt) |
| */ |
| /*! |
| * \file settings.hpp |
| * \author Andrey Semashev |
| * \date 11.10.2009 |
| * |
| * The header contains definition of the library settings container. |
| */ |
| |
| #ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ |
| #define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ |
| |
| #include <cstddef> |
| #include <string> |
| #include <iterator> |
| #include <boost/assert.hpp> |
| #include <boost/move/core.hpp> |
| #include <boost/mpl/if.hpp> |
| #include <boost/iterator/iterator_adaptor.hpp> |
| #include <boost/optional/optional.hpp> |
| #include <boost/property_tree/ptree.hpp> |
| #include <boost/log/detail/setup_config.hpp> |
| #include <boost/log/detail/native_typeof.hpp> |
| #include <boost/utility/explicit_operator_bool.hpp> |
| #if !defined(BOOST_LOG_TYPEOF) |
| #include <boost/utility/enable_if.hpp> |
| #endif |
| #if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) |
| #include <boost/utility/declval.hpp> |
| #endif |
| #include <boost/log/detail/header.hpp> |
| |
| #ifdef BOOST_HAS_PRAGMA_ONCE |
| #pragma once |
| #endif |
| |
| namespace boost { |
| |
| BOOST_LOG_OPEN_NAMESPACE |
| |
| namespace aux { |
| |
| // This workaround is needed for MSVC 10 to work around ICE caused by stack overflow |
| template< typename SectionT, bool IsConstV > |
| struct basic_settings_section_iterator_base; |
| |
| template< typename SectionT > |
| struct basic_settings_section_iterator_base< SectionT, true > |
| { |
| typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type; |
| typedef typename SectionT::property_tree_type::const_iterator base_iterator_type; |
| typedef iterator_adaptor< |
| iterator_type, |
| base_iterator_type, |
| SectionT, |
| use_default, |
| const SectionT |
| > type; |
| }; |
| |
| template< typename SectionT > |
| struct basic_settings_section_iterator_base< SectionT, false > |
| { |
| typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type; |
| typedef typename SectionT::property_tree_type::iterator base_iterator_type; |
| typedef iterator_adaptor< |
| iterator_type, |
| base_iterator_type, |
| SectionT, |
| use_default, |
| SectionT |
| > type; |
| }; |
| |
| } // namespace aux |
| |
| /*! |
| * \brief The class represents a reference to the settings container section |
| * |
| * The section refers to a sub-tree of the library settings container. It does not |
| * own the referred sub-tree but allows for convenient access to parameters within the subsection. |
| */ |
| template< typename CharT > |
| class basic_settings_section |
| { |
| template< typename SectionT, bool IsConstV > |
| friend struct aux::basic_settings_section_iterator_base; |
| |
| public: |
| //! Character type |
| typedef CharT char_type; |
| //! String type |
| typedef std::basic_string< char_type > string_type; |
| //! Property tree type |
| typedef property_tree::basic_ptree< std::string, string_type > property_tree_type; |
| //! Property tree path type |
| typedef typename property_tree_type::path_type path_type; |
| |
| private: |
| #if !defined(BOOST_LOG_DOXYGEN_PASS) |
| |
| //! A reference proxy object |
| #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS |
| template< bool IsConstV > |
| class ref; |
| template< bool IsConstV > |
| friend class ref; |
| #endif |
| template< bool IsConstV > |
| class ref |
| { |
| private: |
| typedef typename mpl::if_c< |
| IsConstV, |
| basic_settings_section< char_type > const, |
| basic_settings_section< char_type > |
| >::type section_type; |
| |
| private: |
| section_type& m_section; |
| path_type m_path; |
| |
| public: |
| ref(section_type& section, std::string const& section_name) : |
| m_section(section), |
| m_path(section_name) |
| { |
| } |
| ref(section_type& section, const char* section_name) : |
| m_section(section), |
| m_path(section_name) |
| { |
| } |
| |
| ref& operator[] (std::string const& param_name) |
| { |
| m_path /= param_name; |
| return *this; |
| } |
| |
| ref& operator= (string_type const& value) |
| { |
| BOOST_ASSERT(m_section.m_ptree != NULL); |
| m_section.m_ptree->put(m_path, value); |
| return *this; |
| } |
| |
| template< bool V > |
| ref& operator= (ref< V > const& value) |
| { |
| BOOST_ASSERT(m_section.m_ptree != NULL); |
| optional< string_type > val = value.get(); |
| if (!!val) |
| { |
| m_section.m_ptree->put(m_path, val); |
| } |
| else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path)) |
| { |
| node.put_value(string_type()); |
| } |
| |
| return *this; |
| } |
| |
| template< typename T > |
| ref& operator= (T const& value) |
| { |
| BOOST_ASSERT(m_section.m_ptree != NULL); |
| m_section.m_ptree->put(m_path, value); |
| return *this; |
| } |
| |
| BOOST_EXPLICIT_OPERATOR_BOOL() |
| |
| bool operator! () const |
| { |
| return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path); |
| } |
| |
| std::string get_name() const |
| { |
| return m_path.dump(); |
| } |
| |
| operator optional< string_type > () const |
| { |
| return get(); |
| } |
| |
| optional< string_type > get() const |
| { |
| if (m_section.m_ptree) |
| return m_section.m_ptree->template get_optional< string_type >(m_path); |
| else |
| return optional< string_type >(); |
| } |
| |
| template< typename T > |
| optional< T > get() const |
| { |
| if (m_section.m_ptree) |
| return m_section.m_ptree->template get_optional< T >(m_path); |
| else |
| return optional< T >(); |
| } |
| |
| operator section_type () const |
| { |
| return get_section(); |
| } |
| |
| section_type get_section() const |
| { |
| if (m_section.m_ptree) |
| return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr()); |
| else |
| return section_type(); |
| } |
| |
| #if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)) |
| #if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) |
| template< typename T > |
| auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value)) |
| { |
| if (m_section.m_ptree) |
| return m_section.m_ptree->get(m_path, def_value); |
| else |
| return def_value; |
| } |
| #else |
| // GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled |
| template< typename T > |
| BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const |
| { |
| if (m_section.m_ptree) |
| return m_section.m_ptree->get(m_path, def_value); |
| else |
| return def_value; |
| } |
| #endif |
| #else |
| template< typename T > |
| T or_default(T const& def_value) const |
| { |
| if (m_section.m_ptree) |
| return m_section.m_ptree->get(m_path, def_value); |
| else |
| return def_value; |
| } |
| |
| template< typename T > |
| typename enable_if< boost::property_tree::detail::is_character< T >, std::basic_string< T > >::type |
| or_default(const T* def_value) const |
| { |
| if (m_section.m_ptree) |
| return m_section.m_ptree->get(m_path, def_value); |
| else |
| return def_value; |
| } |
| #endif |
| string_type or_default(string_type const& def_value) const |
| { |
| return get().get_value_or(def_value); |
| } |
| string_type or_default(typename string_type::value_type const* def_value) const |
| { |
| if (optional< string_type > val = get()) |
| return val.get(); |
| else |
| return def_value; |
| } |
| }; |
| |
| //! An iterator over subsections and parameters |
| #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS |
| template< bool IsConstV > |
| class iter; |
| template< bool IsConstV > |
| friend class iter; |
| #endif |
| template< bool IsConstV > |
| class iter : |
| public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type |
| { |
| friend class boost::iterator_core_access; |
| |
| typedef typename iter::iterator_adaptor_ iterator_adaptor_; |
| // NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE |
| typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type; |
| |
| public: |
| typedef typename iterator_adaptor_::reference reference; |
| |
| public: |
| BOOST_DEFAULTED_FUNCTION(iter(), {}) |
| template< bool OtherIsConstV > |
| iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {} |
| explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {} |
| |
| //! Returns the section name |
| std::string const& get_name() const |
| { |
| return this->base()->first; |
| } |
| |
| private: |
| reference dereference() const |
| { |
| return reference(const_cast< property_tree_type* >(&this->base()->second)); |
| } |
| }; |
| |
| public: |
| typedef ref< true > const_reference; |
| typedef ref< false > reference; |
| typedef iter< true > const_iterator; |
| typedef iter< false > iterator; |
| typedef std::reverse_iterator< const_iterator > const_reverse_iterator; |
| typedef std::reverse_iterator< iterator > reverse_iterator; |
| |
| #else |
| |
| public: |
| /*! |
| * Constant reference to the parameter value |
| */ |
| typedef implementation_defined const_reference; |
| /*! |
| * Mutable reference to the parameter value |
| */ |
| typedef implementation_defined reference; |
| |
| /*! |
| * Constant iterator over nested parameters and subsections |
| */ |
| typedef implementation_defined const_iterator; |
| /*! |
| * Mutable iterator over nested parameters and subsections |
| */ |
| typedef implementation_defined iterator; |
| |
| #endif // !defined(BOOST_LOG_DOXYGEN_PASS) |
| |
| protected: |
| //! Parameters |
| property_tree_type* m_ptree; |
| |
| public: |
| /*! |
| * Default constructor. Creates an empty settings container. |
| */ |
| basic_settings_section() : m_ptree(NULL) |
| { |
| } |
| |
| /*! |
| * Copy constructor. |
| */ |
| basic_settings_section(basic_settings_section const& that) : m_ptree(that.m_ptree) |
| { |
| } |
| |
| /*! |
| * Checks if the section refers to the container. |
| */ |
| BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() |
| |
| /*! |
| * Checks if the section refers to the container. |
| */ |
| bool operator! () const BOOST_NOEXCEPT { return !m_ptree; } |
| |
| /*! |
| * Returns an iterator over the nested subsections and parameters. |
| */ |
| iterator begin() |
| { |
| if (m_ptree) |
| return iterator(m_ptree->begin()); |
| else |
| return iterator(); |
| } |
| |
| /*! |
| * Returns an iterator over the nested subsections and parameters. |
| */ |
| iterator end() |
| { |
| if (m_ptree) |
| return iterator(m_ptree->end()); |
| else |
| return iterator(); |
| } |
| |
| /*! |
| * Returns an iterator over the nested subsections and parameters. |
| */ |
| const_iterator begin() const |
| { |
| if (m_ptree) |
| return const_iterator(m_ptree->begin()); |
| else |
| return const_iterator(); |
| } |
| |
| /*! |
| * Returns an iterator over the nested subsections and parameters. |
| */ |
| const_iterator end() const |
| { |
| if (m_ptree) |
| return const_iterator(m_ptree->end()); |
| else |
| return const_iterator(); |
| } |
| |
| /*! |
| * Returns a reverse iterator over the nested subsections and parameters. |
| */ |
| reverse_iterator rbegin() { return reverse_iterator(begin()); } |
| |
| /*! |
| * Returns a reverse iterator over the nested subsections and parameters. |
| */ |
| reverse_iterator rend() { return reverse_iterator(end()); } |
| |
| /*! |
| * Returns a reverse iterator over the nested subsections and parameters. |
| */ |
| const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } |
| |
| /*! |
| * Returns a reverse iterator over the nested subsections and parameters. |
| */ |
| const_reverse_iterator rend() const { return const_reverse_iterator(end()); } |
| |
| /*! |
| * Checks if the container is empty (i.e. contains no sections and parameters). |
| */ |
| bool empty() const { return m_ptree == NULL || m_ptree->empty(); } |
| |
| /*! |
| * Accessor to a single parameter. This operator should be used in conjunction |
| * with the subsequent subscript operator that designates the parameter name. |
| * |
| * \param section_name The name of the section in which the parameter resides |
| * \return An unspecified reference type that can be used for parameter name specifying |
| */ |
| reference operator[] (std::string const& section_name) { return reference(*this, section_name); } |
| /*! |
| * Accessor to a single parameter. This operator should be used in conjunction |
| * with the subsequent subscript operator that designates the parameter name. |
| * |
| * \param section_name The name of the section in which the parameter resides |
| * \return An unspecified reference type that can be used for parameter name specifying |
| */ |
| const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); } |
| |
| /*! |
| * Accessor to a single parameter. This operator should be used in conjunction |
| * with the subsequent subscript operator that designates the parameter name. |
| * |
| * \param section_name The name of the section in which the parameter resides |
| * \return An unspecified reference type that can be used for parameter name specifying |
| */ |
| reference operator[] (const char* section_name) { return reference(*this, section_name); } |
| /*! |
| * Accessor to a single parameter. This operator should be used in conjunction |
| * with the subsequent subscript operator that designates the parameter name. |
| * |
| * \param section_name The name of the section in which the parameter resides |
| * \return An unspecified reference type that can be used for parameter name specifying |
| */ |
| const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); } |
| |
| /*! |
| * Accessor for the embedded property tree |
| */ |
| property_tree_type const& property_tree() const { return *m_ptree; } |
| /*! |
| * Accessor for the embedded property tree |
| */ |
| property_tree_type& property_tree() { return *m_ptree; } |
| |
| /*! |
| * Checks if the specified section is present in the container. |
| * |
| * \param section_name The name of the section |
| */ |
| bool has_section(string_type const& section_name) const |
| { |
| return m_ptree != NULL && !!m_ptree->get_child_optional(section_name); |
| } |
| /*! |
| * Checks if the specified parameter is present in the container. |
| * |
| * \param section_name The name of the section in which the parameter resides |
| * \param param_name The name of the parameter |
| */ |
| bool has_parameter(string_type const& section_name, string_type const& param_name) const |
| { |
| if (m_ptree) |
| { |
| optional< property_tree_type& > section = m_ptree->get_child_optional(section_name); |
| if (!!section) |
| return (section->find(param_name) != section->not_found()); |
| } |
| |
| return false; |
| } |
| |
| /*! |
| * Swaps two references to settings sections. |
| */ |
| void swap(basic_settings_section& that) |
| { |
| property_tree_type* const p = m_ptree; |
| m_ptree = that.m_ptree; |
| that.m_ptree = p; |
| } |
| |
| protected: |
| explicit basic_settings_section(property_tree_type* tree) : m_ptree(tree) |
| { |
| } |
| }; |
| |
| template< typename CharT > |
| inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right) |
| { |
| left.swap(right); |
| } |
| |
| |
| /*! |
| * \brief The class represents settings container |
| * |
| * All settings are presented as a number of named parameters divided into named sections. |
| * The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this: |
| * |
| * <code><pre> |
| * optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1" |
| * // returns an empty value if no such parameter exists |
| * settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2" |
| * // to value "10" |
| * </pre></code> |
| * |
| * There are also other methods to work with parameters. |
| */ |
| template< typename CharT > |
| class basic_settings : |
| public basic_settings_section< CharT > |
| { |
| typedef basic_settings this_type; |
| BOOST_COPYABLE_AND_MOVABLE(this_type) |
| |
| public: |
| //! Section type |
| typedef basic_settings_section< CharT > section; |
| //! Property tree type |
| typedef typename section::property_tree_type property_tree_type; |
| |
| public: |
| /*! |
| * Default constructor. Creates an empty settings container. |
| */ |
| basic_settings() : section(new property_tree_type()) |
| { |
| } |
| |
| /*! |
| * Copy constructor. |
| */ |
| basic_settings(basic_settings const& that) : |
| section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL)) |
| { |
| } |
| |
| /*! |
| * Move constructor. |
| */ |
| basic_settings(BOOST_RV_REF(this_type) that) |
| { |
| this->swap(that); |
| } |
| /*! |
| * Initializing constructor. Creates a settings container with the copy of the specified property tree. |
| */ |
| explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree)) |
| { |
| } |
| |
| /*! |
| * Destructor |
| */ |
| ~basic_settings() |
| { |
| delete this->m_ptree; |
| } |
| |
| /*! |
| * Copy assignment operator. |
| */ |
| basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that) |
| { |
| if (this != &that) |
| { |
| basic_settings tmp = that; |
| this->swap(tmp); |
| } |
| return *this; |
| } |
| /*! |
| * Move assignment operator. |
| */ |
| basic_settings& operator= (BOOST_RV_REF(basic_settings) that) |
| { |
| this->swap(that); |
| return *this; |
| } |
| }; |
| |
| #ifdef BOOST_LOG_USE_CHAR |
| typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging |
| typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging |
| #endif |
| #ifdef BOOST_LOG_USE_WCHAR_T |
| typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging |
| typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging |
| #endif |
| |
| BOOST_LOG_CLOSE_NAMESPACE // namespace log |
| |
| } // namespace boost |
| |
| #include <boost/log/detail/footer.hpp> |
| |
| #endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ |