]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |