ptr_circular_buffer.hpp 19 KB

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