Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:18

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   attribute_set.hpp
0009  * \author Andrey Semashev
0010  * \date   08.03.2007
0011  *
0012  * This header contains definition of the attribute set container.
0013  */
0014 
0015 #ifndef BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
0016 #define BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_
0017 
0018 #include <cstddef>
0019 #include <utility>
0020 #include <iterator>
0021 #include <boost/move/core.hpp>
0022 #include <boost/core/enable_if.hpp>
0023 #include <boost/type_traits/conditional.hpp>
0024 #include <boost/log/detail/config.hpp>
0025 #include <boost/log/detail/sfinae_tools.hpp>
0026 #include <boost/log/attributes/attribute_name.hpp>
0027 #include <boost/log/attributes/attribute.hpp>
0028 #include <boost/log/detail/header.hpp>
0029 
0030 #ifdef BOOST_HAS_PRAGMA_ONCE
0031 #pragma once
0032 #endif
0033 
0034 namespace boost {
0035 
0036 BOOST_LOG_OPEN_NAMESPACE
0037 
0038 class attribute_set;
0039 class attribute_value_set;
0040 
0041 namespace aux {
0042 
0043 //! Reference proxy object to implement \c operator[]
0044 class attribute_set_reference_proxy
0045 {
0046 private:
0047     //! Key type
0048     typedef attribute_name key_type;
0049     //! Mapped attribute type
0050     typedef attribute mapped_type;
0051 
0052 private:
0053     attribute_set* const m_pContainer;
0054     const key_type m_key;
0055 
0056 public:
0057     //! Constructor
0058     explicit attribute_set_reference_proxy(attribute_set* pContainer, key_type const& key) BOOST_NOEXCEPT :
0059         m_pContainer(pContainer),
0060         m_key(key)
0061     {
0062     }
0063 
0064     //! Conversion operator (would be invoked in case of reading from the container)
0065     BOOST_FORCEINLINE operator mapped_type() const BOOST_NOEXCEPT
0066     {
0067         return read_mapped_value();
0068     }
0069     //! Assignment operator (would be invoked in case of writing to the container)
0070     mapped_type& operator= (mapped_type const& val) const;
0071 
0072 private:
0073     //! Reads the referenced mapped value from the container
0074     mapped_type read_mapped_value() const BOOST_NOEXCEPT;
0075 };
0076 
0077 } // namespace aux
0078 
0079 /*!
0080  * \brief An attribute set class.
0081  *
0082  * An attribute set is an associative container with attribute name as a key and
0083  * pointer to the attribute as a mapped value. The container allows storing only one element for each distinct
0084  * key value. In most regards attribute set container provides interface similar to \c std::unordered_map.
0085  * However, there are differences in \c operator[] semantics and a number of optimizations with regard to iteration.
0086  * Besides, attribute names are stored as a read-only <tt>attribute_name</tt>'s instead of \c std::string,
0087  * which saves memory and CPU time.
0088  */
0089 class attribute_set
0090 {
0091     BOOST_COPYABLE_AND_MOVABLE_ALT(attribute_set)
0092 
0093     friend class attribute_value_set;
0094     friend class aux::attribute_set_reference_proxy;
0095 
0096 public:
0097     //! Key type
0098     typedef attribute_name key_type;
0099     //! Mapped attribute type
0100     typedef attribute mapped_type;
0101 
0102     //! Value type
0103     typedef std::pair< const key_type, mapped_type > value_type;
0104     //! Reference type
0105     typedef value_type& reference;
0106     //! Const reference type
0107     typedef value_type const& const_reference;
0108     //! Pointer type
0109     typedef value_type* pointer;
0110     //! Const pointer type
0111     typedef value_type const* const_pointer;
0112     //! Size type
0113     typedef std::size_t size_type;
0114     //! Difference type
0115     typedef std::ptrdiff_t difference_type;
0116 
0117 private:
0118     //! \cond
0119 
0120     //! Implementation
0121     struct implementation;
0122     friend struct implementation;
0123 
0124     //! A base class for the container nodes
0125     struct node_base
0126     {
0127         node_base* m_pPrev;
0128         node_base* m_pNext;
0129 
0130         node_base();
0131 
0132         BOOST_DELETED_FUNCTION(node_base(node_base const&))
0133         BOOST_DELETED_FUNCTION(node_base& operator= (node_base const&))
0134     };
0135 
0136     //! Container elements
0137     struct node;
0138     friend struct node;
0139     struct node :
0140         public node_base
0141     {
0142         value_type m_Value;
0143 
0144         node(key_type const& key, mapped_type const& data);
0145     };
0146 
0147     //! Iterator class
0148 #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
0149     template< bool fConstV > class iter;
0150     template< bool fConstV > friend class iter;
0151 #endif
0152     template< bool fConstV >
0153     class iter
0154     {
0155         friend class iter< !fConstV >;
0156         friend class attribute_set;
0157 
0158     public:
0159         //  Standard typedefs
0160         typedef attribute_set::difference_type difference_type;
0161         typedef attribute_set::value_type value_type;
0162         typedef typename boost::conditional<
0163             fConstV,
0164             attribute_set::const_reference,
0165             attribute_set::reference
0166         >::type reference;
0167         typedef typename boost::conditional<
0168             fConstV,
0169             attribute_set::const_pointer,
0170             attribute_set::pointer
0171         >::type pointer;
0172         typedef std::bidirectional_iterator_tag iterator_category;
0173 
0174     public:
0175         //  Constructors
0176         BOOST_CONSTEXPR iter() BOOST_NOEXCEPT : m_pNode(NULL) {}
0177         explicit iter(node_base* pNode) BOOST_NOEXCEPT : m_pNode(pNode) {}
0178 #if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
0179         template< bool fOtherConstV, typename = typename boost::enable_if_c< !fOtherConstV && fOtherConstV != fConstV >::type >
0180         iter(iter< fOtherConstV > const& that) BOOST_NOEXCEPT : m_pNode(that.m_pNode) {}
0181 #else
0182         template< bool fOtherConstV >
0183         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 :
0184             m_pNode(that.m_pNode)
0185         {
0186         }
0187 #endif
0188 
0189         //! Assignment
0190         template< bool fOtherConstV >
0191         typename boost::enable_if_c< !fOtherConstV && fOtherConstV != fConstV, iter& >::type operator= (iter< fOtherConstV > const& that) BOOST_NOEXCEPT
0192         {
0193             m_pNode = that.m_pNode;
0194             return *this;
0195         }
0196 
0197         //  Comparison
0198         template< bool fOtherConstV >
0199         typename boost::enable_if_c< !fOtherConstV || fOtherConstV == fConstV, bool >::type operator== (iter< fOtherConstV > const& that) const BOOST_NOEXCEPT { return (m_pNode == that.m_pNode); }
0200         template< bool fOtherConstV >
0201         typename boost::enable_if_c< !fOtherConstV || fOtherConstV == fConstV, bool >::type operator!= (iter< fOtherConstV > const& that) const BOOST_NOEXCEPT { return (m_pNode != that.m_pNode); }
0202 
0203         //  Modification
0204         iter& operator++ () BOOST_NOEXCEPT
0205         {
0206             m_pNode = m_pNode->m_pNext;
0207             return *this;
0208         }
0209         iter& operator-- () BOOST_NOEXCEPT
0210         {
0211             m_pNode = m_pNode->m_pPrev;
0212             return *this;
0213         }
0214         iter operator++ (int) BOOST_NOEXCEPT
0215         {
0216             iter tmp(*this);
0217             m_pNode = m_pNode->m_pNext;
0218             return tmp;
0219         }
0220         iter operator-- (int) BOOST_NOEXCEPT
0221         {
0222             iter tmp(*this);
0223             m_pNode = m_pNode->m_pPrev;
0224             return tmp;
0225         }
0226 
0227         //  Dereferencing
0228         pointer operator-> () const BOOST_NOEXCEPT { return &(static_cast< node* >(m_pNode)->m_Value); }
0229         reference operator* () const BOOST_NOEXCEPT { return static_cast< node* >(m_pNode)->m_Value; }
0230 
0231         node_base* base() const BOOST_NOEXCEPT { return m_pNode; }
0232 
0233     private:
0234         node_base* m_pNode;
0235     };
0236 
0237     //! \endcond
0238 
0239 public:
0240 #ifndef BOOST_LOG_DOXYGEN_PASS
0241     //! Iterator type
0242     typedef iter< false > iterator;
0243     //! Const iterator type
0244     typedef iter< true > const_iterator;
0245 #else
0246     /*!
0247      * Iterator type. The iterator complies to the bidirectional iterator requirements.
0248      */
0249     typedef implementation_defined iterator;
0250     /*!
0251      * Constant iterator type. The iterator complies to the bidirectional iterator requirements with read-only capabilities.
0252      */
0253     typedef implementation_defined const_iterator;
0254 #endif // BOOST_LOG_DOXYGEN_PASS
0255 
0256 private:
0257     //! Pointer to implementation
0258     implementation* m_pImpl;
0259 
0260 public:
0261     /*!
0262      * Default constructor.
0263      *
0264      * \post <tt>empty() == true</tt>
0265      */
0266     BOOST_LOG_API attribute_set();
0267 
0268     /*!
0269      * Copy constructor.
0270      *
0271      * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt>
0272      */
0273     BOOST_LOG_API attribute_set(attribute_set const& that);
0274 
0275     /*!
0276      * Move constructor
0277      */
0278     attribute_set(BOOST_RV_REF(attribute_set) that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl)
0279     {
0280         that.m_pImpl = NULL;
0281     }
0282 
0283     /*!
0284      * Destructor. All stored references to attributes are released.
0285      */
0286     BOOST_LOG_API ~attribute_set() BOOST_NOEXCEPT;
0287 
0288     /*!
0289      * Copy assignment operator.
0290      *
0291      * \post <tt>size() == that.size() && std::equal(begin(), end(), that.begin()) == true</tt>
0292      */
0293     attribute_set& operator= (attribute_set that) BOOST_NOEXCEPT
0294     {
0295         this->swap(that);
0296         return *this;
0297     }
0298 
0299     /*!
0300      * Swaps two instances of the container.
0301      *
0302      * \b Throws: Nothing.
0303      */
0304     void swap(attribute_set& that) BOOST_NOEXCEPT
0305     {
0306         implementation* const p = m_pImpl;
0307         m_pImpl = that.m_pImpl;
0308         that.m_pImpl = p;
0309     }
0310 
0311     /*!
0312      * \return Iterator to the first element of the container.
0313      */
0314     BOOST_LOG_API iterator begin() BOOST_NOEXCEPT;
0315     /*!
0316      * \return Iterator to the after-the-last element of the container.
0317      */
0318     BOOST_LOG_API iterator end() BOOST_NOEXCEPT;
0319     /*!
0320      * \return Constant iterator to the first element of the container.
0321      */
0322     BOOST_LOG_API const_iterator begin() const BOOST_NOEXCEPT;
0323     /*!
0324      * \return Constant iterator to the after-the-last element of the container.
0325      */
0326     BOOST_LOG_API const_iterator end() const BOOST_NOEXCEPT;
0327 
0328     /*!
0329      * \return Number of elements in the container.
0330      */
0331     BOOST_LOG_API size_type size() const BOOST_NOEXCEPT;
0332     /*!
0333      * \return true if there are no elements in the container, false otherwise.
0334      */
0335     bool empty() const BOOST_NOEXCEPT { return (this->size() == 0); }
0336 
0337     /*!
0338      * The method finds the attribute by name.
0339      *
0340      * \param key Attribute name.
0341      * \return Iterator to the found element or end() if the attribute with such name is not found.
0342      */
0343     BOOST_LOG_API iterator find(key_type key) BOOST_NOEXCEPT;
0344     /*!
0345      * The method finds the attribute by name.
0346      *
0347      * \param key Attribute name.
0348      * \return Iterator to the found element or \c end() if the attribute with such name is not found.
0349      */
0350     const_iterator find(key_type key) const BOOST_NOEXCEPT
0351     {
0352         return const_iterator(const_cast< attribute_set* >(this)->find(key));
0353     }
0354     /*!
0355      * The method counts the number of the attribute occurrences in the container. Since there can be only one
0356      * attribute with a particular key, the method always return 0 or 1.
0357      *
0358      * \param key Attribute name.
0359      * \return The number of times the attribute is found in the container.
0360      */
0361     size_type count(key_type key) const BOOST_NOEXCEPT { return size_type(this->find(key) != this->end()); }
0362 
0363     /*!
0364      * Combined lookup/insertion operator. The operator semantics depends on the further usage of the returned reference.
0365      * \li If the reference is used as an assignment target, the assignment expression is equivalent to element insertion,
0366      *     where the element is composed of the second argument of the \c operator[] as a key and the second argument of assignment
0367      *     as a mapped value.
0368      * \li If the returned reference is used in context where a conversion to the mapped type is required,
0369      *     the result of the conversion is equivalent to the mapped value found with the second argument of the \c operator[] as a key,
0370      *     if such an element exists in the container, or a default-constructed mapped value, if an element does not exist in the
0371      *     container.
0372      *
0373      * \param key Attribute name.
0374      * \return A smart reference object of unspecified type.
0375      */
0376     aux::attribute_set_reference_proxy operator[] (key_type key) BOOST_NOEXCEPT
0377     {
0378         return aux::attribute_set_reference_proxy(this, key);
0379     }
0380     /*!
0381      * Lookup operator
0382      *
0383      * \param key Attribute name.
0384      * \return If an element with the corresponding attribute name is found in the container, its mapped value
0385      *         is returned. Otherwise a default-constructed mapped value is returned.
0386      */
0387     mapped_type operator[] (key_type key) const BOOST_NOEXCEPT
0388     {
0389         const_iterator it = this->find(key);
0390         if (it != end())
0391             return it->second;
0392         else
0393             return mapped_type();
0394     }
0395 
0396     /*!
0397      * Insertion method
0398      *
0399      * \param key Attribute name.
0400      * \param data Pointer to the attribute. Must not be NULL.
0401      * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the
0402      *          inserted element. Otherwise the first component points to the element that prevents insertion.
0403      */
0404     BOOST_LOG_API std::pair< iterator, bool > insert(key_type key, mapped_type const& data);
0405 
0406     /*!
0407      * Insertion method
0408      *
0409      * \param value An element to be inserted.
0410      * \returns A pair of values. If second is true, the insertion succeeded and the first component points to the
0411      *          inserted element. Otherwise the first component points to the element that prevents insertion.
0412      */
0413     std::pair< iterator, bool > insert(const_reference value)
0414     {
0415         return this->insert(value.first, value.second);
0416     }
0417 
0418     /*!
0419      * Mass insertion method.
0420      *
0421      * \param begin A forward iterator that points to the first element to be inserted.
0422      * \param end A forward iterator that points to the after-the-last element to be inserted.
0423      */
0424     template< typename FwdIteratorT >
0425     void insert(FwdIteratorT begin, FwdIteratorT end)
0426     {
0427         for (; begin != end; ++begin)
0428             this->insert(*begin);
0429     }
0430 
0431     /*!
0432      * Mass insertion method with ability to acquire iterators to the inserted elements.
0433      *
0434      * \param begin A forward iterator that points to the first element to be inserted.
0435      * \param end A forward iterator that points to the after-the-last element to be inserted.
0436      * \param out An output iterator that receives results of insertion of the elements
0437      */
0438     template< typename FwdIteratorT, typename OutputIteratorT >
0439     void insert(FwdIteratorT begin, FwdIteratorT end, OutputIteratorT out)
0440     {
0441         for (; begin != end; ++begin, ++out)
0442             *out = this->insert(*begin);
0443     }
0444 
0445     /*!
0446      * The method erases all attributes with the specified name
0447      *
0448      * \post All iterators to the erased elements become invalid.
0449      * \param key Attribute name.
0450      * \return Tne number of erased elements
0451      */
0452     BOOST_LOG_API size_type erase(key_type key) BOOST_NOEXCEPT;
0453     /*!
0454      * The method erases the specified attribute
0455      *
0456      * \post All iterators to the erased element become invalid.
0457      * \param it A valid iterator to the element to be erased.
0458      * \return Tne number of erased elements
0459      */
0460     BOOST_LOG_API void erase(iterator it) BOOST_NOEXCEPT;
0461     /*!
0462      * The method erases all attributes within the specified range
0463      *
0464      * \pre \a end is reachable from \a begin with a finite number of increments.
0465      * \post All iterators to the erased elements become invalid.
0466      * \param begin An iterator that points to the first element to be erased.
0467      * \param end An iterator that points to the after-the-last element to be erased.
0468      */
0469     BOOST_LOG_API void erase(iterator begin, iterator end) BOOST_NOEXCEPT;
0470 
0471     /*!
0472      * The method removes all elements from the container
0473      *
0474      * \post <tt>empty() == true</tt>
0475      */
0476     BOOST_LOG_API void clear() BOOST_NOEXCEPT;
0477 };
0478 
0479 /*!
0480  * Free swap overload
0481  */
0482 inline void swap(attribute_set& left, attribute_set& right) BOOST_NOEXCEPT
0483 {
0484     left.swap(right);
0485 }
0486 
0487 namespace aux {
0488 
0489 //! Reads the referenced mapped value from the container
0490 inline attribute_set_reference_proxy::mapped_type attribute_set_reference_proxy::read_mapped_value() const BOOST_NOEXCEPT
0491 {
0492     attribute_set::iterator it = m_pContainer->find(m_key);
0493     if (it != m_pContainer->end())
0494         return it->second;
0495     else
0496         return mapped_type();
0497 }
0498 
0499 //! Assignment operator (would be invoked in case of writing to the container)
0500 inline attribute_set_reference_proxy::mapped_type& attribute_set_reference_proxy::operator= (mapped_type const& val) const
0501 {
0502     std::pair< attribute_set::iterator, bool > res = m_pContainer->insert(m_key, val);
0503     if (!res.second)
0504         res.first->second = val;
0505     return res.first->second;
0506 }
0507 
0508 } // namespace aux
0509 
0510 #ifndef BOOST_LOG_DOXYGEN_PASS
0511 inline attribute& attribute::operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT
0512 {
0513     attribute attr = that;
0514     this->swap(attr);
0515     return *this;
0516 }
0517 #endif
0518 
0519 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0520 
0521 } // namespace boost
0522 
0523 #include <boost/log/detail/footer.hpp>
0524 
0525 #endif // BOOST_LOG_ATTRIBUTE_SET_HPP_INCLUDED_