1 // Helper classes and functions for the circular buffer.
3 // Copyright (c) 2003-2008 Jan Gaspar
5 // Use, modification, and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)
10 #define BOOST_CIRCULAR_BUFFER_DETAILS_HPP
12 #if defined(_MSC_VER) && _MSC_VER >= 1200
16 #include <boost/iterator.hpp>
17 #include <boost/throw_exception.hpp>
18 #include <boost/detail/no_exceptions_support.hpp>
23 namespace cb_details
{
25 template <class Traits
> struct nonconst_traits
;
27 template<class ForwardIterator
, class Diff
, class T
, class Alloc
>
28 void uninitialized_fill_n_with_alloc(
29 ForwardIterator first
, Diff n
, const T
& item
, Alloc
& alloc
);
31 template<class InputIterator
, class ForwardIterator
, class Alloc
>
32 ForwardIterator
uninitialized_copy_with_alloc(
33 InputIterator first
, InputIterator last
, ForwardIterator dest
, Alloc
& alloc
);
37 \brief Defines the data types for a const iterator.
39 template <class Traits
>
42 typedef typename
Traits::value_type value_type
;
43 typedef typename
Traits::const_pointer pointer
;
44 typedef typename
Traits::const_reference reference
;
45 typedef typename
Traits::size_type size_type
;
46 typedef typename
Traits::difference_type difference_type
;
49 typedef nonconst_traits
<Traits
> nonconst_self
;
53 \struct nonconst_traits
54 \brief Defines the data types for a non-const iterator.
56 template <class Traits
>
57 struct nonconst_traits
{
59 typedef typename
Traits::value_type value_type
;
60 typedef typename
Traits::pointer pointer
;
61 typedef typename
Traits::reference reference
;
62 typedef typename
Traits::size_type size_type
;
63 typedef typename
Traits::difference_type difference_type
;
66 typedef nonconst_traits
<Traits
> nonconst_self
;
70 \struct iterator_wrapper
71 \brief Helper iterator dereference wrapper.
73 template <class Iterator
>
74 struct iterator_wrapper
{
75 mutable Iterator m_it
;
76 explicit iterator_wrapper(Iterator it
) : m_it(it
) {}
77 Iterator
operator () () const { return m_it
++; }
79 iterator_wrapper
<Iterator
>& operator = (const iterator_wrapper
<Iterator
>&); // do not generate
84 \brief Helper item dereference wrapper.
86 template <class Pointer
, class Value
>
89 explicit item_wrapper(Value item
) : m_item(item
) {}
90 Pointer
operator () () const { return &m_item
; }
92 item_wrapper
<Pointer
, Value
>& operator = (const item_wrapper
<Pointer
, Value
>&); // do not generate
97 \brief Helper functor for assigning n items.
99 template <class Value
, class Alloc
>
101 typedef typename
Alloc::size_type size_type
;
105 assign_n(size_type n
, Value item
, Alloc
& alloc
) : m_n(n
), m_item(item
), m_alloc(alloc
) {}
106 template <class Pointer
>
107 void operator () (Pointer p
) const {
108 uninitialized_fill_n_with_alloc(p
, m_n
, m_item
, m_alloc
);
111 assign_n
<Value
, Alloc
>& operator = (const assign_n
<Value
, Alloc
>&); // do not generate
116 \brief Helper functor for assigning range of items.
118 template <class Iterator
, class Alloc
>
119 struct assign_range
{
120 const Iterator
& m_first
;
121 const Iterator
& m_last
;
123 assign_range(const Iterator
& first
, const Iterator
& last
, Alloc
& alloc
)
124 : m_first(first
), m_last(last
), m_alloc(alloc
) {}
125 template <class Pointer
>
126 void operator () (Pointer p
) const {
127 uninitialized_copy_with_alloc(m_first
, m_last
, p
, m_alloc
);
130 assign_range
<Iterator
, Alloc
>& operator = (const assign_range
<Iterator
, Alloc
>&); // do not generate
134 \class capacity_control
135 \brief Capacity controller of the space optimized circular buffer.
137 template <class Size
>
138 class capacity_control
{
140 //! The capacity of the space optimized circular buffer.
143 //! The lowest guaranteed capacity of the adapted circular buffer.
149 capacity_control(Size capacity
, Size min_capacity
= 0)
150 : m_capacity(capacity
), m_min_capacity(min_capacity
) {
151 BOOST_CB_ASSERT(capacity
>= min_capacity
); // check for capacity lower than min_capacity
154 // Default copy constructor.
156 // Default assign operator.
158 //! Get the capacity of the space optimized circular buffer.
159 Size
capacity() const { return m_capacity
; }
161 //! Get the minimal capacity of the space optimized circular buffer.
162 Size
min_capacity() const { return m_min_capacity
; }
164 //! Size operator - returns the capacity of the space optimized circular buffer.
165 operator Size() const { return m_capacity
; }
170 \brief Random access iterator for the circular buffer.
171 \param Buff The type of the underlying circular buffer.
172 \param Traits Basic iterator types.
173 \note This iterator is not circular. It was designed
174 for iterating from begin() to end() of the circular buffer.
176 template <class Buff
, class Traits
>
178 public boost::iterator
<
179 std::random_access_iterator_tag
,
180 typename
Traits::value_type
,
181 typename
Traits::difference_type
,
182 typename
Traits::pointer
,
183 typename
Traits::reference
>
184 #if BOOST_CB_ENABLE_DEBUG
185 , public debug_iterator_base
186 #endif // #if BOOST_CB_ENABLE_DEBUG
191 typedef boost::iterator
<
192 std::random_access_iterator_tag
,
193 typename
Traits::value_type
,
194 typename
Traits::difference_type
,
195 typename
Traits::pointer
,
196 typename
Traits::reference
> base_iterator
;
198 //! Non-const iterator.
199 typedef iterator
<Buff
, typename
Traits::nonconst_self
> nonconst_self
;
203 //! The type of the elements stored in the circular buffer.
204 typedef typename
base_iterator::value_type value_type
;
206 //! Pointer to the element.
207 typedef typename
base_iterator::pointer pointer
;
209 //! Reference to the element.
210 typedef typename
base_iterator::reference reference
;
213 typedef typename
Traits::size_type size_type
;
216 typedef typename
base_iterator::difference_type difference_type
;
220 //! The circular buffer where the iterator points to.
223 //! An internal iterator.
226 // Construction & assignment
228 // Default copy constructor.
230 //! Default constructor.
231 iterator() : m_buff(0), m_it(0) {}
233 #if BOOST_CB_ENABLE_DEBUG
235 //! Copy constructor (used for converting from a non-const to a const iterator).
236 iterator(const nonconst_self
& it
) : debug_iterator_base(it
), m_buff(it
.m_buff
), m_it(it
.m_it
) {}
238 //! Internal constructor.
240 \note This constructor is not intended to be used directly by the user.
242 iterator(const Buff
* cb
, const pointer p
) : debug_iterator_base(cb
), m_buff(cb
), m_it(p
) {}
246 iterator(const nonconst_self
& it
) : m_buff(it
.m_buff
), m_it(it
.m_it
) {}
248 iterator(const Buff
* cb
, const pointer p
) : m_buff(cb
), m_it(p
) {}
250 #endif // #if BOOST_CB_ENABLE_DEBUG
253 iterator
& operator = (const iterator
& it
) {
256 #if BOOST_CB_ENABLE_DEBUG
257 debug_iterator_base::operator =(it
);
258 #endif // #if BOOST_CB_ENABLE_DEBUG
264 // Random access iterator methods
266 //! Dereferencing operator.
267 reference
operator * () const {
268 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
269 BOOST_CB_ASSERT(m_it
!= 0); // check for iterator pointing to end()
273 //! Dereferencing operator.
274 pointer
operator -> () const { return &(operator*()); }
276 //! Difference operator.
277 template <class Traits0
>
278 difference_type
operator - (const iterator
<Buff
, Traits0
>& it
) const {
279 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
280 BOOST_CB_ASSERT(it
.is_valid(m_buff
)); // check for uninitialized or invalidated iterator
281 return linearize_pointer(*this) - linearize_pointer(it
);
284 //! Increment operator (prefix).
285 iterator
& operator ++ () {
286 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
287 BOOST_CB_ASSERT(m_it
!= 0); // check for iterator pointing to end()
288 m_buff
->increment(m_it
);
289 if (m_it
== m_buff
->m_last
)
294 //! Increment operator (postfix).
295 iterator
operator ++ (int) {
296 iterator
<Buff
, Traits
> tmp
= *this;
301 //! Decrement operator (prefix).
302 iterator
& operator -- () {
303 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
304 BOOST_CB_ASSERT(m_it
!= m_buff
->m_first
); // check for iterator pointing to begin()
306 m_it
= m_buff
->m_last
;
307 m_buff
->decrement(m_it
);
311 //! Decrement operator (postfix).
312 iterator
operator -- (int) {
313 iterator
<Buff
, Traits
> tmp
= *this;
318 //! Iterator addition.
319 iterator
& operator += (difference_type n
) {
320 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
322 BOOST_CB_ASSERT(m_buff
->end() - *this >= n
); // check for too large n
323 m_it
= m_buff
->add(m_it
, n
);
324 if (m_it
== m_buff
->m_last
)
332 //! Iterator addition.
333 iterator
operator + (difference_type n
) const { return iterator
<Buff
, Traits
>(*this) += n
; }
335 //! Iterator subtraction.
336 iterator
& operator -= (difference_type n
) {
337 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
339 BOOST_CB_ASSERT(*this - m_buff
->begin() >= n
); // check for too large n
340 m_it
= m_buff
->sub(m_it
== 0 ? m_buff
->m_last
: m_it
, n
);
347 //! Iterator subtraction.
348 iterator
operator - (difference_type n
) const { return iterator
<Buff
, Traits
>(*this) -= n
; }
350 //! Element access operator.
351 reference
operator [] (difference_type n
) const { return *(*this + n
); }
353 // Equality & comparison
356 template <class Traits0
>
357 bool operator == (const iterator
<Buff
, Traits0
>& it
) const {
358 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
359 BOOST_CB_ASSERT(it
.is_valid(m_buff
)); // check for uninitialized or invalidated iterator
360 return m_it
== it
.m_it
;
364 template <class Traits0
>
365 bool operator != (const iterator
<Buff
, Traits0
>& it
) const {
366 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
367 BOOST_CB_ASSERT(it
.is_valid(m_buff
)); // check for uninitialized or invalidated iterator
368 return m_it
!= it
.m_it
;
372 template <class Traits0
>
373 bool operator < (const iterator
<Buff
, Traits0
>& it
) const {
374 BOOST_CB_ASSERT(is_valid(m_buff
)); // check for uninitialized or invalidated iterator
375 BOOST_CB_ASSERT(it
.is_valid(m_buff
)); // check for uninitialized or invalidated iterator
376 return linearize_pointer(*this) < linearize_pointer(it
);
380 template <class Traits0
>
381 bool operator > (const iterator
<Buff
, Traits0
>& it
) const { return it
< *this; }
384 template <class Traits0
>
385 bool operator <= (const iterator
<Buff
, Traits0
>& it
) const { return !(it
< *this); }
387 //! Greater or equal.
388 template <class Traits0
>
389 bool operator >= (const iterator
<Buff
, Traits0
>& it
) const { return !(*this < it
); }
393 //! Get a pointer which would point to the same element as the iterator in case the circular buffer is linearized.
394 template <class Traits0
>
395 typename
Traits0::pointer
linearize_pointer(const iterator
<Buff
, Traits0
>& it
) const {
396 return it
.m_it
== 0 ? m_buff
->m_buff
+ m_buff
->size() :
397 (it
.m_it
< m_buff
->m_first
? it
.m_it
+ (m_buff
->m_end
- m_buff
->m_first
)
398 : m_buff
->m_buff
+ (it
.m_it
- m_buff
->m_first
));
402 //! Iterator addition.
403 template <class Buff
, class Traits
>
404 inline iterator
<Buff
, Traits
>
405 operator + (typename
Traits::difference_type n
, const iterator
<Buff
, Traits
>& it
) {
409 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
411 //! Iterator category.
412 template <class Buff
, class Traits
>
413 inline std::random_access_iterator_tag
iterator_category(const iterator
<Buff
, Traits
>&) {
414 return std::random_access_iterator_tag();
417 //! The type of the elements stored in the circular buffer.
418 template <class Buff
, class Traits
>
419 inline typename
Traits::value_type
* value_type(const iterator
<Buff
, Traits
>&) { return 0; }
422 template <class Buff
, class Traits
>
423 inline typename
Traits::difference_type
* distance_type(const iterator
<Buff
, Traits
>&) { return 0; }
425 #endif // #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
428 \fn ForwardIterator uninitialized_copy_with_alloc(InputIterator first, InputIterator last, ForwardIterator dest,
430 \brief Equivalent of <code>std::uninitialized_copy</code> with allocator.
432 template<class InputIterator
, class ForwardIterator
, class Alloc
>
433 inline ForwardIterator
uninitialized_copy_with_alloc(InputIterator first
, InputIterator last
, ForwardIterator dest
,
435 ForwardIterator next
= dest
;
437 for (; first
!= last
; ++first
, ++dest
)
438 alloc
.construct(dest
, *first
);
440 for (; next
!= dest
; ++next
)
449 \fn void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc)
450 \brief Equivalent of <code>std::uninitialized_fill_n</code> with allocator.
452 template<class ForwardIterator
, class Diff
, class T
, class Alloc
>
453 inline void uninitialized_fill_n_with_alloc(ForwardIterator first
, Diff n
, const T
& item
, Alloc
& alloc
) {
454 ForwardIterator next
= first
;
456 for (; n
> 0; ++first
, --n
)
457 alloc
.construct(first
, item
);
459 for (; next
!= first
; ++next
)
466 } // namespace cb_details
470 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)