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 |
67 | ptr_circular_buffer() |
68 | { } |
69 | |
70 | explicit ptr_circular_buffer( capacity_type n ) |
71 | : base_type( n, ptr_container_detail::fixed_length_sequence_tag() ) |
72 | { } |
73 | |
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 > |
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 > |
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 | |
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 > |
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 | |
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 |
110 | allocator_type& get_allocator() |
111 | { |
112 | return this->base().get_allocator(); |
113 | } |
114 | |
115 | allocator_type get_allocator() const |
116 | { |
117 | return this->base().get_allocator(); |
118 | } |
119 | |
120 | public: // circular buffer functions |
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 | |
127 | 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 | |
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 | |
139 | 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 | |
145 | pointer linearize() // nothrow |
146 | { |
147 | return reinterpret_cast<pointer>(this->base().linearize()); |
148 | } |
149 | |
150 | bool full() const // nothrow |
151 | { |
152 | return this->base().full(); |
153 | } |
154 | |
155 | size_type reserve() const // nothrow |
156 | { |
157 | return this->base().reserve(); |
158 | } |
159 | |
160 | void reserve( size_type n ) // strong |
161 | { |
162 | if( capacity() < n ) |
163 | set_capacity( n ); |
164 | } |
165 | |
166 | capacity_type capacity() const // nothrow |
167 | { |
168 | return this->base().capacity(); |
169 | } |
170 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 > |
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 > |
266 | void assign( const Range& r ) // strong |
267 | { |
268 | assign( boost::begin(r), boost::end(r ) ); |
269 | } |
270 | |
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 | |
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 > |
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 | |
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 > |
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 > |
313 | void push_back( std::unique_ptr<U> ptr ) // nothrow |
314 | { |
315 | push_back( ptr.release() ); |
316 | } |
317 | #endif |
318 | |
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 > |
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 > |
339 | void push_front( std::unique_ptr<U> ptr ) // nothrow |
340 | { |
341 | push_front( ptr.release() ); |
342 | } |
343 | #endif |
344 | |
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 > |
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 > |
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 > |
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 |
390 | insert( iterator before, const Range& r ) |
391 | { |
392 | insert( before, boost::begin(r), boost::end(r) ); |
393 | } |
394 | |
395 | #endif |
396 | |
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 > |
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 > |
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 > |
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 |
443 | rinsert( iterator before, const Range& r ) |
444 | { |
445 | rinsert( before, boost::begin(r), boost::end(r) ); |
446 | } |
447 | |
448 | #endif |
449 | |
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 | |
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 > |
467 | iterator rerase( const Range& r ) // nothrow |
468 | { |
469 | return rerase( boost::begin(r), boost::end(r) ); |
470 | } |
471 | |
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 > |
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 > |
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 |
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 > |
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 | |
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 | |
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 > |
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 > |
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 | |