attribute_set.hpp 16 KB

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