| /* |
| * 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 attribute_set.hpp |
| * \author Andrey Semashev |
| * \date 08.03.2007 |
| * |
| * This header contains definition of the attribute set container. |
| */ |
| |
| #ifndef BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_ |
| #define BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_ |
| |
| #include <cstddef> |
| #include <utility> |
| #include <iterator> |
| #include <boost/mpl/if.hpp> |
| #include <boost/move/core.hpp> |
| #include <boost/log/detail/config.hpp> |
| #include <boost/log/attributes/attribute_name.hpp> |
| #include <boost/log/attributes/attribute.hpp> |
| #include <boost/log/detail/header.hpp> |
| |
| #ifdef BOOST_HAS_PRAGMA_ONCE |
| #pragma once |
| #endif |
| |
| namespace boost { |
| |
| BOOST_LOG_OPEN_NAMESPACE |
| |
| class attribute_set; |
| class attribute_value_set; |
| |
| namespace aux { |
| |
| //! Reference proxy object to implement \c operator[] |
| class attribute_set_reference_proxy |
| { |
| private: |
| //! Key type |
| typedef attribute_name key_type; |
| //! Mapped attribute type |
| typedef attribute mapped_type; |
| |
| private: |
| attribute_set* const m_pContainer; |
| const key_type m_key; |
| |
| public: |
| //! Constructor |
| explicit attribute_set_reference_proxy(attribute_set* pContainer, key_type const& key) BOOST_NOEXCEPT : |
| m_pContainer(pContainer), |
| m_key(key) |
| { |
| } |
| |
| //! Conversion operator (would be invoked in case of reading from the container) |
| operator mapped_type() const BOOST_NOEXCEPT; |
| //! Assignment operator (would be invoked in case of writing to the container) |
| mapped_type& operator= (mapped_type const& val) const; |
| }; |
| |
| } // namespace aux |
| |
| /*! |
| * \brief An attribute set class. |
| * |
| * An attribute set is an associative container with attribute name as a key and |
| * pointer to the attribute as a mapped value. The container allows storing only one element for each distinct |
| * key value. In most regards attribute set container provides interface similar to \c std::unordered_map. |
| * However, there are differences in \c operator[] semantics and a number of optimizations with regard to iteration. |
| * Besides, attribute names are stored as a read-only <tt>attribute_name</tt>'s instead of \c std::string, |
| * which saves memory and CPU time. |
| */ |
| class attribute_set |
| { |
| BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_set) |
| |
| friend class attribute_value_set; |
| friend class aux::attribute_set_reference_proxy; |
| |
| public: |
| //! Key type |
| typedef attribute_name key_type; |
| //! Mapped attribute type |
| typedef attribute mapped_type; |
| |
| //! Value type |
| typedef std::pair< const key_type, mapped_type > value_type; |
| //! Reference type |
| typedef value_type& reference; |
| //! Const reference type |
| typedef value_type const& const_reference; |
| //! Pointer type |
| typedef value_type* pointer; |
| //! Const pointer type |
| typedef value_type const* const_pointer; |
| //! Size type |
| typedef std::size_t size_type; |
| //! Difference type |
| typedef std::ptrdiff_t difference_type; |
| |
| private: |
| //! \cond |
| |
| //! Implementation |
| struct implementation; |
| friend struct implementation; |
| |
| //! A base class for the container nodes |
| struct node_base |
| { |
| node_base* m_pPrev; |
| node_base* m_pNext; |
| |
| node_base(); |
| |
| BOOST_DELETED_FUNCTION(node_base(node_base const&)) |
| BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&)) |
| }; |
| |
| //! Container elements |
| struct node; |
| friend struct node; |
| struct node : |
| public node_base |
| { |
| value_type m_Value; |
| |
| node(key_type const& key, mapped_type const& data); |
| }; |
| |
| //! Iterator class |
| #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS |
| template< bool fConstV > class iter; |
| template< bool fConstV > friend class iter; |
| #endif |
| template< bool fConstV > |
| class iter |
| { |
| friend class iter< !fConstV >; |
| friend class attribute_set; |
| |
| public: |
| // Standard typedefs |
| typedef attribute_set::difference_type difference_type; |
| typedef attribute_set::value_type value_type; |
| typedef typename mpl::if_c< |
| fConstV, |
| attribute_set::const_reference, |
| attribute_set::reference |
| >::type reference; |
| typedef typename mpl::if_c< |
| fConstV, |
| attribute_set::const_pointer, |
| attribute_set::pointer |
| >::type pointer; |
| typedef std::bidirectional_iterator_tag iterator_category; |
| |
| public: |
| // Constructors |
| BOOST_CONSTEXPR iter() : m_pNode(NULL) {} |
| explicit iter(node_base* pNode) BOOST_NOEXCEPT : m_pNode(pNode) {} |
| iter(iter< false > const& that) BOOST_NOEXCEPT : m_pNode(that.m_pNode) {} |
| |
| //! Assignment |
| template< bool f > |
| iter& operator= (iter< f > const& that) BOOST_NOEXCEPT |
| { |
| m_pNode = that.m_pNode; |
| return *this; |
| } |
| |
| // Comparison |
| template< bool f > |
| bool operator== (iter< f > const& that) const BOOST_NOEXCEPT { return (m_pNode == that.m_pNode); } |
| template< bool f > |
| bool operator!= (iter< f > const& that) const BOOST_NOEXCEPT { return (m_pNode != that.m_pNode); } |
| |
| // Modification |
| iter& operator++ () BOOST_NOEXCEPT |
| { |
| m_pNode = m_pNode->m_pNext; |
| return *this; |
| } |
| iter& operator-- () BOOST_NOEXCEPT |
| { |
| m_pNode = m_pNode->m_pPrev; |
| return *this; |
| } |
| iter operator++ (int) BOOST_NOEXCEPT |
| { |
| iter tmp(*this); |
| m_pNode = m_pNode->m_pNext; |
| return tmp; |
| } |
| iter operator-- (int) BOOST_NOEXCEPT |
| { |
| iter tmp(*this); |
| m_pNode = m_pNode->m_pPrev; |
| return tmp; |
| } |
| |
| // Dereferencing |
| pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); } |
| reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; } |
| |
| node_base* base() const BOOST_NOEXCEPT { return m_pNode; } |
| |
| private: |
| node_base* m_pNode; |
| }; |
| |
| //! \endcond |
| |
| public: |
| #ifndef BOOST_LOG_DOXYGEN_PASS |
| //! Iterator type |
| typedef iter< false > iterator; |
| //! Const iterator type |
| typedef iter< true > const_iterator; |
| #else |
| /*! |
| * Iterator type. The iterator complies to the bidirectional iterator requirements. |
| */ |
| typedef implementation_defined iterator; |
| /*! |
| * Constant iterator type. The iterator complies to the bidirectional iterator requirements with read-only capabilities. |
| */ |
| typedef implementation_defined const_iterator; |
| #endif // BOOST_LOG_DOXYGEN_PASS |
| |
| private: |
| //! Pointer to implementation |
| implementation* m_pImpl; |
| |
| public: |
| /*! |
| * Default constructor. |
| * |
| * \post <tt>empty() == true</tt> |
| */ |
| BOOST_LOG_API attribute_set(); |
| |
| /*! |
| * Copy constructor. |
| * |
| * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt> |
| */ |
| BOOST_LOG_API attribute_set(attribute_set const& that); |
| |
| /*! |
| * Move constructor |
| */ |
| attribute_set(BOOST_RV_REF(attribute_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) |
| { |
| that.m_pImpl = NULL; |
| } |
| |
| /*! |
| * Destructor. All stored references to attributes are released. |
| */ |
| BOOST_LOG_API ~attribute_set() BOOST_NOEXCEPT; |
| |
| /*! |
| * Copy assignment operator. |
| * |
| * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt> |
| */ |
| attribute_set& operator= (attribute_set that) BOOST_NOEXCEPT |
| { |
| this->swap(that); |
| return *this; |
| } |
| |
| /*! |
| * Swaps two instances of the container. |
| * |
| * \b Throws: Nothing. |
| */ |
| void swap(attribute_set& that) BOOST_NOEXCEPT |
| { |
| implementation* const p = m_pImpl; |
| m_pImpl = that.m_pImpl; |
| that.m_pImpl = p; |
| } |
| |
| /*! |
| * \return Iterator to the first element of the container. |
| */ |
| BOOST_LOG_API iterator begin() BOOST_NOEXCEPT; |
| /*! |
| * \return Iterator to the after-the-last element of the container. |
| */ |
| BOOST_LOG_API iterator end() BOOST_NOEXCEPT; |
| /*! |
| * \return Constant iterator to the first element of the container. |
| */ |
| BOOST_LOG_API const_iterator begin() const BOOST_NOEXCEPT; |
| /*! |
| * \return Constant iterator to the after-the-last element of the container. |
| */ |
| BOOST_LOG_API const_iterator end() const BOOST_NOEXCEPT; |
| |
| /*! |
| * \return Number of elements in the container. |
| */ |
| BOOST_LOG_API size_type size() const BOOST_NOEXCEPT; |
| /*! |
| * \return true if there are no elements in the container, false otherwise. |
| */ |
| bool empty() const BOOST_NOEXCEPT { return (this->size() == 0); } |
| |
| /*! |
| * The method finds the attribute by name. |
| * |
| * \param key Attribute name. |
| * \return Iterator to the found element or end() if the attribute with such name is not found. |
| */ |
| BOOST_LOG_API iterator find(key_type key) BOOST_NOEXCEPT; |
| /*! |
| * The method finds the attribute by name. |
| * |
| * \param key Attribute name. |
| * \return Iterator to the found element or \c end() if the attribute with such name is not found. |
| */ |
| const_iterator find(key_type key) const BOOST_NOEXCEPT |
| { |
| return const_iterator(const_cast< attribute_set* >(this)->find(key)); |
| } |
| /*! |
| * The method counts the number of the attribute occurrences in the container. Since there can be only one |
| * attribute with a particular key, the method always return 0 or 1. |
| * |
| * \param key Attribute name. |
| * \return The number of times the attribute is found in the container. |
| */ |
| size_type count(key_type key) const BOOST_NOEXCEPT { return size_type(this->find(key) != this->end()); } |
| |
| /*! |
| * Combined lookup/insertion operator. The operator semantics depends on the further usage of the returned reference. |
| * \li If the reference is used as an assignment target, the assignment expression is equivalent to element insertion, |
| * where the element is composed of the second argument of the \c operator[] as a key and the second argument of assignment |
| * as a mapped value. |
| * \li If the returned reference is used in context where a conversion to the mapped type is required, |
| * the result of the conversion is equivalent to the mapped value found with the second argument of the \c operator[] as a key, |
| * if such an element exists in the container, or a default-constructed mapped value, if an element does not exist in the |
| * container. |
| * |
| * \param key Attribute name. |
| * \return A smart reference object of unspecified type. |
| */ |
| aux::attribute_set_reference_proxy operator[] (key_type key) BOOST_NOEXCEPT |
| { |
| return aux::attribute_set_reference_proxy(this, key); |
| } |
| /*! |
| * Lookup operator |
| * |
| * \param key Attribute name. |
| * \return If an element with the corresponding attribute name is found in the container, its mapped value |
| * is returned. Otherwise a default-constructed mapped value is returned. |
| */ |
| mapped_type operator[] (key_type key) const BOOST_NOEXCEPT |
| { |
| const_iterator it = this->find(key); |
| if (it != end()) |
| return it->second; |
| else |
| return mapped_type(); |
| } |
| |
| /*! |
| * Insertion method |
| * |
| * \param key Attribute name. |
| * \param data Pointer to the attribute. Must not be NULL. |
| * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the |
| * inserted element. Otherwise the first component points to the element that prevents insertion. |
| */ |
| BOOST_LOG_API std::pair< iterator, bool > insert(key_type key, mapped_type const& data); |
| |
| /*! |
| * Insertion method |
| * |
| * \param value An element to be inserted. |
| * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the |
| * inserted element. Otherwise the first component points to the element that prevents insertion. |
| */ |
| std::pair< iterator, bool > insert(const_reference value) |
| { |
| return this->insert(value.first, value.second); |
| } |
| |
| /*! |
| * Mass insertion method. |
| * |
| * \param begin A forward iterator that points to the first element to be inserted. |
| * \param end A forward iterator that points to the after-the-last element to be inserted. |
| */ |
| template< typename FwdIteratorT > |
| void insert(FwdIteratorT begin, FwdIteratorT end) |
| { |
| for (; begin != end; ++begin) |
| this->insert(*begin); |
| } |
| |
| /*! |
| * Mass insertion method with ability to acquire iterators to the inserted elements. |
| * |
| * \param begin A forward iterator that points to the first element to be inserted. |
| * \param end A forward iterator that points to the after-the-last element to be inserted. |
| * \param out An output iterator that receives results of insertion of the elements |
| */ |
| template< typename FwdIteratorT, typename OutputIteratorT > |
| void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out) |
| { |
| for (; begin != end; ++begin, ++out) |
| *out = this->insert(*begin); |
| } |
| |
| /*! |
| * The method erases all attributes with the specified name |
| * |
| * \post All iterators to the erased elements become invalid. |
| * \param key Attribute name. |
| * \return Tne number of erased elements |
| */ |
| BOOST_LOG_API size_type erase(key_type key) BOOST_NOEXCEPT; |
| /*! |
| * The method erases the specified attribute |
| * |
| * \post All iterators to the erased element become invalid. |
| * \param it A valid iterator to the element to be erased. |
| * \return Tne number of erased elements |
| */ |
| BOOST_LOG_API void erase(iterator it) BOOST_NOEXCEPT; |
| /*! |
| * The method erases all attributes within the specified range |
| * |
| * \pre \a end is reachable from \a begin with a finite number of increments. |
| * \post All iterators to the erased elements become invalid. |
| * \param begin An iterator that points to the first element to be erased. |
| * \param end An iterator that points to the after-the-last element to be erased. |
| */ |
| BOOST_LOG_API void erase(iterator begin, iterator end) BOOST_NOEXCEPT; |
| |
| /*! |
| * The method removes all elements from the container |
| * |
| * \post <tt>empty() == true</tt> |
| */ |
| BOOST_LOG_API void clear() BOOST_NOEXCEPT; |
| }; |
| |
| /*! |
| * Free swap overload |
| */ |
| inline void swap(attribute_set& left, attribute_set& right) BOOST_NOEXCEPT |
| { |
| left.swap(right); |
| } |
| |
| namespace aux { |
| |
| //! Conversion operator (would be invoked in case of reading from the container) |
| inline attribute_set_reference_proxy::operator mapped_type() const BOOST_NOEXCEPT |
| { |
| attribute_set::iterator it = m_pContainer->find(m_key); |
| if (it != m_pContainer->end()) |
| return it->second; |
| else |
| return mapped_type(); |
| } |
| |
| //! Assignment operator (would be invoked in case of writing to the container) |
| inline attribute_set_reference_proxy::mapped_type& attribute_set_reference_proxy::operator= (mapped_type const& val) const |
| { |
| std::pair< attribute_set::iterator, bool > res = m_pContainer->insert(m_key, val); |
| if (!res.second) |
| res.first->second = val; |
| return res.first->second; |
| } |
| |
| } // namespace aux |
| |
| #ifndef BOOST_LOG_DOXYGEN_PASS |
| inline attribute& attribute::operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT |
| { |
| attribute attr = that; |
| this->swap(attr); |
| return *this; |
| } |
| #endif |
| |
| BOOST_LOG_CLOSE_NAMESPACE // namespace log |
| |
| } // namespace boost |
| |
| #include <boost/log/detail/footer.hpp> |
| |
| #endif // BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_ |