2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
9 * \author Andrey Semashev
12 * The header contains definition of the library settings container.
15 #ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
16 #define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
21 #include <boost/assert.hpp>
22 #include <boost/move/core.hpp>
23 #include <boost/mpl/if.hpp>
24 #include <boost/iterator/iterator_adaptor.hpp>
25 #include <boost/optional/optional.hpp>
26 #include <boost/property_tree/ptree.hpp>
27 #include <boost/log/detail/setup_config.hpp>
28 #include <boost/log/detail/native_typeof.hpp>
29 #include <boost/utility/explicit_operator_bool.hpp>
30 #if !defined(BOOST_LOG_TYPEOF)
31 #include <boost/core/enable_if.hpp>
33 #if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
34 #include <boost/utility/declval.hpp>
36 #include <boost/log/detail/header.hpp>
38 #ifdef BOOST_HAS_PRAGMA_ONCE
44 BOOST_LOG_OPEN_NAMESPACE
48 // This workaround is needed for MSVC 10 to work around ICE caused by stack overflow
49 template< typename SectionT, bool IsConstV >
50 struct basic_settings_section_iterator_base;
52 template< typename SectionT >
53 struct basic_settings_section_iterator_base< SectionT, true >
55 typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type;
56 typedef typename SectionT::property_tree_type::const_iterator base_iterator_type;
57 typedef iterator_adaptor<
66 template< typename SectionT >
67 struct basic_settings_section_iterator_base< SectionT, false >
69 typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type;
70 typedef typename SectionT::property_tree_type::iterator base_iterator_type;
71 typedef iterator_adaptor<
83 * \brief The class represents a reference to the settings container section
85 * The section refers to a sub-tree of the library settings container. It does not
86 * own the referred sub-tree but allows for convenient access to parameters within the subsection.
88 template< typename CharT >
89 class basic_settings_section
91 template< typename SectionT, bool IsConstV >
92 friend struct aux::basic_settings_section_iterator_base;
96 typedef CharT char_type;
98 typedef std::basic_string< char_type > string_type;
99 //! Property tree type
100 typedef property_tree::basic_ptree< std::string, string_type > property_tree_type;
101 //! Property tree path type
102 typedef typename property_tree_type::path_type path_type;
105 #if !defined(BOOST_LOG_DOXYGEN_PASS)
107 //! A reference proxy object
108 #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
109 template< bool IsConstV >
111 template< bool IsConstV >
114 template< bool IsConstV >
118 typedef typename mpl::if_c<
120 basic_settings_section< char_type > const,
121 basic_settings_section< char_type >
122 >::type section_type;
125 section_type& m_section;
129 ref(section_type& section, std::string const& section_name) :
134 ref(section_type& section, const char* section_name) :
140 ref& operator[] (std::string const& param_name)
142 m_path /= param_name;
146 ref& operator= (string_type const& value)
148 BOOST_ASSERT(m_section.m_ptree != NULL);
149 m_section.m_ptree->put(m_path, value);
154 ref& operator= (ref< V > const& value)
156 BOOST_ASSERT(m_section.m_ptree != NULL);
157 optional< string_type > val = value.get();
160 m_section.m_ptree->put(m_path, val);
162 else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path))
164 node.put_value(string_type());
170 template< typename T >
171 ref& operator= (T const& value)
173 BOOST_ASSERT(m_section.m_ptree != NULL);
174 m_section.m_ptree->put(m_path, value);
178 BOOST_EXPLICIT_OPERATOR_BOOL()
180 bool operator! () const
182 return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path);
185 std::string get_name() const
187 return m_path.dump();
190 operator optional< string_type > () const
195 optional< string_type > get() const
197 if (m_section.m_ptree)
198 return m_section.m_ptree->template get_optional< string_type >(m_path);
200 return optional< string_type >();
203 template< typename T >
204 optional< T > get() const
206 if (m_section.m_ptree)
207 return m_section.m_ptree->template get_optional< T >(m_path);
209 return optional< T >();
212 operator section_type () const
214 return get_section();
217 section_type get_section() const
219 if (m_section.m_ptree)
220 return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr());
222 return section_type();
225 #if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5))
226 #if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
227 template< typename T >
228 auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value))
230 if (m_section.m_ptree)
231 return m_section.m_ptree->get(m_path, def_value);
236 // GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled
237 template< typename T >
238 BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const
240 if (m_section.m_ptree)
241 return m_section.m_ptree->get(m_path, def_value);
247 template< typename T >
248 T or_default(T const& def_value) const
250 if (m_section.m_ptree)
251 return m_section.m_ptree->get(m_path, def_value);
256 template< typename T >
257 typename boost::enable_if_c< boost::property_tree::detail::is_character< T >::value, std::basic_string< T > >::type
258 or_default(const T* def_value) const
260 if (m_section.m_ptree)
261 return m_section.m_ptree->get(m_path, def_value);
266 string_type or_default(string_type const& def_value) const
268 return get().get_value_or(def_value);
270 string_type or_default(typename string_type::value_type const* def_value) const
272 if (optional< string_type > val = get())
279 //! An iterator over subsections and parameters
280 #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
281 template< bool IsConstV >
283 template< bool IsConstV >
286 template< bool IsConstV >
288 public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type
290 friend class boost::iterator_core_access;
292 typedef typename iter::iterator_adaptor_ iterator_adaptor_;
293 // NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE
294 typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type;
297 typedef typename iterator_adaptor_::reference reference;
300 BOOST_DEFAULTED_FUNCTION(iter(), {})
301 template< bool OtherIsConstV >
302 iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {}
303 explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {}
305 //! Returns the section name
306 std::string const& get_name() const
308 return this->base()->first;
312 reference dereference() const
314 return reference(const_cast< property_tree_type* >(&this->base()->second));
319 typedef ref< true > const_reference;
320 typedef ref< false > reference;
321 typedef iter< true > const_iterator;
322 typedef iter< false > iterator;
323 typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
324 typedef std::reverse_iterator< iterator > reverse_iterator;
330 * Constant reference to the parameter value
332 typedef implementation_defined const_reference;
334 * Mutable reference to the parameter value
336 typedef implementation_defined reference;
339 * Constant iterator over nested parameters and subsections
341 typedef implementation_defined const_iterator;
343 * Mutable iterator over nested parameters and subsections
345 typedef implementation_defined iterator;
347 #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
351 property_tree_type* m_ptree;
355 * Default constructor. Creates an empty settings container.
357 basic_settings_section() : m_ptree(NULL)
364 basic_settings_section(basic_settings_section const& that) : m_ptree(that.m_ptree)
369 * Checks if the section refers to the container.
371 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
374 * Checks if the section refers to the container.
376 bool operator! () const BOOST_NOEXCEPT { return !m_ptree; }
379 * Returns an iterator over the nested subsections and parameters.
384 return iterator(m_ptree->begin());
390 * Returns an iterator over the nested subsections and parameters.
395 return iterator(m_ptree->end());
401 * Returns an iterator over the nested subsections and parameters.
403 const_iterator begin() const
406 return const_iterator(m_ptree->begin());
408 return const_iterator();
412 * Returns an iterator over the nested subsections and parameters.
414 const_iterator end() const
417 return const_iterator(m_ptree->end());
419 return const_iterator();
423 * Returns a reverse iterator over the nested subsections and parameters.
425 reverse_iterator rbegin() { return reverse_iterator(begin()); }
428 * Returns a reverse iterator over the nested subsections and parameters.
430 reverse_iterator rend() { return reverse_iterator(end()); }
433 * Returns a reverse iterator over the nested subsections and parameters.
435 const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); }
438 * Returns a reverse iterator over the nested subsections and parameters.
440 const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
443 * Checks if the container is empty (i.e. contains no sections and parameters).
445 bool empty() const { return m_ptree == NULL || m_ptree->empty(); }
448 * Accessor to a single parameter. This operator should be used in conjunction
449 * with the subsequent subscript operator that designates the parameter name.
451 * \param section_name The name of the section in which the parameter resides
452 * \return An unspecified reference type that can be used for parameter name specifying
454 reference operator[] (std::string const& section_name) { return reference(*this, section_name); }
456 * Accessor to a single parameter. This operator should be used in conjunction
457 * with the subsequent subscript operator that designates the parameter name.
459 * \param section_name The name of the section in which the parameter resides
460 * \return An unspecified reference type that can be used for parameter name specifying
462 const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); }
465 * Accessor to a single parameter. This operator should be used in conjunction
466 * with the subsequent subscript operator that designates the parameter name.
468 * \param section_name The name of the section in which the parameter resides
469 * \return An unspecified reference type that can be used for parameter name specifying
471 reference operator[] (const char* section_name) { return reference(*this, section_name); }
473 * Accessor to a single parameter. This operator should be used in conjunction
474 * with the subsequent subscript operator that designates the parameter name.
476 * \param section_name The name of the section in which the parameter resides
477 * \return An unspecified reference type that can be used for parameter name specifying
479 const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); }
482 * Accessor for the embedded property tree
484 property_tree_type const& property_tree() const { return *m_ptree; }
486 * Accessor for the embedded property tree
488 property_tree_type& property_tree() { return *m_ptree; }
491 * Checks if the specified section is present in the container.
493 * \param section_name The name of the section
495 bool has_section(string_type const& section_name) const
497 return m_ptree != NULL && !!m_ptree->get_child_optional(section_name);
500 * Checks if the specified parameter is present in the container.
502 * \param section_name The name of the section in which the parameter resides
503 * \param param_name The name of the parameter
505 bool has_parameter(string_type const& section_name, string_type const& param_name) const
509 optional< property_tree_type& > section = m_ptree->get_child_optional(section_name);
511 return (section->find(param_name) != section->not_found());
518 * Swaps two references to settings sections.
520 void swap(basic_settings_section& that)
522 property_tree_type* const p = m_ptree;
523 m_ptree = that.m_ptree;
528 explicit basic_settings_section(property_tree_type* tree) : m_ptree(tree)
533 template< typename CharT >
534 inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right)
541 * \brief The class represents settings container
543 * All settings are presented as a number of named parameters divided into named sections.
544 * The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this:
547 * optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1"
548 * // returns an empty value if no such parameter exists
549 * settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2"
553 * There are also other methods to work with parameters.
555 template< typename CharT >
556 class basic_settings :
557 public basic_settings_section< CharT >
559 typedef basic_settings this_type;
560 BOOST_COPYABLE_AND_MOVABLE(this_type)
564 typedef basic_settings_section< CharT > section;
565 //! Property tree type
566 typedef typename section::property_tree_type property_tree_type;
570 * Default constructor. Creates an empty settings container.
572 basic_settings() : section(new property_tree_type())
579 basic_settings(basic_settings const& that) :
580 section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL))
587 basic_settings(BOOST_RV_REF(this_type) that)
592 * Initializing constructor. Creates a settings container with the copy of the specified property tree.
594 explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree))
603 delete this->m_ptree;
607 * Copy assignment operator.
609 basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that)
613 basic_settings tmp = that;
619 * Move assignment operator.
621 basic_settings& operator= (BOOST_RV_REF(basic_settings) that)
628 #ifdef BOOST_LOG_USE_CHAR
629 typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging
630 typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging
632 #ifdef BOOST_LOG_USE_WCHAR_T
633 typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging
634 typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging
637 BOOST_LOG_CLOSE_NAMESPACE // namespace log
641 #include <boost/log/detail/footer.hpp>
643 #endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_