comparison DEPENDENCIES/generic/include/boost/circular_buffer/details.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 // Helper classes and functions for the circular buffer.
2
3 // Copyright (c) 2003-2008 Jan Gaspar
4
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)
8
9 #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)
10 #define BOOST_CIRCULAR_BUFFER_DETAILS_HPP
11
12 #if defined(_MSC_VER) && _MSC_VER >= 1200
13 #pragma once
14 #endif
15
16 #include <boost/iterator.hpp>
17 #include <boost/throw_exception.hpp>
18 #include <boost/move/move.hpp>
19 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
20 #include <boost/detail/no_exceptions_support.hpp>
21 #include <iterator>
22
23 // Silence MS /W4 warnings like C4913:
24 // "user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used"
25 // This might happen when previously including some boost headers that overload the coma operator.
26 #if defined(_MSC_VER)
27 # pragma warning(push)
28 # pragma warning(disable:4913)
29 #endif
30
31 namespace boost {
32
33 namespace cb_details {
34
35 template <class Traits> struct nonconst_traits;
36
37 template<class ForwardIterator, class Diff, class T, class Alloc>
38 void uninitialized_fill_n_with_alloc(
39 ForwardIterator first, Diff n, const T& item, Alloc& alloc);
40
41 template<class ValueType, class InputIterator, class ForwardIterator>
42 ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest);
43
44 template<class ValueType, class InputIterator, class ForwardIterator>
45 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest);
46
47 /*!
48 \struct const_traits
49 \brief Defines the data types for a const iterator.
50 */
51 template <class Traits>
52 struct const_traits {
53 // Basic types
54 typedef typename Traits::value_type value_type;
55 typedef typename Traits::const_pointer pointer;
56 typedef typename Traits::const_reference reference;
57 typedef typename Traits::size_type size_type;
58 typedef typename Traits::difference_type difference_type;
59
60 // Non-const traits
61 typedef nonconst_traits<Traits> nonconst_self;
62 };
63
64 /*!
65 \struct nonconst_traits
66 \brief Defines the data types for a non-const iterator.
67 */
68 template <class Traits>
69 struct nonconst_traits {
70 // Basic types
71 typedef typename Traits::value_type value_type;
72 typedef typename Traits::pointer pointer;
73 typedef typename Traits::reference reference;
74 typedef typename Traits::size_type size_type;
75 typedef typename Traits::difference_type difference_type;
76
77 // Non-const traits
78 typedef nonconst_traits<Traits> nonconst_self;
79 };
80
81 /*!
82 \struct iterator_wrapper
83 \brief Helper iterator dereference wrapper.
84 */
85 template <class Iterator>
86 struct iterator_wrapper {
87 mutable Iterator m_it;
88 explicit iterator_wrapper(Iterator it) : m_it(it) {}
89 Iterator operator () () const { return m_it++; }
90 private:
91 iterator_wrapper<Iterator>& operator = (const iterator_wrapper<Iterator>&); // do not generate
92 };
93
94 /*!
95 \struct item_wrapper
96 \brief Helper item dereference wrapper.
97 */
98 template <class Pointer, class Value>
99 struct item_wrapper {
100 Value m_item;
101 explicit item_wrapper(Value item) : m_item(item) {}
102 Pointer operator () () const { return &m_item; }
103 private:
104 item_wrapper<Pointer, Value>& operator = (const item_wrapper<Pointer, Value>&); // do not generate
105 };
106
107 /*!
108 \struct assign_n
109 \brief Helper functor for assigning n items.
110 */
111 template <class Value, class Alloc>
112 struct assign_n {
113 typedef typename Alloc::size_type size_type;
114 size_type m_n;
115 Value m_item;
116 Alloc& m_alloc;
117 assign_n(size_type n, Value item, Alloc& alloc) : m_n(n), m_item(item), m_alloc(alloc) {}
118 template <class Pointer>
119 void operator () (Pointer p) const {
120 uninitialized_fill_n_with_alloc(p, m_n, m_item, m_alloc);
121 }
122 private:
123 assign_n<Value, Alloc>& operator = (const assign_n<Value, Alloc>&); // do not generate
124 };
125
126 /*!
127 \struct assign_range
128 \brief Helper functor for assigning range of items.
129 */
130 template <class ValueType, class Iterator>
131 struct assign_range {
132 Iterator m_first;
133 Iterator m_last;
134
135 assign_range(const Iterator& first, const Iterator& last) BOOST_NOEXCEPT
136 : m_first(first), m_last(last) {}
137
138 template <class Pointer>
139 void operator () (Pointer p) const {
140 boost::cb_details::uninitialized_copy<ValueType>(m_first, m_last, p);
141 }
142 };
143
144 template <class ValueType, class Iterator>
145 inline assign_range<ValueType, Iterator> make_assign_range(const Iterator& first, const Iterator& last) {
146 return assign_range<ValueType, Iterator>(first, last);
147 }
148
149 /*!
150 \class capacity_control
151 \brief Capacity controller of the space optimized circular buffer.
152 */
153 template <class Size>
154 class capacity_control {
155
156 //! The capacity of the space-optimized circular buffer.
157 Size m_capacity;
158
159 //! The lowest guaranteed or minimum capacity of the adapted space-optimized circular buffer.
160 Size m_min_capacity;
161
162 public:
163
164 //! Constructor.
165 capacity_control(Size buffer_capacity, Size min_buffer_capacity = 0)
166 : m_capacity(buffer_capacity), m_min_capacity(min_buffer_capacity)
167 { // Check for capacity lower than min_capacity.
168 BOOST_CB_ASSERT(buffer_capacity >= min_buffer_capacity);
169 }
170
171 // Default copy constructor.
172
173 // Default assign operator.
174
175 //! Get the capacity of the space optimized circular buffer.
176 Size capacity() const { return m_capacity; }
177
178 //! Get the minimal capacity of the space optimized circular buffer.
179 Size min_capacity() const { return m_min_capacity; }
180
181 //! Size operator - returns the capacity of the space optimized circular buffer.
182 operator Size() const { return m_capacity; }
183 };
184
185 /*!
186 \struct iterator
187 \brief Random access iterator for the circular buffer.
188 \param Buff The type of the underlying circular buffer.
189 \param Traits Basic iterator types.
190 \note This iterator is not circular. It was designed
191 for iterating from begin() to end() of the circular buffer.
192 */
193 template <class Buff, class Traits>
194 struct iterator :
195 public boost::iterator<
196 std::random_access_iterator_tag,
197 typename Traits::value_type,
198 typename Traits::difference_type,
199 typename Traits::pointer,
200 typename Traits::reference>
201 #if BOOST_CB_ENABLE_DEBUG
202 , public debug_iterator_base
203 #endif // #if BOOST_CB_ENABLE_DEBUG
204 {
205 // Helper types
206
207 //! Base iterator.
208 typedef boost::iterator<
209 std::random_access_iterator_tag,
210 typename Traits::value_type,
211 typename Traits::difference_type,
212 typename Traits::pointer,
213 typename Traits::reference> base_iterator;
214
215 //! Non-const iterator.
216 typedef iterator<Buff, typename Traits::nonconst_self> nonconst_self;
217
218 // Basic types
219
220 //! The type of the elements stored in the circular buffer.
221 typedef typename base_iterator::value_type value_type;
222
223 //! Pointer to the element.
224 typedef typename base_iterator::pointer pointer;
225
226 //! Reference to the element.
227 typedef typename base_iterator::reference reference;
228
229 //! Size type.
230 typedef typename Traits::size_type size_type;
231
232 //! Difference type.
233 typedef typename base_iterator::difference_type difference_type;
234
235 // Member variables
236
237 //! The circular buffer where the iterator points to.
238 const Buff* m_buff;
239
240 //! An internal iterator.
241 pointer m_it;
242
243 // Construction & assignment
244
245 // Default copy constructor.
246
247 //! Default constructor.
248 iterator() : m_buff(0), m_it(0) {}
249
250 #if BOOST_CB_ENABLE_DEBUG
251
252 //! Copy constructor (used for converting from a non-const to a const iterator).
253 iterator(const nonconst_self& it) : debug_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {}
254
255 //! Internal constructor.
256 /*!
257 \note This constructor is not intended to be used directly by the user.
258 */
259 iterator(const Buff* cb, const pointer p) : debug_iterator_base(cb), m_buff(cb), m_it(p) {}
260
261 #else
262
263 iterator(const nonconst_self& it) : m_buff(it.m_buff), m_it(it.m_it) {}
264
265 iterator(const Buff* cb, const pointer p) : m_buff(cb), m_it(p) {}
266
267 #endif // #if BOOST_CB_ENABLE_DEBUG
268
269 //! Assign operator.
270 iterator& operator = (const iterator& it) {
271 if (this == &it)
272 return *this;
273 #if BOOST_CB_ENABLE_DEBUG
274 debug_iterator_base::operator =(it);
275 #endif // #if BOOST_CB_ENABLE_DEBUG
276 m_buff = it.m_buff;
277 m_it = it.m_it;
278 return *this;
279 }
280
281 // Random access iterator methods
282
283 //! Dereferencing operator.
284 reference operator * () const {
285 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
286 BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end()
287 return *m_it;
288 }
289
290 //! Dereferencing operator.
291 pointer operator -> () const { return &(operator*()); }
292
293 //! Difference operator.
294 template <class Traits0>
295 difference_type operator - (const iterator<Buff, Traits0>& it) const {
296 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
297 BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
298 return linearize_pointer(*this) - linearize_pointer(it);
299 }
300
301 //! Increment 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 != 0); // check for iterator pointing to end()
305 m_buff->increment(m_it);
306 if (m_it == m_buff->m_last)
307 m_it = 0;
308 return *this;
309 }
310
311 //! Increment operator (postfix).
312 iterator operator ++ (int) {
313 iterator<Buff, Traits> tmp = *this;
314 ++*this;
315 return tmp;
316 }
317
318 //! Decrement operator (prefix).
319 iterator& operator -- () {
320 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
321 BOOST_CB_ASSERT(m_it != m_buff->m_first); // check for iterator pointing to begin()
322 if (m_it == 0)
323 m_it = m_buff->m_last;
324 m_buff->decrement(m_it);
325 return *this;
326 }
327
328 //! Decrement operator (postfix).
329 iterator operator -- (int) {
330 iterator<Buff, Traits> tmp = *this;
331 --*this;
332 return tmp;
333 }
334
335 //! Iterator addition.
336 iterator& operator += (difference_type n) {
337 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
338 if (n > 0) {
339 BOOST_CB_ASSERT(m_buff->end() - *this >= n); // check for too large n
340 m_it = m_buff->add(m_it, n);
341 if (m_it == m_buff->m_last)
342 m_it = 0;
343 } else if (n < 0) {
344 *this -= -n;
345 }
346 return *this;
347 }
348
349 //! Iterator addition.
350 iterator operator + (difference_type n) const { return iterator<Buff, Traits>(*this) += n; }
351
352 //! Iterator subtraction.
353 iterator& operator -= (difference_type n) {
354 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
355 if (n > 0) {
356 BOOST_CB_ASSERT(*this - m_buff->begin() >= n); // check for too large n
357 m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n);
358 } else if (n < 0) {
359 *this += -n;
360 }
361 return *this;
362 }
363
364 //! Iterator subtraction.
365 iterator operator - (difference_type n) const { return iterator<Buff, Traits>(*this) -= n; }
366
367 //! Element access operator.
368 reference operator [] (difference_type n) const { return *(*this + n); }
369
370 // Equality & comparison
371
372 //! Equality.
373 template <class Traits0>
374 bool operator == (const iterator<Buff, Traits0>& it) const {
375 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
376 BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
377 return m_it == it.m_it;
378 }
379
380 //! Inequality.
381 template <class Traits0>
382 bool operator != (const iterator<Buff, Traits0>& it) const {
383 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
384 BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
385 return m_it != it.m_it;
386 }
387
388 //! Less.
389 template <class Traits0>
390 bool operator < (const iterator<Buff, Traits0>& it) const {
391 BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator
392 BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator
393 return linearize_pointer(*this) < linearize_pointer(it);
394 }
395
396 //! Greater.
397 template <class Traits0>
398 bool operator > (const iterator<Buff, Traits0>& it) const { return it < *this; }
399
400 //! Less or equal.
401 template <class Traits0>
402 bool operator <= (const iterator<Buff, Traits0>& it) const { return !(it < *this); }
403
404 //! Greater or equal.
405 template <class Traits0>
406 bool operator >= (const iterator<Buff, Traits0>& it) const { return !(*this < it); }
407
408 // Helpers
409
410 //! Get a pointer which would point to the same element as the iterator in case the circular buffer is linearized.
411 template <class Traits0>
412 typename Traits0::pointer linearize_pointer(const iterator<Buff, Traits0>& it) const {
413 return it.m_it == 0 ? m_buff->m_buff + m_buff->size() :
414 (it.m_it < m_buff->m_first ? it.m_it + (m_buff->m_end - m_buff->m_first)
415 : m_buff->m_buff + (it.m_it - m_buff->m_first));
416 }
417 };
418
419 //! Iterator addition.
420 template <class Buff, class Traits>
421 inline iterator<Buff, Traits>
422 operator + (typename Traits::difference_type n, const iterator<Buff, Traits>& it) {
423 return it + n;
424 }
425
426 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
427
428 //! Iterator category.
429 template <class Buff, class Traits>
430 inline std::random_access_iterator_tag iterator_category(const iterator<Buff, Traits>&) {
431 return std::random_access_iterator_tag();
432 }
433
434 //! The type of the elements stored in the circular buffer.
435 template <class Buff, class Traits>
436 inline typename Traits::value_type* value_type(const iterator<Buff, Traits>&) { return 0; }
437
438 //! Distance type.
439 template <class Buff, class Traits>
440 inline typename Traits::difference_type* distance_type(const iterator<Buff, Traits>&) { return 0; }
441
442 #endif // #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
443
444 /*!
445 \fn ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest)
446 \brief Equivalent of <code>std::uninitialized_copy</code> but with explicit specification of value type.
447 */
448 template<class ValueType, class InputIterator, class ForwardIterator>
449 inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest) {
450 typedef ValueType value_type;
451
452 // We do not use allocator.construct and allocator.destroy
453 // because C++03 requires to take parameter by const reference but
454 // Boost.move requires nonconst reference
455 ForwardIterator next = dest;
456 BOOST_TRY {
457 for (; first != last; ++first, ++dest)
458 ::new (dest) value_type(*first);
459 } BOOST_CATCH(...) {
460 for (; next != dest; ++next)
461 next->~value_type();
462 BOOST_RETHROW
463 }
464 BOOST_CATCH_END
465 return dest;
466 }
467
468 template<class ValueType, class InputIterator, class ForwardIterator>
469 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest,
470 true_type) {
471 for (; first != last; ++first, ++dest)
472 ::new (dest) ValueType(boost::move(*first));
473 return dest;
474 }
475
476 template<class ValueType, class InputIterator, class ForwardIterator>
477 ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest,
478 false_type) {
479 return uninitialized_copy<ValueType>(first, last, dest);
480 }
481
482 /*!
483 \fn ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest)
484 \brief Equivalent of <code>std::uninitialized_copy</code> but with explicit specification of value type and moves elements if they have noexcept move constructors.
485 */
486 template<class ValueType, class InputIterator, class ForwardIterator>
487 ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest) {
488 typedef typename boost::is_nothrow_move_constructible<ValueType>::type tag_t;
489 return uninitialized_move_if_noexcept_impl<ValueType>(first, last, dest, tag_t());
490 }
491
492 /*!
493 \fn void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc)
494 \brief Equivalent of <code>std::uninitialized_fill_n</code> with allocator.
495 */
496 template<class ForwardIterator, class Diff, class T, class Alloc>
497 inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) {
498 ForwardIterator next = first;
499 BOOST_TRY {
500 for (; n > 0; ++first, --n)
501 alloc.construct(first, item);
502 } BOOST_CATCH(...) {
503 for (; next != first; ++next)
504 alloc.destroy(next);
505 BOOST_RETHROW
506 }
507 BOOST_CATCH_END
508 }
509
510 } // namespace cb_details
511
512 } // namespace boost
513
514 #if defined(_MSC_VER)
515 # pragma warning(pop)
516 #endif
517
518 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP)