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