1//
2// Boost.Pointer Container
3//
4// Copyright Thorsten Ottosen 2008. Use, modification and
5// distribution is subject to the Boost Software License, Version
6// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// For more information, see http://www.boost.org/libs/ptr_container/
10//
11
12#ifndef BOOST_PTR_CONTAINER_PTR_CIRCULAR_BUFFER_HPP
13#define BOOST_PTR_CONTAINER_PTR_CIRCULAR_BUFFER_HPP
14
15#if defined(_MSC_VER) && (_MSC_VER >= 1200)
16# pragma once
17#endif
18
19#include <boost/circular_buffer.hpp>
20#include <boost/ptr_container/ptr_sequence_adapter.hpp>
21
22namespace boost
23{
24
25 template
26 <
27 class T,
28 class CloneAllocator = heap_clone_allocator,
29 class Allocator = std::allocator<void*>
30 >
31 class ptr_circular_buffer : public
32 ptr_sequence_adapter< T,
33 boost::circular_buffer<void*,Allocator>,
34 CloneAllocator >
35 {
36 typedef ptr_sequence_adapter< T,
37 boost::circular_buffer<void*,Allocator>,
38 CloneAllocator >
39 base_type;
40
41 typedef boost::circular_buffer<void*,Allocator> circular_buffer_type;
42 typedef ptr_circular_buffer<T,CloneAllocator,Allocator> this_type;
43
44 public: // typedefs
45 typedef typename base_type::value_type value_type;
46 typedef value_type* pointer;
47 typedef const value_type* const_pointer;
48 typedef typename base_type::size_type size_type;
49 typedef typename base_type::allocator_type allocator_type;
50 typedef typename base_type::iterator iterator;
51 typedef typename base_type::const_iterator const_iterator;
52 typedef typename base_type::auto_type auto_type;
53
54 typedef std::pair<pointer,size_type> array_range;
55 typedef std::pair<const_pointer,size_type> const_array_range;
56 typedef typename circular_buffer_type::capacity_type capacity_type;
57
58 public: // constructors
59 ptr_circular_buffer()
60 { }
61
62 explicit ptr_circular_buffer( capacity_type n )
63 : base_type( n, ptr_container_detail::fixed_length_sequence_tag() )
64 { }
65
66 ptr_circular_buffer( capacity_type n,
67 const allocator_type& alloc )
68 : base_type( n, alloc, ptr_container_detail::fixed_length_sequence_tag() )
69 { }
70
71 template< class ForwardIterator >
72 ptr_circular_buffer( ForwardIterator first, ForwardIterator last )
73 : base_type( first, last, ptr_container_detail::fixed_length_sequence_tag() )
74 { }
75
76 template< class InputIterator >
77 ptr_circular_buffer( capacity_type n, InputIterator first, InputIterator last )
78 : base_type( n, first, last, ptr_container_detail::fixed_length_sequence_tag() )
79 { }
80
81 ptr_circular_buffer( const ptr_circular_buffer& r )
82 : base_type( r.size(), r.begin(), r.end(),
83 ptr_container_detail::fixed_length_sequence_tag() )
84 { }
85
86 template< class U >
87 ptr_circular_buffer( const ptr_circular_buffer<U>& r )
88 : base_type( r.size(), r.begin(), r.end(),
89 ptr_container_detail::fixed_length_sequence_tag() )
90 { }
91
92 ptr_circular_buffer& operator=( ptr_circular_buffer r )
93 {
94 this->swap( r );
95 return *this;
96 }
97
98 BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( ptr_circular_buffer,
99 base_type, this_type )
100
101 public: // allocators
102 allocator_type& get_allocator()
103 {
104 return this->base().get_allocator();
105 }
106
107 allocator_type get_allocator() const
108 {
109 return this->base().get_allocator();
110 }
111
112 public: // circular buffer functions
113 array_range array_one() // nothrow
114 {
115 typename circular_buffer_type::array_range r = this->base().array_one();
116 return array_range( reinterpret_cast<pointer>(r.first), r.second );
117 }
118
119 const_array_range array_one() const // nothrow
120 {
121 typename circular_buffer_type::const_array_range r = this->base().array_one();
122 return const_array_range( reinterpret_cast<const_pointer>(r.first), r.second );
123 }
124
125 array_range array_two() // nothrow
126 {
127 typename circular_buffer_type::array_range r = this->base().array_two();
128 return array_range( reinterpret_cast<pointer>(r.first), r.second );
129 }
130
131 const_array_range array_two() const // nothrow
132 {
133 typename circular_buffer_type::const_array_range r = this->base().array_two();
134 return const_array_range( reinterpret_cast<const_pointer>(r.first), r.second );
135 }
136
137 pointer linearize() // nothrow
138 {
139 return reinterpret_cast<pointer>(this->base().linearize());
140 }
141
142 bool full() const // nothrow
143 {
144 return this->base().full();
145 }
146
147 size_type reserve() const // nothrow
148 {
149 return this->base().reserve();
150 }
151
152 void reserve( size_type n ) // strong
153 {
154 if( capacity() < n )
155 set_capacity( n );
156 }
157
158 capacity_type capacity() const // nothrow
159 {
160 return this->base().capacity();
161 }
162
163 void set_capacity( capacity_type new_capacity ) // strong
164 {
165 if( this->size() > new_capacity )
166 {
167 this->erase( this->begin() + new_capacity, this->end() );
168 }
169 this->base().set_capacity( new_capacity );
170 }
171
172 void rset_capacity( capacity_type new_capacity ) // strong
173 {
174 if( this->size() > new_capacity )
175 {
176 this->erase( this->begin(),
177 this->begin() + (this->size()-new_capacity) );
178 }
179 this->base().rset_capacity( new_capacity );
180 }
181
182 void resize( size_type size ) // basic
183 {
184 size_type old_size = this->size();
185 if( old_size > size )
186 {
187 this->erase( boost::next( this->begin(), size ), this->end() );
188 }
189 else if( size > old_size )
190 {
191 for( ; old_size != size; ++old_size )
192 this->push_back( new BOOST_DEDUCED_TYPENAME
193 boost::remove_pointer<value_type>::type() );
194 }
195
196 BOOST_ASSERT( this->size() == size );
197 }
198
199 void resize( size_type size, value_type to_clone ) // basic
200 {
201 size_type old_size = this->size();
202 if( old_size > size )
203 {
204 this->erase( boost::next( this->begin(), size ), this->end() );
205 }
206 else if( size > old_size )
207 {
208 for( ; old_size != size; ++old_size )
209 this->push_back( this->null_policy_allocate_clone( to_clone ) );
210 }
211
212 BOOST_ASSERT( this->size() == size );
213 }
214
215 void rresize( size_type size ) // basic
216 {
217 size_type old_size = this->size();
218 if( old_size > size )
219 {
220 this->erase( this->begin(),
221 boost::next( this->begin(), old_size - size ) );
222 }
223 else if( size > old_size )
224 {
225 for( ; old_size != size; ++old_size )
226 this->push_front( new BOOST_DEDUCED_TYPENAME
227 boost::remove_pointer<value_type>::type() );
228 }
229
230 BOOST_ASSERT( this->size() == size );
231 }
232
233 void rresize( size_type size, value_type to_clone ) // basic
234 {
235 size_type old_size = this->size();
236 if( old_size > size )
237 {
238 this->erase( this->begin(),
239 boost::next( this->begin(), old_size - size ) );
240 }
241 else if( size > old_size )
242 {
243 for( ; old_size != size; ++old_size )
244 this->push_front( this->null_policy_allocate_clone( to_clone ) );
245 }
246
247 BOOST_ASSERT( this->size() == size );
248 }
249
250 template< class InputIterator >
251 void assign( InputIterator first, InputIterator last ) // strong
252 {
253 ptr_circular_buffer temp( first, last );
254 this->swap( temp );
255 }
256
257 template< class Range >
258 void assign( const Range& r ) // strong
259 {
260 assign( boost::begin(r), boost::end(r ) );
261 }
262
263 void assign( size_type n, value_type to_clone ) // strong
264 {
265 ptr_circular_buffer temp( n );
266 for( size_type i = 0u; i != n; ++i )
267 temp.push_back( this->null_policy_allocate_clone( to_clone ) );
268 this->swap( temp );
269 }
270
271 void assign( capacity_type capacity, size_type n,
272 value_type to_clone ) // basic
273 {
274 this->assign( (std::min)(n,capacity), to_clone );
275 }
276
277 template< class InputIterator >
278 void assign( capacity_type capacity,
279 InputIterator first, InputIterator last ) // basic
280 {
281 this->assign( first, last );
282 this->set_capacity( capacity );
283 }
284
285 void push_back( value_type ptr ) // nothrow
286 {
287 BOOST_ASSERT( capacity() > 0 );
288 this->enforce_null_policy( ptr, "Null pointer in 'push_back()'" );
289
290 auto_type old_ptr;
291 if( full() )
292 old_ptr.reset( &*this->begin() );
293 this->base().push_back( ptr );
294 }
295
296 template< class U >
297 void push_back( std::auto_ptr<U> ptr ) // nothrow
298 {
299 push_back( ptr.release() );
300 }
301
302 void push_front( value_type ptr ) // nothrow
303 {
304 BOOST_ASSERT( capacity() > 0 );
305 this->enforce_null_policy( ptr, "Null pointer in 'push_front()'" );
306
307 auto_type old_ptr;
308 if( full() )
309 old_ptr.reset( &*(--this->end()) );
310 this->base().push_front( ptr );
311 }
312
313 template< class U >
314 void push_front( std::auto_ptr<U> ptr ) // nothrow
315 {
316 push_front( ptr.release() );
317 }
318
319 iterator insert( iterator pos, value_type ptr ) // nothrow
320 {
321 BOOST_ASSERT( capacity() > 0 );
322 this->enforce_null_policy( ptr, "Null pointer in 'insert()'" );
323
324 auto_type new_ptr( ptr );
325 iterator b = this->begin();
326 if( full() && pos == b )
327 return b;
328
329 auto_type old_ptr;
330 if( full() )
331 old_ptr.reset( &*this->begin() );
332
333 new_ptr.release();
334 return this->base().insert( pos.base(), ptr );
335 }
336
337 template< class U >
338 iterator insert( iterator pos, std::auto_ptr<U> ptr ) // nothrow
339 {
340 return insert( pos, ptr.release() );
341 }
342
343 template< class InputIterator >
344 void insert( iterator pos, InputIterator first, InputIterator last ) // basic
345 {
346 for( ; first != last; ++first, ++pos )
347 pos = insert( pos, this->null_policy_allocate_clone( &*first ) );
348 }
349
350#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
351#else
352 template< class Range >
353 BOOST_DEDUCED_TYPENAME
354 boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
355 insert( iterator before, const Range& r )
356 {
357 insert( before, boost::begin(r), boost::end(r) );
358 }
359
360#endif
361
362 iterator rinsert( iterator pos, value_type ptr ) // nothrow
363 {
364 BOOST_ASSERT( capacity() > 0 );
365 this->enforce_null_policy( ptr, "Null pointer in 'rinsert()'" );
366
367 auto_type new_ptr( ptr );
368 iterator b = this->end();
369 if (full() && pos == b)
370 return b;
371
372 auto_type old_ptr;
373 if( full() )
374 old_ptr.reset( &this->back() );
375
376 new_ptr.release();
377 return this->base().rinsert( pos.base(), ptr );
378 }
379
380 template< class U >
381 iterator rinsert( iterator pos, std::auto_ptr<U> ptr ) // nothrow
382 {
383 return rinsert( pos, ptr.release() );
384 }
385
386
387 template< class InputIterator >
388 void rinsert( iterator pos, InputIterator first, InputIterator last ) // basic
389 {
390 for( ; first != last; ++first, ++pos )
391 pos = rinsert( pos, this->null_policy_allocate_clone( &*first ) );
392 }
393
394#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
395#else
396 template< class Range >
397 BOOST_DEDUCED_TYPENAME
398 boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
399 rinsert( iterator before, const Range& r )
400 {
401 rinsert( before, boost::begin(r), boost::end(r) );
402 }
403
404#endif
405
406 iterator rerase( iterator pos ) // nothrow
407 {
408 BOOST_ASSERT( !this->empty() );
409 BOOST_ASSERT( pos != this->end() );
410
411 this->remove( pos );
412 return iterator( this->base().rerase( pos.base() ) );
413 }
414
415 iterator rerase( iterator first, iterator last ) // nothrow
416 {
417 this->remove( first, last );
418 return iterator( this->base().rerase( first.base(),
419 last.base() ) );
420 }
421
422 template< class Range >
423 iterator rerase( const Range& r ) // nothrow
424 {
425 return rerase( boost::begin(r), boost::end(r) );
426 }
427
428 void rotate( const_iterator new_begin ) // nothrow
429 {
430 this->base().rotate( new_begin.base() );
431 }
432
433 public: // transfer
434 template< class PtrSeqAdapter >
435 void transfer( iterator before,
436 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first,
437 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last,
438 PtrSeqAdapter& from ) // nothrow
439 {
440 BOOST_ASSERT( (void*)&from != (void*)this );
441 if( from.empty() )
442 return;
443 for( BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator begin = first;
444 begin != last; ++begin, ++before )
445 before = insert( before, &*begin ); // nothrow
446 from.base().erase( first.base(), last.base() ); // nothrow
447 }
448
449 template< class PtrSeqAdapter >
450 void transfer( iterator before,
451 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object,
452 PtrSeqAdapter& from ) // nothrow
453 {
454 BOOST_ASSERT( (void*)&from != (void*)this );
455 if( from.empty() )
456 return;
457 insert( before, &*object ); // nothrow
458 from.base().erase( object.base() ); // nothrow
459 }
460
461#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
462#else
463
464 template< class PtrSeqAdapter, class Range >
465 BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
466 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type
467 transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // nothrow
468 {
469 transfer( before, boost::begin(r), boost::end(r), from );
470 }
471
472#endif
473 template< class PtrSeqAdapter >
474 void transfer( iterator before, PtrSeqAdapter& from ) // nothrow
475 {
476 transfer( before, from.begin(), from.end(), from );
477 }
478
479 public: // C-array support
480
481 void transfer( iterator before, value_type* from,
482 size_type size, bool delete_from = true ) // nothrow
483 {
484 BOOST_ASSERT( from != 0 );
485 if( delete_from )
486 {
487 BOOST_DEDUCED_TYPENAME base_type::scoped_deleter
488 deleter( from, size ); // nothrow
489 for( size_type i = 0u; i != size; ++i, ++before )
490 before = insert( before, *(from+i) ); // nothrow
491 deleter.release(); // nothrow
492 }
493 else
494 {
495 for( size_type i = 0u; i != size; ++i, ++before )
496 before = insert( before, *(from+i) ); // nothrow
497 }
498 }
499
500 value_type* c_array() // nothrow
501 {
502 if( this->empty() )
503 return 0;
504 this->linearize();
505 T** res = reinterpret_cast<T**>( &this->begin().base()[0] );
506 return res;
507 }
508
509 };
510
511 //////////////////////////////////////////////////////////////////////////////
512 // clonability
513
514 template< typename T, typename CA, typename A >
515 inline ptr_circular_buffer<T,CA,A>* new_clone( const ptr_circular_buffer<T,CA,A>& r )
516 {
517 return r.clone().release();
518 }
519
520 /////////////////////////////////////////////////////////////////////////
521 // swap
522
523 template< typename T, typename CA, typename A >
524 inline void swap( ptr_circular_buffer<T,CA,A>& l, ptr_circular_buffer<T,CA,A>& r )
525 {
526 l.swap(r);
527 }
528
529}
530
531#endif
532

source code of boost/boost/ptr_container/ptr_circular_buffer.hpp