ptr_circular_buffer.hpp 18 KB

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