00001
00002
00003
00004
00005
00006
00007
00008
00009 #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
00010 #define BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP
00011
00012 #if defined(_MSC_VER) && _MSC_VER >= 1200
00013 #pragma once
00014 #endif
00015
00016 namespace boost {
00017
00031 template<class T, class Alloc>
00032 class circular_buffer_space_optimized : private circular_buffer<T, Alloc> {
00033 public:
00034
00035
00036 typedef typename circular_buffer<T, Alloc>::value_type value_type;
00037 typedef typename circular_buffer<T, Alloc>::pointer pointer;
00038 typedef typename circular_buffer<T, Alloc>::const_pointer const_pointer;
00039 typedef typename circular_buffer<T, Alloc>::reference reference;
00040 typedef typename circular_buffer<T, Alloc>::const_reference const_reference;
00041 typedef typename circular_buffer<T, Alloc>::size_type size_type;
00042 typedef typename circular_buffer<T, Alloc>::difference_type difference_type;
00043 typedef typename circular_buffer<T, Alloc>::allocator_type allocator_type;
00044 typedef typename circular_buffer<T, Alloc>::param_value_type param_value_type;
00045 typedef typename circular_buffer<T, Alloc>::const_iterator const_iterator;
00046 typedef typename circular_buffer<T, Alloc>::iterator iterator;
00047 typedef typename circular_buffer<T, Alloc>::const_reverse_iterator const_reverse_iterator;
00048 typedef typename circular_buffer<T, Alloc>::reverse_iterator reverse_iterator;
00049
00050
00051
00052 using circular_buffer<T, Alloc>::get_allocator;
00053 using circular_buffer<T, Alloc>::begin;
00054 using circular_buffer<T, Alloc>::end;
00055 using circular_buffer<T, Alloc>::rbegin;
00056 using circular_buffer<T, Alloc>::rend;
00057 using circular_buffer<T, Alloc>::at;
00058 using circular_buffer<T, Alloc>::front;
00059 using circular_buffer<T, Alloc>::back;
00060 using circular_buffer<T, Alloc>::data;
00061 using circular_buffer<T, Alloc>::size;
00062 using circular_buffer<T, Alloc>::max_size;
00063 using circular_buffer<T, Alloc>::empty;
00064
00065 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00066 reference operator [] (size_type n) { return circular_buffer<T, Alloc>::operator[](n); }
00067 return_value_type operator [] (size_type n) const { return circular_buffer<T, Alloc>::operator[](n); }
00068 #else
00069 using circular_buffer<T, Alloc>::operator[];
00070 #endif
00071
00072 private:
00073
00074
00076 size_type m_capacity;
00077
00079 size_type m_min_capacity;
00080
00081 public:
00082
00083
00085 bool full() const { return size() == capacity(); }
00086
00088
00091 size_type min_capacity() const { return m_min_capacity; }
00092
00094
00102 void set_min_capacity(size_type new_min_capacity) {
00103 BOOST_CB_ASSERT(capacity() >= new_min_capacity);
00104 m_min_capacity = new_min_capacity;
00105 if (new_min_capacity > circular_buffer<T, Alloc>::capacity())
00106 circular_buffer<T, Alloc>::set_capacity(new_min_capacity);
00107 else
00108 check_high_capacity();
00109 }
00110
00112 size_type capacity() const { return m_capacity; }
00113
00114 #if defined(BOOST_CB_TEST)
00115
00117
00121 size_type internal_capacity() const { return circular_buffer<T, Alloc>::capacity(); }
00122
00123 #endif // #if defined(BOOST_CB_TEST)
00124
00126
00132 void set_capacity(size_type new_capacity, bool remove_front = true) {
00133 BOOST_CB_ASSERT(new_capacity >= min_capacity());
00134 if (new_capacity < circular_buffer<T, Alloc>::capacity())
00135 circular_buffer<T, Alloc>::set_capacity(new_capacity, remove_front);
00136 m_capacity = new_capacity;
00137 }
00138
00140 void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) {
00141 if (new_size > size()) {
00142 if (new_size > capacity())
00143 m_capacity = new_size;
00144 insert(end(), new_size - size(), item);
00145 } else {
00146 if (remove_front)
00147 erase(begin(), end() - new_size);
00148 else
00149 erase(begin() + new_size, end());
00150 }
00151 }
00152
00154
00167 explicit circular_buffer_space_optimized(
00168 size_type capacity,
00169 size_type min_capacity = 0,
00170 const allocator_type& alloc = allocator_type())
00171 : circular_buffer<T, Alloc>(min_capacity, alloc)
00172 , m_capacity(capacity)
00173 , m_min_capacity(min_capacity) {
00174 BOOST_CB_ASSERT(capacity >= min_capacity);
00175 }
00176
00178
00192 circular_buffer_space_optimized(
00193 size_type capacity,
00194 size_type min_capacity,
00195 param_value_type item,
00196 const allocator_type& alloc = allocator_type())
00197 : circular_buffer<T, Alloc>(capacity, item, alloc)
00198 , m_capacity(capacity)
00199 , m_min_capacity(min_capacity) {
00200 BOOST_CB_ASSERT(capacity >= min_capacity);
00201 }
00202
00203
00204
00206
00227 template <class InputIterator>
00228 circular_buffer_space_optimized(
00229 size_type capacity,
00230 size_type min_capacity,
00231 InputIterator first,
00232 InputIterator last,
00233 const allocator_type& alloc = allocator_type())
00234 : circular_buffer<T, Alloc>(
00235 init_capacity(capacity, min_capacity, first, last), first, last, alloc)
00236 , m_capacity(capacity)
00237 , m_min_capacity(min_capacity) {
00238 BOOST_CB_ASSERT(capacity >= min_capacity);
00239 BOOST_CB_ASSERT(std::distance(first, last) >= 0);
00240 }
00241
00242
00243
00244
00245
00247 void assign(size_type n, param_value_type item) {
00248 if (n > m_capacity)
00249 m_capacity = n;
00250 circular_buffer<T, Alloc>::assign(n, item);
00251 }
00252
00254 template <class InputIterator>
00255 void assign(InputIterator first, InputIterator last) {
00256 circular_buffer<T, Alloc>::assign(first, last);
00257 size_type capacity = circular_buffer<T, Alloc>::capacity();
00258 if (capacity > m_capacity)
00259 m_capacity = capacity;
00260 }
00261
00263 void swap(circular_buffer_space_optimized& cb) {
00264 std::swap(m_capacity, cb.m_capacity);
00265 std::swap(m_min_capacity, cb.m_min_capacity);
00266 circular_buffer<T, Alloc>::swap(cb);
00267 }
00268
00270
00275 void push_back(param_value_type item) {
00276 check_low_capacity();
00277 circular_buffer<T, Alloc>::push_back(item);
00278 }
00279
00281
00286 void push_back() { push_back(value_type()); }
00287
00289
00294 void push_front(param_value_type item) {
00295 check_low_capacity();
00296 circular_buffer<T, Alloc>::push_front(item);
00297 }
00298
00300
00305 void push_front() { push_front(value_type()); }
00306
00308
00313 void pop_back() {
00314 circular_buffer<T, Alloc>::pop_back();
00315 check_high_capacity();
00316 }
00317
00319
00324 void pop_front() {
00325 circular_buffer<T, Alloc>::pop_front();
00326 check_high_capacity();
00327 }
00328
00330
00335 iterator insert(iterator pos, param_value_type item) {
00336 size_type index = pos - begin();
00337 check_low_capacity();
00338 return circular_buffer<T, Alloc>::insert(begin() + index, item);
00339 }
00340
00342
00347 iterator insert(iterator pos) { return insert(pos, value_type()); }
00348
00350
00355 void insert(iterator pos, size_type n, param_value_type item) {
00356 size_type index = pos - begin();
00357 check_low_capacity(n);
00358 circular_buffer<T, Alloc>::insert(begin() + index, n, item);
00359 }
00360
00362
00367 template <class InputIterator>
00368 void insert(iterator pos, InputIterator first, InputIterator last) {
00369 insert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
00370 }
00371
00373
00378 iterator rinsert(iterator pos, param_value_type item) {
00379 size_type index = pos - begin();
00380 check_low_capacity();
00381 return circular_buffer<T, Alloc>::rinsert(begin() + index, item);
00382 }
00383
00385
00390 iterator rinsert(iterator pos) { return rinsert(pos, value_type()); }
00391
00393
00398 void rinsert(iterator pos, size_type n, param_value_type item) {
00399 size_type index = pos - begin();
00400 check_low_capacity(n);
00401 circular_buffer<T, Alloc>::rinsert(begin() + index, n, item);
00402 }
00403
00405
00410 template <class InputIterator>
00411 void rinsert(iterator pos, InputIterator first, InputIterator last) {
00412 rinsert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
00413 }
00414
00416
00421 iterator erase(iterator pos) {
00422 iterator it = circular_buffer<T, Alloc>::erase(pos);
00423 size_type index = it - begin();
00424 check_high_capacity();
00425 return begin() + index;
00426 }
00427
00429
00434 iterator erase(iterator first, iterator last) {
00435 iterator it = circular_buffer<T, Alloc>::erase(first, last);
00436 size_type index = it - begin();
00437 check_high_capacity();
00438 return begin() + index;
00439 }
00440
00442 void clear() { erase(begin(), end()); }
00443
00444 private:
00445
00446
00448 size_type ensure_reserve(size_type new_capacity, size_type size) const {
00449 if (size + new_capacity / 5 >= new_capacity)
00450 new_capacity *= 2;
00451 if (new_capacity > capacity())
00452 return capacity();
00453 return new_capacity;
00454 }
00455
00457
00458
00459
00460 void check_low_capacity(size_type n = 1) {
00461 size_type new_size = size() + n;
00462 size_type new_capacity = circular_buffer<T, Alloc>::capacity();
00463 if (new_size > new_capacity) {
00464 if (new_capacity == 0)
00465 new_capacity = 1;
00466 for (; new_size > new_capacity; new_capacity *= 2);
00467 circular_buffer<T, Alloc>::set_capacity(
00468 ensure_reserve(new_capacity, new_size));
00469 }
00470 }
00471
00473
00474
00475
00476 void check_high_capacity() {
00477 size_type new_capacity = circular_buffer<T, Alloc>::capacity();
00478 while (new_capacity / 3 >= size()) {
00479 new_capacity /= 2;
00480 if (new_capacity <= min_capacity()) {
00481 new_capacity = min_capacity();
00482 break;
00483 }
00484 }
00485 circular_buffer<T, Alloc>::set_capacity(
00486 ensure_reserve(new_capacity, size()));
00487 }
00488
00490 template <class InputIterator>
00491 static size_type init_capacity(size_type capacity, size_type min_capacity, InputIterator first, InputIterator last) {
00492 BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
00493 return std::min(capacity, std::max(min_capacity,
00494 static_cast<size_type>(std::distance(first, last))));
00495 }
00496
00498 template <class InputIterator>
00499 void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
00500 insert(pos, (size_type)n, item);
00501 }
00502
00504 template <class InputIterator>
00505 void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
00506 size_type index = pos - begin();
00507 check_low_capacity(std::distance(first, last));
00508 circular_buffer<T, Alloc>::insert(begin() + index, first, last);
00509 }
00510
00512 template <class InputIterator>
00513 void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
00514 rinsert(pos, (size_type)n, item);
00515 }
00516
00518 template <class InputIterator>
00519 void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
00520 size_type index = pos - begin();
00521 check_low_capacity(std::distance(first, last));
00522 circular_buffer<T, Alloc>::rinsert(begin() + index, first, last);
00523 }
00524 };
00525
00526
00527
00529 template <class T, class Alloc>
00530 inline bool operator == (const circular_buffer_space_optimized<T, Alloc>& lhs,
00531 const circular_buffer_space_optimized<T, Alloc>& rhs) {
00532 return lhs.size() == rhs.size() &&
00533 std::equal(lhs.begin(), lhs.end(), rhs.begin());
00534 }
00535
00537 template <class T, class Alloc>
00538 inline bool operator < (const circular_buffer_space_optimized<T, Alloc>& lhs,
00539 const circular_buffer_space_optimized<T, Alloc>& rhs) {
00540 return std::lexicographical_compare(
00541 lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
00542 }
00543
00544 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
00545
00547 template <class T, class Alloc>
00548 inline bool operator != (const circular_buffer_space_optimized<T, Alloc>& lhs,
00549 const circular_buffer_space_optimized<T, Alloc>& rhs) {
00550 return !(lhs == rhs);
00551 }
00552
00554 template <class T, class Alloc>
00555 inline bool operator > (const circular_buffer_space_optimized<T, Alloc>& lhs,
00556 const circular_buffer_space_optimized<T, Alloc>& rhs) {
00557 return rhs < lhs;
00558 }
00559
00561 template <class T, class Alloc>
00562 inline bool operator <= (const circular_buffer_space_optimized<T, Alloc>& lhs,
00563 const circular_buffer_space_optimized<T, Alloc>& rhs) {
00564 return !(rhs < lhs);
00565 }
00566
00568 template <class T, class Alloc>
00569 inline bool operator >= (const circular_buffer_space_optimized<T, Alloc>& lhs,
00570 const circular_buffer_space_optimized<T, Alloc>& rhs) {
00571 return !(lhs < rhs);
00572 }
00573
00575 template <class T, class Alloc>
00576 inline void swap(circular_buffer_space_optimized<T, Alloc>& lhs,
00577 circular_buffer_space_optimized<T, Alloc>& rhs) {
00578 lhs.swap(rhs);
00579 }
00580
00581 #endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
00582
00583 }
00584
00585 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)