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