settings.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. /*
  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)
  6. */
  7. /*!
  8. * \file settings.hpp
  9. * \author Andrey Semashev
  10. * \date 11.10.2009
  11. *
  12. * The header contains definition of the library settings container.
  13. */
  14. #ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
  15. #define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_
  16. #include <cstddef>
  17. #include <string>
  18. #include <iterator>
  19. #include <boost/assert.hpp>
  20. #include <boost/move/core.hpp>
  21. #include <boost/type_traits/conditional.hpp>
  22. #include <boost/iterator/iterator_adaptor.hpp>
  23. #include <boost/optional/optional.hpp>
  24. #include <boost/property_tree/ptree.hpp>
  25. #include <boost/core/explicit_operator_bool.hpp>
  26. #include <boost/log/detail/setup_config.hpp>
  27. #include <boost/log/detail/native_typeof.hpp>
  28. #if !defined(BOOST_LOG_TYPEOF)
  29. #include <boost/core/enable_if.hpp>
  30. #endif
  31. #if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
  32. #include <boost/utility/declval.hpp>
  33. #endif
  34. #include <boost/log/detail/header.hpp>
  35. #ifdef BOOST_HAS_PRAGMA_ONCE
  36. #pragma once
  37. #endif
  38. namespace boost {
  39. BOOST_LOG_OPEN_NAMESPACE
  40. namespace aux {
  41. // This workaround is needed for MSVC 10 to work around ICE caused by stack overflow
  42. template< typename SectionT, bool IsConstV >
  43. struct basic_settings_section_iterator_base;
  44. template< typename SectionT >
  45. struct basic_settings_section_iterator_base< SectionT, true >
  46. {
  47. typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type;
  48. typedef typename SectionT::property_tree_type::const_iterator base_iterator_type;
  49. typedef iterator_adaptor<
  50. iterator_type,
  51. base_iterator_type,
  52. SectionT,
  53. use_default,
  54. const SectionT
  55. > type;
  56. };
  57. template< typename SectionT >
  58. struct basic_settings_section_iterator_base< SectionT, false >
  59. {
  60. typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type;
  61. typedef typename SectionT::property_tree_type::iterator base_iterator_type;
  62. typedef iterator_adaptor<
  63. iterator_type,
  64. base_iterator_type,
  65. SectionT,
  66. use_default,
  67. SectionT
  68. > type;
  69. };
  70. } // namespace aux
  71. /*!
  72. * \brief The class represents a reference to the settings container section
  73. *
  74. * The section refers to a sub-tree of the library settings container. It does not
  75. * own the referred sub-tree but allows for convenient access to parameters within the subsection.
  76. */
  77. template< typename CharT >
  78. class basic_settings_section
  79. {
  80. template< typename SectionT, bool IsConstV >
  81. friend struct aux::basic_settings_section_iterator_base;
  82. public:
  83. //! Character type
  84. typedef CharT char_type;
  85. //! String type
  86. typedef std::basic_string< char_type > string_type;
  87. //! Property tree type
  88. typedef property_tree::basic_ptree< std::string, string_type > property_tree_type;
  89. //! Property tree path type
  90. typedef typename property_tree_type::path_type path_type;
  91. private:
  92. #if !defined(BOOST_LOG_DOXYGEN_PASS)
  93. //! A reference proxy object
  94. #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
  95. template< bool IsConstV >
  96. class ref;
  97. template< bool IsConstV >
  98. friend class ref;
  99. #endif
  100. template< bool IsConstV >
  101. class ref
  102. {
  103. private:
  104. typedef typename boost::conditional<
  105. IsConstV,
  106. basic_settings_section< char_type > const,
  107. basic_settings_section< char_type >
  108. >::type section_type;
  109. private:
  110. section_type& m_section;
  111. path_type m_path;
  112. public:
  113. ref(section_type& section, std::string const& section_name) :
  114. m_section(section),
  115. m_path(section_name)
  116. {
  117. }
  118. ref(section_type& section, const char* section_name) :
  119. m_section(section),
  120. m_path(section_name)
  121. {
  122. }
  123. ref& operator[] (std::string const& param_name)
  124. {
  125. m_path /= param_name;
  126. return *this;
  127. }
  128. ref& operator= (string_type const& value)
  129. {
  130. BOOST_ASSERT(m_section.m_ptree != NULL);
  131. m_section.m_ptree->put(m_path, value);
  132. return *this;
  133. }
  134. template< bool V >
  135. ref& operator= (ref< V > const& value)
  136. {
  137. BOOST_ASSERT(m_section.m_ptree != NULL);
  138. optional< string_type > val = value.get();
  139. if (!!val)
  140. {
  141. m_section.m_ptree->put(m_path, val);
  142. }
  143. else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path))
  144. {
  145. node.put_value(string_type());
  146. }
  147. return *this;
  148. }
  149. template< typename T >
  150. ref& operator= (T const& value)
  151. {
  152. BOOST_ASSERT(m_section.m_ptree != NULL);
  153. m_section.m_ptree->put(m_path, value);
  154. return *this;
  155. }
  156. BOOST_EXPLICIT_OPERATOR_BOOL()
  157. bool operator! () const
  158. {
  159. return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path);
  160. }
  161. std::string get_name() const
  162. {
  163. return m_path.dump();
  164. }
  165. operator optional< string_type > () const
  166. {
  167. return get();
  168. }
  169. optional< string_type > get() const
  170. {
  171. if (m_section.m_ptree)
  172. return m_section.m_ptree->template get_optional< string_type >(m_path);
  173. else
  174. return optional< string_type >();
  175. }
  176. template< typename T >
  177. optional< T > get() const
  178. {
  179. if (m_section.m_ptree)
  180. return m_section.m_ptree->template get_optional< T >(m_path);
  181. else
  182. return optional< T >();
  183. }
  184. operator section_type () const
  185. {
  186. return get_section();
  187. }
  188. section_type get_section() const
  189. {
  190. if (m_section.m_ptree)
  191. return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr());
  192. else
  193. return section_type();
  194. }
  195. #if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5))
  196. #if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
  197. template< typename T >
  198. auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value))
  199. {
  200. if (m_section.m_ptree)
  201. return m_section.m_ptree->get(m_path, def_value);
  202. else
  203. return def_value;
  204. }
  205. #else
  206. // GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled
  207. template< typename T >
  208. BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const
  209. {
  210. if (m_section.m_ptree)
  211. return m_section.m_ptree->get(m_path, def_value);
  212. else
  213. return def_value;
  214. }
  215. #endif
  216. #else
  217. template< typename T >
  218. T or_default(T const& def_value) const
  219. {
  220. if (m_section.m_ptree)
  221. return m_section.m_ptree->get(m_path, def_value);
  222. else
  223. return def_value;
  224. }
  225. template< typename T >
  226. typename boost::enable_if_c< boost::property_tree::detail::is_character< T >::value, std::basic_string< T > >::type
  227. or_default(const T* def_value) const
  228. {
  229. if (m_section.m_ptree)
  230. return m_section.m_ptree->get(m_path, def_value);
  231. else
  232. return def_value;
  233. }
  234. #endif
  235. string_type or_default(string_type const& def_value) const
  236. {
  237. return get().get_value_or(def_value);
  238. }
  239. string_type or_default(typename string_type::value_type const* def_value) const
  240. {
  241. if (optional< string_type > val = get())
  242. return val.get();
  243. else
  244. return def_value;
  245. }
  246. };
  247. //! An iterator over subsections and parameters
  248. #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
  249. template< bool IsConstV >
  250. class iter;
  251. template< bool IsConstV >
  252. friend class iter;
  253. #endif
  254. template< bool IsConstV >
  255. class iter :
  256. public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type
  257. {
  258. friend class boost::iterator_core_access;
  259. typedef typename iter::iterator_adaptor_ iterator_adaptor_;
  260. // NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE
  261. typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type;
  262. public:
  263. typedef typename iterator_adaptor_::reference reference;
  264. public:
  265. BOOST_DEFAULTED_FUNCTION(iter(), {})
  266. template< bool OtherIsConstV >
  267. iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {}
  268. explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {}
  269. //! Returns the section name
  270. std::string const& get_name() const
  271. {
  272. return this->base()->first;
  273. }
  274. private:
  275. reference dereference() const
  276. {
  277. return reference(const_cast< property_tree_type* >(&this->base()->second));
  278. }
  279. };
  280. public:
  281. typedef ref< true > const_reference;
  282. typedef ref< false > reference;
  283. typedef iter< true > const_iterator;
  284. typedef iter< false > iterator;
  285. typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
  286. typedef std::reverse_iterator< iterator > reverse_iterator;
  287. #else
  288. public:
  289. /*!
  290. * Constant reference to the parameter value
  291. */
  292. typedef implementation_defined const_reference;
  293. /*!
  294. * Mutable reference to the parameter value
  295. */
  296. typedef implementation_defined reference;
  297. /*!
  298. * Constant iterator over nested parameters and subsections
  299. */
  300. typedef implementation_defined const_iterator;
  301. /*!
  302. * Mutable iterator over nested parameters and subsections
  303. */
  304. typedef implementation_defined iterator;
  305. #endif // !defined(BOOST_LOG_DOXYGEN_PASS)
  306. protected:
  307. //! Parameters
  308. property_tree_type* m_ptree;
  309. public:
  310. /*!
  311. * Default constructor. Creates an empty settings container.
  312. */
  313. basic_settings_section() BOOST_NOEXCEPT : m_ptree(NULL)
  314. {
  315. }
  316. /*!
  317. * Copy constructor.
  318. */
  319. basic_settings_section(basic_settings_section const& that) BOOST_NOEXCEPT : m_ptree(that.m_ptree)
  320. {
  321. }
  322. /*!
  323. * Checks if the section refers to the container.
  324. */
  325. BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
  326. /*!
  327. * Checks if the section refers to the container.
  328. */
  329. bool operator! () const BOOST_NOEXCEPT { return !m_ptree; }
  330. /*!
  331. * Returns an iterator over the nested subsections and parameters.
  332. */
  333. iterator begin()
  334. {
  335. if (m_ptree)
  336. return iterator(m_ptree->begin());
  337. else
  338. return iterator();
  339. }
  340. /*!
  341. * Returns an iterator over the nested subsections and parameters.
  342. */
  343. iterator end()
  344. {
  345. if (m_ptree)
  346. return iterator(m_ptree->end());
  347. else
  348. return iterator();
  349. }
  350. /*!
  351. * Returns an iterator over the nested subsections and parameters.
  352. */
  353. const_iterator begin() const
  354. {
  355. if (m_ptree)
  356. return const_iterator(m_ptree->begin());
  357. else
  358. return const_iterator();
  359. }
  360. /*!
  361. * Returns an iterator over the nested subsections and parameters.
  362. */
  363. const_iterator end() const
  364. {
  365. if (m_ptree)
  366. return const_iterator(m_ptree->end());
  367. else
  368. return const_iterator();
  369. }
  370. /*!
  371. * Returns a reverse iterator over the nested subsections and parameters.
  372. */
  373. reverse_iterator rbegin() { return reverse_iterator(begin()); }
  374. /*!
  375. * Returns a reverse iterator over the nested subsections and parameters.
  376. */
  377. reverse_iterator rend() { return reverse_iterator(end()); }
  378. /*!
  379. * Returns a reverse iterator over the nested subsections and parameters.
  380. */
  381. const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); }
  382. /*!
  383. * Returns a reverse iterator over the nested subsections and parameters.
  384. */
  385. const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
  386. /*!
  387. * Checks if the container is empty (i.e. contains no sections and parameters).
  388. */
  389. bool empty() const { return m_ptree == NULL || m_ptree->empty(); }
  390. /*!
  391. * Accessor to a single parameter. This operator should be used in conjunction
  392. * with the subsequent subscript operator that designates the parameter name.
  393. *
  394. * \param section_name The name of the section in which the parameter resides
  395. * \return An unspecified reference type that can be used for parameter name specifying
  396. */
  397. reference operator[] (std::string const& section_name) { return reference(*this, section_name); }
  398. /*!
  399. * Accessor to a single parameter. This operator should be used in conjunction
  400. * with the subsequent subscript operator that designates the parameter name.
  401. *
  402. * \param section_name The name of the section in which the parameter resides
  403. * \return An unspecified reference type that can be used for parameter name specifying
  404. */
  405. const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); }
  406. /*!
  407. * Accessor to a single parameter. This operator should be used in conjunction
  408. * with the subsequent subscript operator that designates the parameter name.
  409. *
  410. * \param section_name The name of the section in which the parameter resides
  411. * \return An unspecified reference type that can be used for parameter name specifying
  412. */
  413. reference operator[] (const char* section_name) { return reference(*this, section_name); }
  414. /*!
  415. * Accessor to a single parameter. This operator should be used in conjunction
  416. * with the subsequent subscript operator that designates the parameter name.
  417. *
  418. * \param section_name The name of the section in which the parameter resides
  419. * \return An unspecified reference type that can be used for parameter name specifying
  420. */
  421. const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); }
  422. /*!
  423. * Accessor for the embedded property tree
  424. */
  425. property_tree_type const& property_tree() const { return *m_ptree; }
  426. /*!
  427. * Accessor for the embedded property tree
  428. */
  429. property_tree_type& property_tree() { return *m_ptree; }
  430. /*!
  431. * Checks if the specified section is present in the container.
  432. *
  433. * \param section_name The name of the section
  434. */
  435. bool has_section(string_type const& section_name) const
  436. {
  437. return m_ptree != NULL && !!m_ptree->get_child_optional(section_name);
  438. }
  439. /*!
  440. * Checks if the specified parameter is present in the container.
  441. *
  442. * \param section_name The name of the section in which the parameter resides
  443. * \param param_name The name of the parameter
  444. */
  445. bool has_parameter(string_type const& section_name, string_type const& param_name) const
  446. {
  447. if (m_ptree)
  448. {
  449. optional< property_tree_type& > section = m_ptree->get_child_optional(section_name);
  450. if (!!section)
  451. return (section->find(param_name) != section->not_found());
  452. }
  453. return false;
  454. }
  455. /*!
  456. * Swaps two references to settings sections.
  457. */
  458. void swap(basic_settings_section& that) BOOST_NOEXCEPT
  459. {
  460. property_tree_type* const p = m_ptree;
  461. m_ptree = that.m_ptree;
  462. that.m_ptree = p;
  463. }
  464. protected:
  465. explicit basic_settings_section(property_tree_type* tree) BOOST_NOEXCEPT : m_ptree(tree)
  466. {
  467. }
  468. };
  469. template< typename CharT >
  470. inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right) BOOST_NOEXCEPT
  471. {
  472. left.swap(right);
  473. }
  474. /*!
  475. * \brief The class represents settings container
  476. *
  477. * All settings are presented as a number of named parameters divided into named sections.
  478. * The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this:
  479. *
  480. * <code><pre>
  481. * optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1"
  482. * // returns an empty value if no such parameter exists
  483. * settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2"
  484. * // to value "10"
  485. * </pre></code>
  486. *
  487. * There are also other methods to work with parameters.
  488. */
  489. template< typename CharT >
  490. class basic_settings :
  491. public basic_settings_section< CharT >
  492. {
  493. typedef basic_settings this_type;
  494. BOOST_COPYABLE_AND_MOVABLE(this_type)
  495. public:
  496. //! Section type
  497. typedef basic_settings_section< CharT > section;
  498. //! Property tree type
  499. typedef typename section::property_tree_type property_tree_type;
  500. public:
  501. /*!
  502. * Default constructor. Creates an empty settings container.
  503. */
  504. basic_settings() : section(new property_tree_type())
  505. {
  506. }
  507. /*!
  508. * Copy constructor.
  509. */
  510. basic_settings(basic_settings const& that) :
  511. section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL))
  512. {
  513. }
  514. /*!
  515. * Move constructor.
  516. */
  517. basic_settings(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
  518. {
  519. this->swap(that);
  520. }
  521. /*!
  522. * Initializing constructor. Creates a settings container with the copy of the specified property tree.
  523. */
  524. explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree))
  525. {
  526. }
  527. /*!
  528. * Destructor
  529. */
  530. ~basic_settings() BOOST_NOEXCEPT
  531. {
  532. delete this->m_ptree;
  533. }
  534. /*!
  535. * Copy assignment operator.
  536. */
  537. basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that)
  538. {
  539. if (this != &that)
  540. {
  541. basic_settings tmp = that;
  542. this->swap(tmp);
  543. }
  544. return *this;
  545. }
  546. /*!
  547. * Move assignment operator.
  548. */
  549. basic_settings& operator= (BOOST_RV_REF(basic_settings) that) BOOST_NOEXCEPT
  550. {
  551. this->swap(that);
  552. return *this;
  553. }
  554. };
  555. #ifdef BOOST_LOG_USE_CHAR
  556. typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging
  557. typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging
  558. #endif
  559. #ifdef BOOST_LOG_USE_WCHAR_T
  560. typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging
  561. typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging
  562. #endif
  563. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  564. } // namespace boost
  565. #include <boost/log/detail/footer.hpp>
  566. #endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_