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 | |
22 | namespace 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 | |