Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:34:29

0001 // Helper classes and functions for the circular buffer.
0002 
0003 // Copyright (c) 2003-2008 Jan Gaspar
0004 
0005 // Copyright 2014,2018 Glen Joseph Fernandes
0006 // (glenjofe@gmail.com)
0007 
0008 // Use, modification, and distribution is subject to the Boost Software
0009 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0010 // http://www.boost.org/LICENSE_1_0.txt)
0011 
0012 #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)
0013 #define BOOST_CIRCULAR_BUFFER_DETAILS_HPP
0014 
0015 #if defined(_MSC_VER)
0016     #pragma once
0017 #endif
0018 
0019 #include <boost/throw_exception.hpp>
0020 #include <boost/core/allocator_access.hpp>
0021 #include <boost/core/pointer_traits.hpp>
0022 #include <boost/move/move.hpp>
0023 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
0024 #include <boost/core/no_exceptions_support.hpp>
0025 #include <iterator>
0026 
0027 // Silence MS /W4 warnings like C4913:
0028 // "user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used"
0029 // This might happen when previously including some boost headers that overload the coma operator.
0030 #if defined(_MSC_VER)
0031 #  pragma warning(push)
0032 #  pragma warning(disable:4913)
0033 #endif
0034 
0035 namespace boost {
0036 
0037 namespace cb_details {
0038 
0039 template <class Alloc> struct nonconst_traits;
0040 
0041 template<class ForwardIterator, class Diff, class T, class Alloc>
0042 void uninitialized_fill_n_with_alloc(
0043     ForwardIterator first, Diff n, const T& item, Alloc& alloc);
0044 
0045 template<class InputIterator, class ForwardIterator, class Alloc>
0046 ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a);
0047 
0048 template<class InputIterator, class ForwardIterator, class Alloc>
0049 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a);
0050 
0051 /*!
0052     \struct const_traits
0053     \brief Defines the data types for a const iterator.
0054 */
0055 template <class Alloc>
0056 struct const_traits {
0057     // Basic types
0058     typedef typename Alloc::value_type value_type;
0059     typedef typename boost::allocator_const_pointer<Alloc>::type pointer;
0060     typedef const value_type& reference;
0061     typedef typename boost::allocator_size_type<Alloc>::type size_type;
0062     typedef typename boost::allocator_difference_type<Alloc>::type difference_type;
0063 
0064     // Non-const traits
0065     typedef nonconst_traits<Alloc> nonconst_self;
0066 };
0067 
0068 /*!
0069     \struct nonconst_traits
0070     \brief Defines the data types for a non-const iterator.
0071 */
0072 template <class Alloc>
0073 struct nonconst_traits {
0074     // Basic types
0075     typedef typename Alloc::value_type value_type;
0076     typedef typename boost::allocator_pointer<Alloc>::type pointer;
0077     typedef value_type& reference;
0078     typedef typename boost::allocator_size_type<Alloc>::type size_type;
0079     typedef typename boost::allocator_difference_type<Alloc>::type difference_type;
0080 
0081     // Non-const traits
0082     typedef nonconst_traits<Alloc> nonconst_self;
0083 };
0084 
0085 /*!
0086     \struct iterator_wrapper
0087     \brief Helper iterator dereference wrapper.
0088 */
0089 template <class Iterator>
0090 struct iterator_wrapper {
0091     mutable Iterator m_it;
0092     explicit iterator_wrapper(Iterator it) : m_it(it) {}
0093     Iterator operator () () const { return m_it++; }
0094 private:
0095     iterator_wrapper<Iterator>& operator = (const iterator_wrapper<Iterator>&); // do not generate
0096 };
0097 
0098 /*!
0099     \struct item_wrapper
0100     \brief Helper item dereference wrapper.
0101 */
0102 template <class Pointer, class Value>
0103 struct item_wrapper {
0104     Value m_item;
0105     explicit item_wrapper(Value item) : m_item(item) {}
0106     Pointer operator () () const { return &m_item; }
0107 private:
0108     item_wrapper<Pointer, Value>& operator = (const item_wrapper<Pointer, Value>&); // do not generate
0109 };
0110 
0111 /*!
0112     \struct assign_n
0113     \brief Helper functor for assigning n items.
0114 */
0115 template <class Value, class Alloc>
0116 struct assign_n {
0117     typedef typename boost::allocator_size_type<Alloc>::type size_type;
0118     size_type m_n;
0119     Value m_item;
0120     Alloc& m_alloc;
0121     assign_n(size_type n, Value item, Alloc& alloc) : m_n(n), m_item(item), m_alloc(alloc) {}
0122     template <class Pointer>
0123     void operator () (Pointer p) const {
0124         uninitialized_fill_n_with_alloc(p, m_n, m_item, m_alloc);
0125     }
0126 private:
0127     assign_n<Value, Alloc>& operator = (const assign_n<Value, Alloc>&); // do not generate
0128 };
0129 
0130 /*!
0131     \struct assign_range
0132     \brief Helper functor for assigning range of items.
0133 */
0134 template <class Iterator, class Alloc>
0135 struct assign_range {
0136     Iterator m_first;
0137     Iterator m_last;
0138     Alloc&   m_alloc;
0139 
0140     assign_range(const Iterator& first, const Iterator& last, Alloc& alloc)
0141         : m_first(first), m_last(last), m_alloc(alloc) {}
0142 
0143     template <class Pointer>
0144     void operator () (Pointer p) const {
0145         boost::cb_details::uninitialized_copy(m_first, m_last, p, m_alloc);
0146     }
0147 };
0148 
0149 template <class Iterator, class Alloc>
0150 inline assign_range<Iterator, Alloc> make_assign_range(const Iterator& first, const Iterator& last, Alloc& a) {
0151     return assign_range<Iterator, Alloc>(first, last, a);
0152 }
0153 
0154 /*!
0155     \class capacity_control
0156     \brief Capacity controller of the space optimized circular buffer.
0157 */
0158 template <class Size>
0159 class capacity_control {
0160 
0161     //! The capacity of the space-optimized circular buffer.
0162     Size m_capacity;
0163 
0164     //! The lowest guaranteed or minimum capacity of the adapted space-optimized circular buffer.
0165     Size m_min_capacity;
0166 
0167 public:
0168 
0169     //! Constructor.
0170     capacity_control(Size buffer_capacity, Size min_buffer_capacity = 0)
0171     : m_capacity(buffer_capacity), m_min_capacity(min_buffer_capacity)
0172     { // Check for capacity lower than min_capacity.
0173         BOOST_CB_ASSERT(buffer_capacity >= min_buffer_capacity);
0174     }
0175 
0176     // Default copy constructor.
0177 
0178     // Default assign operator.
0179 
0180     //! Get the capacity of the space optimized circular buffer.
0181     Size capacity() const { return m_capacity; }
0182 
0183     //! Get the minimal capacity of the space optimized circular buffer.
0184     Size min_capacity() const { return m_min_capacity; }
0185 
0186     //! Size operator - returns the capacity of the space optimized circular buffer.
0187     operator Size() const { return m_capacity; }
0188 };
0189 
0190 /*!
0191     \struct iterator
0192     \brief Random access iterator for the circular buffer.
0193     \param Buff The type of the underlying circular buffer.
0194     \param Traits Basic iterator types.
0195     \note This iterator is not circular. It was designed
0196           for iterating from begin() to end() of the circular buffer.
0197 */
0198 template <class Buff, class Traits>
0199 struct iterator
0200 #if BOOST_CB_ENABLE_DEBUG
0201     : public debug_iterator_base
0202 #endif // #if BOOST_CB_ENABLE_DEBUG
0203 {
0204 // Helper types
0205 
0206     //! Non-const iterator.
0207     typedef iterator<Buff, typename Traits::nonconst_self> nonconst_self;
0208 
0209 // Basic types
0210     typedef std::random_access_iterator_tag iterator_category;
0211 
0212     //! The type of the elements stored in the circular buffer.
0213     typedef typename Traits::value_type value_type;
0214 
0215     //! Pointer to the element.
0216     typedef typename Traits::pointer pointer;
0217 
0218     //! Reference to the element.
0219     typedef typename Traits::reference reference;
0220 
0221     //! Size type.
0222     typedef typename Traits::size_type size_type;
0223 
0224     //! Difference type.
0225     typedef typename Traits::difference_type difference_type;
0226 
0227 // Member variables
0228 
0229     //! The circular buffer where the iterator points to.
0230     const Buff* m_buff;
0231 
0232     //! An internal iterator.
0233     pointer m_it;
0234 
0235 // Construction & assignment
0236 
0237     // Default copy constructor.
0238 
0239     //! Default constructor.
0240     iterator() : m_buff(0), m_it(0) {}
0241 
0242 #if BOOST_CB_ENABLE_DEBUG
0243 
0244     //! Copy constructor (used for converting from a non-const to a const iterator).
0245     iterator(const nonconst_self& it) : debug_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {}
0246 
0247     //! Internal constructor.
0248     /*!
0249         \note This constructor is not intended to be used directly by the user.
0250     */
0251     iterator(const Buff* cb, const pointer p) : debug_iterator_base(cb), m_buff(cb), m_it(p) {}
0252 
0253 #else
0254 
0255     iterator(const nonconst_self& it) : m_buff(it.m_buff), m_it(it.m_it) {}
0256 
0257     iterator(const Buff* cb, const pointer p) : m_buff(cb), m_it(p) {}
0258 
0259 #endif // #if BOOST_CB_ENABLE_DEBUG
0260 
0261     //! Assign operator.
0262 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
0263     iterator& operator=(const iterator&) = default;
0264 #else
0265     iterator& operator=(const iterator& it) {
0266         if (this == &it)
0267             return *this;
0268 #if BOOST_CB_ENABLE_DEBUG
0269         debug_iterator_base::operator =(it);
0270 #endif // #if BOOST_CB_ENABLE_DEBUG
0271         m_buff = it.m_buff;
0272         m_it = it.m_it;
0273         return *this;
0274     }
0275 #endif
0276 
0277 // Random access iterator methods
0278 
0279     //! Dereferencing operator.
0280     reference operator * () const {
0281         BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
0282         BOOST_CB_ASSERT(m_it != 0);        // check for iterator pointing to end()
0283         return *m_it;
0284     }
0285 
0286     //! Dereferencing operator.
0287     pointer operator -> () const { return &(operator*()); }
0288 
0289     //! Difference operator.
0290     template <class Traits0>
0291     difference_type operator - (const iterator<Buff, Traits0>& it) const {
0292         BOOST_CB_ASSERT(is_valid(m_buff));    // check for uninitialized or invalidated iterator
0293         BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
0294         return linearize_pointer(*this) - linearize_pointer(it);
0295     }
0296 
0297     //! Increment operator (prefix).
0298     iterator& operator ++ () {
0299         BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
0300         BOOST_CB_ASSERT(m_it != 0);        // check for iterator pointing to end()
0301         m_buff->increment(m_it);
0302         if (m_it == m_buff->m_last)
0303             m_it = 0;
0304         return *this;
0305     }
0306 
0307     //! Increment operator (postfix).
0308     iterator operator ++ (int) {
0309         iterator<Buff, Traits> tmp = *this;
0310         ++*this;
0311         return tmp;
0312     }
0313 
0314     //! Decrement operator (prefix).
0315     iterator& operator -- () {
0316         BOOST_CB_ASSERT(is_valid(m_buff));        // check for uninitialized or invalidated iterator
0317         BOOST_CB_ASSERT(m_it != m_buff->m_first); // check for iterator pointing to begin()
0318         if (m_it == 0)
0319             m_it = m_buff->m_last;
0320         m_buff->decrement(m_it);
0321         return *this;
0322     }
0323 
0324     //! Decrement operator (postfix).
0325     iterator operator -- (int) {
0326         iterator<Buff, Traits> tmp = *this;
0327         --*this;
0328         return tmp;
0329     }
0330 
0331     //! Iterator addition.
0332     iterator& operator += (difference_type n) {
0333         BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
0334         if (n > 0) {
0335             BOOST_CB_ASSERT(m_buff->end() - *this >= n); // check for too large n
0336             m_it = m_buff->add(m_it, n);
0337             if (m_it == m_buff->m_last)
0338                 m_it = 0;
0339         } else if (n < 0) {
0340             *this -= -n;
0341         }
0342         return *this;
0343     }
0344 
0345     //! Iterator addition.
0346     iterator operator + (difference_type n) const { return iterator<Buff, Traits>(*this) += n; }
0347 
0348     //! Iterator subtraction.
0349     iterator& operator -= (difference_type n) {
0350         BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
0351         if (n > 0) {
0352             BOOST_CB_ASSERT(*this - m_buff->begin() >= n); // check for too large n
0353             m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n);
0354         } else if (n < 0) {
0355             *this += -n;
0356         }
0357         return *this;
0358     }
0359 
0360     //! Iterator subtraction.
0361     iterator operator - (difference_type n) const { return iterator<Buff, Traits>(*this) -= n; }
0362 
0363     //! Element access operator.
0364     reference operator [] (difference_type n) const { return *(*this + n); }
0365 
0366 // Equality & comparison
0367 
0368     //! Equality.
0369     template <class Traits0>
0370     bool operator == (const iterator<Buff, Traits0>& it) const {
0371         BOOST_CB_ASSERT(is_valid(m_buff));    // check for uninitialized or invalidated iterator
0372         BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
0373         return m_it == it.m_it;
0374     }
0375 
0376     //! Inequality.
0377     template <class Traits0>
0378     bool operator != (const iterator<Buff, Traits0>& it) const {
0379         BOOST_CB_ASSERT(is_valid(m_buff));    // check for uninitialized or invalidated iterator
0380         BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
0381         return m_it != it.m_it;
0382     }
0383 
0384     //! Less.
0385     template <class Traits0>
0386     bool operator < (const iterator<Buff, Traits0>& it) const {
0387         BOOST_CB_ASSERT(is_valid(m_buff));    // check for uninitialized or invalidated iterator
0388         BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
0389         return linearize_pointer(*this) < linearize_pointer(it);
0390     }
0391 
0392     //! Greater.
0393     template <class Traits0>
0394     bool operator > (const iterator<Buff, Traits0>& it) const { return it < *this; }
0395 
0396     //! Less or equal.
0397     template <class Traits0>
0398     bool operator <= (const iterator<Buff, Traits0>& it) const { return !(it < *this); }
0399 
0400     //! Greater or equal.
0401     template <class Traits0>
0402     bool operator >= (const iterator<Buff, Traits0>& it) const { return !(*this < it); }
0403 
0404 // Helpers
0405 
0406     //! Get a pointer which would point to the same element as the iterator in case the circular buffer is linearized.
0407     template <class Traits0>
0408     typename Traits0::pointer linearize_pointer(const iterator<Buff, Traits0>& it) const {
0409         return it.m_it == 0 ? m_buff->m_buff + m_buff->size() :
0410             (it.m_it < m_buff->m_first ? it.m_it + (m_buff->m_end - m_buff->m_first)
0411                 : m_buff->m_buff + (it.m_it - m_buff->m_first));
0412     }
0413 };
0414 
0415 //! Iterator addition.
0416 template <class Buff, class Traits>
0417 inline iterator<Buff, Traits>
0418 operator + (typename Traits::difference_type n, const iterator<Buff, Traits>& it) {
0419     return it + n;
0420 }
0421 
0422 /*!
0423     \fn ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest)
0424     \brief Equivalent of <code>std::uninitialized_copy</code> but with explicit specification of value type.
0425 */
0426 template<class InputIterator, class ForwardIterator, class Alloc>
0427 inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) {
0428     ForwardIterator next = dest;
0429     BOOST_TRY {
0430         for (; first != last; ++first, ++dest)
0431             boost::allocator_construct(a, boost::to_address(dest), *first);
0432     } BOOST_CATCH(...) {
0433         for (; next != dest; ++next)
0434             boost::allocator_destroy(a, boost::to_address(next));
0435         BOOST_RETHROW
0436     }
0437     BOOST_CATCH_END
0438     return dest;
0439 }
0440 
0441 template<class InputIterator, class ForwardIterator, class Alloc>
0442 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
0443     true_type) {
0444     for (; first != last; ++first, ++dest)
0445         boost::allocator_construct(a, boost::to_address(dest), boost::move(*first));
0446     return dest;
0447 }
0448 
0449 template<class InputIterator, class ForwardIterator, class Alloc>
0450 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a,
0451     false_type) {
0452     return uninitialized_copy(first, last, dest, a);
0453 }
0454 
0455 /*!
0456     \fn ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest)
0457     \brief Equivalent of <code>std::uninitialized_copy</code> but with explicit specification of value type and moves elements if they have noexcept move constructors.
0458 */
0459 template<class InputIterator, class ForwardIterator, class Alloc>
0460 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) {
0461     typedef typename boost::is_nothrow_move_constructible<typename Alloc::value_type>::type tag_t;
0462     return uninitialized_move_if_noexcept_impl(first, last, dest, a, tag_t());
0463 }
0464 
0465 /*!
0466     \fn void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc)
0467     \brief Equivalent of <code>std::uninitialized_fill_n</code> with allocator.
0468 */
0469 template<class ForwardIterator, class Diff, class T, class Alloc>
0470 inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) {
0471     ForwardIterator next = first;
0472     BOOST_TRY {
0473         for (; n > 0; ++first, --n)
0474             boost::allocator_construct(alloc, boost::to_address(first), item);
0475     } BOOST_CATCH(...) {
0476         for (; next != first; ++next)
0477             boost::allocator_destroy(alloc, boost::to_address(next));
0478         BOOST_RETHROW
0479     }
0480     BOOST_CATCH_END
0481 }
0482 
0483 } // namespace cb_details
0484 
0485 } // namespace boost
0486 
0487 #if defined(_MSC_VER)
0488 #  pragma warning(pop)
0489 #endif
0490 
0491 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)