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