attribute_set.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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 attribute_set.hpp
  9. * \author Andrey Semashev
  10. * \date 08.03.2007
  11. *
  12. * This header contains definition of the attribute set container.
  13. */
  14. #ifndef BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
  15. #define BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
  16. #include <cstddef>
  17. #include <utility>
  18. #include <iterator>
  19. #include <boost/move/core.hpp>
  20. #include <boost/core/enable_if.hpp>
  21. #include <boost/type_traits/conditional.hpp>
  22. #include <boost/log/detail/config.hpp>
  23. #include <boost/log/detail/sfinae_tools.hpp>
  24. #include <boost/log/attributes/attribute_name.hpp>
  25. #include <boost/log/attributes/attribute.hpp>
  26. #include <boost/log/detail/header.hpp>
  27. #ifdef BOOST_HAS_PRAGMA_ONCE
  28. #pragma once
  29. #endif
  30. namespace boost {
  31. BOOST_LOG_OPEN_NAMESPACE
  32. class attribute_set;
  33. class attribute_value_set;
  34. namespace aux {
  35. //! Reference proxy object to implement \c operator[]
  36. class attribute_set_reference_proxy
  37. {
  38. private:
  39. //! Key type
  40. typedef attribute_name key_type;
  41. //! Mapped attribute type
  42. typedef attribute mapped_type;
  43. private:
  44. attribute_set* const m_pContainer;
  45. const key_type m_key;
  46. public:
  47. //! Constructor
  48. explicit attribute_set_reference_proxy(attribute_set* pContainer, key_type const& key) BOOST_NOEXCEPT :
  49. m_pContainer(pContainer),
  50. m_key(key)
  51. {
  52. }
  53. //! Conversion operator (would be invoked in case of reading from the container)
  54. BOOST_FORCEINLINE operator mapped_type() const BOOST_NOEXCEPT
  55. {
  56. return read_mapped_value();
  57. }
  58. //! Assignment operator (would be invoked in case of writing to the container)
  59. mapped_type& operator= (mapped_type const& val) const;
  60. private:
  61. //! Reads the referenced mapped value from the container
  62. mapped_type read_mapped_value() const BOOST_NOEXCEPT;
  63. };
  64. } // namespace aux
  65. /*!
  66. * \brief An attribute set class.
  67. *
  68. * An attribute set is an associative container with attribute name as a key and
  69. * pointer to the attribute as a mapped value. The container allows storing only one element for each distinct
  70. * key value. In most regards attribute set container provides interface similar to \c std::unordered_map.
  71. * However, there are differences in \c operator[] semantics and a number of optimizations with regard to iteration.
  72. * Besides, attribute names are stored as a read-only <tt>attribute_name</tt>'s instead of \c std::string,
  73. * which saves memory and CPU time.
  74. */
  75. class attribute_set
  76. {
  77. BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_set)
  78. friend class attribute_value_set;
  79. friend class aux::attribute_set_reference_proxy;
  80. public:
  81. //! Key type
  82. typedef attribute_name key_type;
  83. //! Mapped attribute type
  84. typedef attribute mapped_type;
  85. //! Value type
  86. typedef std::pair< const key_type, mapped_type > value_type;
  87. //! Reference type
  88. typedef value_type& reference;
  89. //! Const reference type
  90. typedef value_type const& const_reference;
  91. //! Pointer type
  92. typedef value_type* pointer;
  93. //! Const pointer type
  94. typedef value_type const* const_pointer;
  95. //! Size type
  96. typedef std::size_t size_type;
  97. //! Difference type
  98. typedef std::ptrdiff_t difference_type;
  99. private:
  100. //! \cond
  101. //! Implementation
  102. struct implementation;
  103. friend struct implementation;
  104. //! A base class for the container nodes
  105. struct node_base
  106. {
  107. node_base* m_pPrev;
  108. node_base* m_pNext;
  109. node_base();
  110. BOOST_DELETED_FUNCTION(node_base(node_base const&))
  111. BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&))
  112. };
  113. //! Container elements
  114. struct node;
  115. friend struct node;
  116. struct node :
  117. public node_base
  118. {
  119. value_type m_Value;
  120. node(key_type const& key, mapped_type const& data);
  121. };
  122. //! Iterator class
  123. #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
  124. template< bool fConstV > class iter;
  125. template< bool fConstV > friend class iter;
  126. #endif
  127. template< bool fConstV >
  128. class iter
  129. {
  130. friend class iter< !fConstV >;
  131. friend class attribute_set;
  132. public:
  133. // Standard typedefs
  134. typedef attribute_set::difference_type difference_type;
  135. typedef attribute_set::value_type value_type;
  136. typedef typename boost::conditional<
  137. fConstV,
  138. attribute_set::const_reference,
  139. attribute_set::reference
  140. >::type reference;
  141. typedef typename boost::conditional<
  142. fConstV,
  143. attribute_set::const_pointer,
  144. attribute_set::pointer
  145. >::type pointer;
  146. typedef std::bidirectional_iterator_tag iterator_category;
  147. public:
  148. // Constructors
  149. BOOST_CONSTEXPR iter() BOOST_NOEXCEPT : m_pNode(NULL) {}
  150. explicit iter(node_base* pNode) BOOST_NOEXCEPT : m_pNode(pNode) {}
  151. #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  152. template< bool fOtherConstV, typename = typename boost::enable_if_c< !fOtherConstV && fOtherConstV != fConstV >::type >
  153. iter(iter< fOtherConstV > const& that) BOOST_NOEXCEPT : m_pNode(that.m_pNode) {}
  154. #else
  155. template< bool fOtherConstV >
  156. iter(iter< fOtherConstV > const& that, typename boost::enable_if_c< !fOtherConstV && fOtherConstV != fConstV, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) BOOST_NOEXCEPT :
  157. m_pNode(that.m_pNode)
  158. {
  159. }
  160. #endif
  161. //! Assignment
  162. template< bool fOtherConstV >
  163. typename boost::enable_if_c< !fOtherConstV && fOtherConstV != fConstV, iter& >::type operator= (iter< fOtherConstV > const& that) BOOST_NOEXCEPT
  164. {
  165. m_pNode = that.m_pNode;
  166. return *this;
  167. }
  168. // Comparison
  169. template< bool fOtherConstV >
  170. typename boost::enable_if_c< !fOtherConstV || fOtherConstV == fConstV, bool >::type operator== (iter< fOtherConstV > const& that) const BOOST_NOEXCEPT { return (m_pNode == that.m_pNode); }
  171. template< bool fOtherConstV >
  172. typename boost::enable_if_c< !fOtherConstV || fOtherConstV == fConstV, bool >::type operator!= (iter< fOtherConstV > const& that) const BOOST_NOEXCEPT { return (m_pNode != that.m_pNode); }
  173. // Modification
  174. iter& operator++ () BOOST_NOEXCEPT
  175. {
  176. m_pNode = m_pNode->m_pNext;
  177. return *this;
  178. }
  179. iter& operator-- () BOOST_NOEXCEPT
  180. {
  181. m_pNode = m_pNode->m_pPrev;
  182. return *this;
  183. }
  184. iter operator++ (int) BOOST_NOEXCEPT
  185. {
  186. iter tmp(*this);
  187. m_pNode = m_pNode->m_pNext;
  188. return tmp;
  189. }
  190. iter operator-- (int) BOOST_NOEXCEPT
  191. {
  192. iter tmp(*this);
  193. m_pNode = m_pNode->m_pPrev;
  194. return tmp;
  195. }
  196. // Dereferencing
  197. pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); }
  198. reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; }
  199. node_base* base() const BOOST_NOEXCEPT { return m_pNode; }
  200. private:
  201. node_base* m_pNode;
  202. };
  203. //! \endcond
  204. public:
  205. #ifndef BOOST_LOG_DOXYGEN_PASS
  206. //! Iterator type
  207. typedef iter< false > iterator;
  208. //! Const iterator type
  209. typedef iter< true > const_iterator;
  210. #else
  211. /*!
  212. * Iterator type. The iterator complies to the bidirectional iterator requirements.
  213. */
  214. typedef implementation_defined iterator;
  215. /*!
  216. * Constant iterator type. The iterator complies to the bidirectional iterator requirements with read-only capabilities.
  217. */
  218. typedef implementation_defined const_iterator;
  219. #endif // BOOST_LOG_DOXYGEN_PASS
  220. private:
  221. //! Pointer to implementation
  222. implementation* m_pImpl;
  223. public:
  224. /*!
  225. * Default constructor.
  226. *
  227. * \post <tt>empty() == true</tt>
  228. */
  229. BOOST_LOG_API attribute_set();
  230. /*!
  231. * Copy constructor.
  232. *
  233. * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt>
  234. */
  235. BOOST_LOG_API attribute_set(attribute_set const& that);
  236. /*!
  237. * Move constructor
  238. */
  239. attribute_set(BOOST_RV_REF(attribute_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl)
  240. {
  241. that.m_pImpl = NULL;
  242. }
  243. /*!
  244. * Destructor. All stored references to attributes are released.
  245. */
  246. BOOST_LOG_API ~attribute_set() BOOST_NOEXCEPT;
  247. /*!
  248. * Copy assignment operator.
  249. *
  250. * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt>
  251. */
  252. attribute_set& operator= (attribute_set that) BOOST_NOEXCEPT
  253. {
  254. this->swap(that);
  255. return *this;
  256. }
  257. /*!
  258. * Swaps two instances of the container.
  259. *
  260. * \b Throws: Nothing.
  261. */
  262. void swap(attribute_set& that) BOOST_NOEXCEPT
  263. {
  264. implementation* const p = m_pImpl;
  265. m_pImpl = that.m_pImpl;
  266. that.m_pImpl = p;
  267. }
  268. /*!
  269. * \return Iterator to the first element of the container.
  270. */
  271. BOOST_LOG_API iterator begin() BOOST_NOEXCEPT;
  272. /*!
  273. * \return Iterator to the after-the-last element of the container.
  274. */
  275. BOOST_LOG_API iterator end() BOOST_NOEXCEPT;
  276. /*!
  277. * \return Constant iterator to the first element of the container.
  278. */
  279. BOOST_LOG_API const_iterator begin() const BOOST_NOEXCEPT;
  280. /*!
  281. * \return Constant iterator to the after-the-last element of the container.
  282. */
  283. BOOST_LOG_API const_iterator end() const BOOST_NOEXCEPT;
  284. /*!
  285. * \return Number of elements in the container.
  286. */
  287. BOOST_LOG_API size_type size() const BOOST_NOEXCEPT;
  288. /*!
  289. * \return true if there are no elements in the container, false otherwise.
  290. */
  291. bool empty() const BOOST_NOEXCEPT { return (this->size() == 0); }
  292. /*!
  293. * The method finds the attribute by name.
  294. *
  295. * \param key Attribute name.
  296. * \return Iterator to the found element or end() if the attribute with such name is not found.
  297. */
  298. BOOST_LOG_API iterator find(key_type key) BOOST_NOEXCEPT;
  299. /*!
  300. * The method finds the attribute by name.
  301. *
  302. * \param key Attribute name.
  303. * \return Iterator to the found element or \c end() if the attribute with such name is not found.
  304. */
  305. const_iterator find(key_type key) const BOOST_NOEXCEPT
  306. {
  307. return const_iterator(const_cast< attribute_set* >(this)->find(key));
  308. }
  309. /*!
  310. * The method counts the number of the attribute occurrences in the container. Since there can be only one
  311. * attribute with a particular key, the method always return 0 or 1.
  312. *
  313. * \param key Attribute name.
  314. * \return The number of times the attribute is found in the container.
  315. */
  316. size_type count(key_type key) const BOOST_NOEXCEPT { return size_type(this->find(key) != this->end()); }
  317. /*!
  318. * Combined lookup/insertion operator. The operator semantics depends on the further usage of the returned reference.
  319. * \li If the reference is used as an assignment target, the assignment expression is equivalent to element insertion,
  320. * where the element is composed of the second argument of the \c operator[] as a key and the second argument of assignment
  321. * as a mapped value.
  322. * \li If the returned reference is used in context where a conversion to the mapped type is required,
  323. * the result of the conversion is equivalent to the mapped value found with the second argument of the \c operator[] as a key,
  324. * if such an element exists in the container, or a default-constructed mapped value, if an element does not exist in the
  325. * container.
  326. *
  327. * \param key Attribute name.
  328. * \return A smart reference object of unspecified type.
  329. */
  330. aux::attribute_set_reference_proxy operator[] (key_type key) BOOST_NOEXCEPT
  331. {
  332. return aux::attribute_set_reference_proxy(this, key);
  333. }
  334. /*!
  335. * Lookup operator
  336. *
  337. * \param key Attribute name.
  338. * \return If an element with the corresponding attribute name is found in the container, its mapped value
  339. * is returned. Otherwise a default-constructed mapped value is returned.
  340. */
  341. mapped_type operator[] (key_type key) const BOOST_NOEXCEPT
  342. {
  343. const_iterator it = this->find(key);
  344. if (it != end())
  345. return it->second;
  346. else
  347. return mapped_type();
  348. }
  349. /*!
  350. * Insertion method
  351. *
  352. * \param key Attribute name.
  353. * \param data Pointer to the attribute. Must not be NULL.
  354. * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the
  355. * inserted element. Otherwise the first component points to the element that prevents insertion.
  356. */
  357. BOOST_LOG_API std::pair< iterator, bool > insert(key_type key, mapped_type const& data);
  358. /*!
  359. * Insertion method
  360. *
  361. * \param value An element to be inserted.
  362. * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the
  363. * inserted element. Otherwise the first component points to the element that prevents insertion.
  364. */
  365. std::pair< iterator, bool > insert(const_reference value)
  366. {
  367. return this->insert(value.first, value.second);
  368. }
  369. /*!
  370. * Mass insertion method.
  371. *
  372. * \param begin A forward iterator that points to the first element to be inserted.
  373. * \param end A forward iterator that points to the after-the-last element to be inserted.
  374. */
  375. template< typename FwdIteratorT >
  376. void insert(FwdIteratorT begin, FwdIteratorT end)
  377. {
  378. for (; begin != end; ++begin)
  379. this->insert(*begin);
  380. }
  381. /*!
  382. * Mass insertion method with ability to acquire iterators to the inserted elements.
  383. *
  384. * \param begin A forward iterator that points to the first element to be inserted.
  385. * \param end A forward iterator that points to the after-the-last element to be inserted.
  386. * \param out An output iterator that receives results of insertion of the elements
  387. */
  388. template< typename FwdIteratorT, typename OutputIteratorT >
  389. void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out)
  390. {
  391. for (; begin != end; ++begin, ++out)
  392. *out = this->insert(*begin);
  393. }
  394. /*!
  395. * The method erases all attributes with the specified name
  396. *
  397. * \post All iterators to the erased elements become invalid.
  398. * \param key Attribute name.
  399. * \return Tne number of erased elements
  400. */
  401. BOOST_LOG_API size_type erase(key_type key) BOOST_NOEXCEPT;
  402. /*!
  403. * The method erases the specified attribute
  404. *
  405. * \post All iterators to the erased element become invalid.
  406. * \param it A valid iterator to the element to be erased.
  407. * \return Tne number of erased elements
  408. */
  409. BOOST_LOG_API void erase(iterator it) BOOST_NOEXCEPT;
  410. /*!
  411. * The method erases all attributes within the specified range
  412. *
  413. * \pre \a end is reachable from \a begin with a finite number of increments.
  414. * \post All iterators to the erased elements become invalid.
  415. * \param begin An iterator that points to the first element to be erased.
  416. * \param end An iterator that points to the after-the-last element to be erased.
  417. */
  418. BOOST_LOG_API void erase(iterator begin, iterator end) BOOST_NOEXCEPT;
  419. /*!
  420. * The method removes all elements from the container
  421. *
  422. * \post <tt>empty() == true</tt>
  423. */
  424. BOOST_LOG_API void clear() BOOST_NOEXCEPT;
  425. };
  426. /*!
  427. * Free swap overload
  428. */
  429. inline void swap(attribute_set& left, attribute_set& right) BOOST_NOEXCEPT
  430. {
  431. left.swap(right);
  432. }
  433. namespace aux {
  434. //! Reads the referenced mapped value from the container
  435. inline attribute_set_reference_proxy::mapped_type attribute_set_reference_proxy::read_mapped_value() const BOOST_NOEXCEPT
  436. {
  437. attribute_set::iterator it = m_pContainer->find(m_key);
  438. if (it != m_pContainer->end())
  439. return it->second;
  440. else
  441. return mapped_type();
  442. }
  443. //! Assignment operator (would be invoked in case of writing to the container)
  444. inline attribute_set_reference_proxy::mapped_type& attribute_set_reference_proxy::operator= (mapped_type const& val) const
  445. {
  446. std::pair< attribute_set::iterator, bool > res = m_pContainer->insert(m_key, val);
  447. if (!res.second)
  448. res.first->second = val;
  449. return res.first->second;
  450. }
  451. } // namespace aux
  452. #ifndef BOOST_LOG_DOXYGEN_PASS
  453. inline attribute& attribute::operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT
  454. {
  455. attribute attr = that;
  456. this->swap(attr);
  457. return *this;
  458. }
  459. #endif
  460. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  461. } // namespace boost
  462. #include <boost/log/detail/footer.hpp>
  463. #endif // BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_