00001
00002
00003
00004
00005
00006
00007
00008
00009 #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)
00010 #define BOOST_CIRCULAR_BUFFER_BASE_HPP
00011
00012 #if defined(_MSC_VER) && _MSC_VER >= 1200
00013 #pragma once
00014 #endif
00015
00016 #include <boost/call_traits.hpp>
00017 #include <boost/concept_check.hpp>
00018 #include <boost/throw_exception.hpp>
00019 #include <boost/iterator/reverse_iterator.hpp>
00020 #include <algorithm>
00021 #if !defined(BOOST_NO_EXCEPTIONS)
00022 #include <stdexcept>
00023 #endif
00024 #if BOOST_CB_ENABLE_DEBUG
00025 #include <string.h>
00026 #endif
00027
00028 namespace boost {
00029
00042 template <class T, class Alloc>
00043 class circular_buffer : cb_details::cb_iterator_registry {
00044
00045
00046 BOOST_CLASS_REQUIRE(T, boost, CopyConstructibleConcept);
00047
00048 public:
00049
00050
00052 typedef typename Alloc::value_type value_type;
00053
00055 typedef typename Alloc::pointer pointer;
00056
00058 typedef typename Alloc::const_pointer const_pointer;
00059
00061 typedef typename Alloc::reference reference;
00062
00064 typedef typename Alloc::const_reference const_reference;
00065
00067
00070 typedef typename Alloc::difference_type difference_type;
00071
00073
00076 typedef typename Alloc::size_type size_type;
00077
00079 typedef Alloc allocator_type;
00080
00082 allocator_type get_allocator() const { return m_alloc; }
00083
00085
00089 allocator_type& get_allocator() { return m_alloc; }
00090
00091
00092
00093
00094 typedef typename call_traits<value_type>::param_type param_value_type;
00095
00096
00097 typedef typename call_traits<value_type>::param_type return_value_type;
00098
00099
00100
00102 typedef cb_details::cb_iterator< circular_buffer<T, Alloc>, cb_details::cb_const_traits<Alloc> > const_iterator;
00103
00105 typedef cb_details::cb_iterator< circular_buffer<T, Alloc>, cb_details::cb_nonconst_traits<Alloc> > iterator;
00106
00108 typedef reverse_iterator<const_iterator> const_reverse_iterator;
00109
00111 typedef reverse_iterator<iterator> reverse_iterator;
00112
00113 private:
00114
00115
00117 pointer m_buff;
00118
00120 pointer m_end;
00121
00123 pointer m_first;
00124
00126 pointer m_last;
00127
00129 size_type m_size;
00130
00132 allocator_type m_alloc;
00133
00134
00135 #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
00136 friend iterator;
00137 friend const_iterator;
00138 #else
00139 friend struct iterator;
00140 friend struct const_iterator;
00141 #endif
00142
00143 public:
00144
00145
00147 iterator begin() { return iterator(this, empty() ? 0 : m_first); }
00148
00150 iterator end() { return iterator(this, 0); }
00151
00153 const_iterator begin() const { return const_iterator(this, empty() ? 0 : m_first); }
00154
00156 const_iterator end() const { return const_iterator(this, 0); }
00157
00159 reverse_iterator rbegin() { return reverse_iterator(end()); }
00160
00162 reverse_iterator rend() { return reverse_iterator(begin()); }
00163
00165 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
00166
00168 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
00169
00171
00174 reference operator [] (size_type index) {
00175 BOOST_CB_ASSERT(index < size());
00176 return *add(m_first, index);
00177 }
00178
00180
00183 return_value_type operator [] (size_type index) const {
00184 BOOST_CB_ASSERT(index < size());
00185 return *add(m_first, index);
00186 }
00187
00189
00192 reference at(size_type index) {
00193 check_position(index);
00194 return (*this)[index];
00195 }
00196
00198
00201 return_value_type at(size_type index) const {
00202 check_position(index);
00203 return (*this)[index];
00204 }
00205
00207
00210 reference front() {
00211 BOOST_CB_ASSERT(!empty());
00212 return *m_first;
00213 }
00214
00216
00219 reference back() {
00220 BOOST_CB_ASSERT(!empty());
00221 return *((m_last == m_buff ? m_end : m_last) - 1);
00222 }
00223
00225
00228 return_value_type front() const {
00229 BOOST_CB_ASSERT(!empty());
00230 return *m_first;
00231 }
00232
00234
00237 return_value_type back() const {
00238 BOOST_CB_ASSERT(!empty());
00239 return *((m_last == m_buff ? m_end : m_last) - 1);
00240 }
00241
00243
00251 pointer data() {
00252 if (empty())
00253 return 0;
00254 if (m_first < m_last || m_last == m_buff)
00255 return m_first;
00256 size_type constructed = 0;
00257 pointer src = m_first;
00258 pointer dest = m_buff;
00259 pointer tmp = 0;
00260 BOOST_CB_TRY
00261 tmp = allocate(1);
00262 for (pointer first = m_first; dest < src; src = first) {
00263 for (size_type ii = 0; src < m_end; ++src, ++dest, ++ii) {
00264 if (dest == first) {
00265 first += ii;
00266 break;
00267 }
00268 if (is_uninitialized(dest)) {
00269 m_alloc.construct(dest, *src);
00270 ++constructed;
00271 } else {
00272 m_alloc.construct(tmp, *src);
00273 BOOST_CB_TRY
00274 replace(src, *dest);
00275 BOOST_CB_UNWIND(
00276 destroy_item(tmp);
00277 tidy(src);
00278 )
00279 BOOST_CB_TRY
00280 replace(dest, *tmp);
00281 BOOST_CB_UNWIND(
00282 destroy_item(tmp);
00283 tidy(dest);
00284 )
00285 destroy_item(tmp);
00286 }
00287 }
00288 }
00289 deallocate(tmp, 1);
00290 BOOST_CB_UNWIND(
00291 deallocate(tmp, 1);
00292 m_last += constructed;
00293 m_size += constructed;
00294 )
00295 for (dest = m_buff + size(); dest < m_end; ++dest)
00296 destroy_item(dest);
00297 m_first = m_buff;
00298 m_last = add(m_buff, size());
00299 return m_buff;
00300 }
00301
00302
00303
00305 size_type size() const { return m_size; }
00306
00308 size_type max_size() const { return m_alloc.max_size(); }
00309
00311
00315 bool empty() const { return size() == 0; }
00316
00318
00323 bool full() const { return size() == capacity(); }
00324
00326 size_type capacity() const { return m_end - m_buff; }
00327
00329
00347 void set_capacity(size_type new_capacity, bool remove_front = true) {
00348 if (new_capacity == capacity())
00349 return;
00350 pointer buff = allocate(new_capacity);
00351 size_type new_size = std::min(new_capacity, size());
00352 BOOST_CB_TRY
00353 if (remove_front)
00354 cb_details::uninitialized_copy(end() - new_size, end(), buff, m_alloc);
00355 else
00356 cb_details::uninitialized_copy(begin(), begin() + new_size, buff, m_alloc);
00357 BOOST_CB_UNWIND(deallocate(buff, new_capacity))
00358 destroy();
00359 m_size = new_size;
00360 m_buff = m_first = buff;
00361 m_end = m_buff + new_capacity;
00362 m_last = add(m_buff, size());
00363 }
00364
00366
00387 void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) {
00388 if (new_size > size()) {
00389 if (new_size > capacity())
00390 set_capacity(new_size);
00391 insert(end(), new_size - size(), item);
00392 } else {
00393 if (remove_front)
00394 erase(begin(), end() - new_size);
00395 else
00396 erase(begin() + new_size, end());
00397 }
00398 }
00399
00400
00401
00403
00407 explicit circular_buffer(
00408 size_type capacity,
00409 const allocator_type& alloc = allocator_type())
00410 : m_size(0), m_alloc(alloc) {
00411 m_first = m_last = m_buff = allocate(capacity);
00412 m_end = m_buff + capacity;
00413 }
00414
00416
00421 circular_buffer(
00422 size_type capacity,
00423 param_value_type item,
00424 const allocator_type& alloc = allocator_type())
00425 : m_size(capacity), m_alloc(alloc) {
00426 m_first = m_last = m_buff = allocate(capacity);
00427 m_end = m_buff + capacity;
00428 BOOST_CB_TRY
00429 cb_details::uninitialized_fill_n(m_buff, size(), item, m_alloc);
00430 BOOST_CB_UNWIND(deallocate(m_buff, capacity))
00431 }
00432
00434
00439 circular_buffer(const circular_buffer<T, Alloc>& cb)
00440 : m_size(cb.size()), m_alloc(cb.get_allocator()) {
00441 m_first = m_last = m_buff = allocate(cb.capacity());
00442 BOOST_CB_TRY
00443 m_end = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, m_alloc);
00444 BOOST_CB_UNWIND(deallocate(m_buff, cb.capacity()))
00445 }
00446
00448
00458 template <class InputIterator>
00459 circular_buffer(
00460 size_type capacity,
00461 InputIterator first,
00462 InputIterator last,
00463 const allocator_type& alloc = allocator_type())
00464 : m_alloc(alloc) {
00465 BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
00466 BOOST_CB_ASSERT(std::distance(first, last) >= 0);
00467 m_first = m_buff = allocate(capacity);
00468 m_end = m_buff + capacity;
00469 size_type diff = std::distance(first, last);
00470 if (diff > capacity) {
00471 std::advance(first, diff - capacity);
00472 m_size = capacity;
00473 m_last = m_buff;
00474 } else {
00475 m_size = diff;
00476 if (diff == capacity)
00477 m_last = m_buff;
00478 else
00479 m_last = m_buff + size();
00480 }
00481 BOOST_CB_TRY
00482 cb_details::uninitialized_copy(first, last, m_buff, m_alloc);
00483 BOOST_CB_UNWIND(deallocate(m_buff, capacity))
00484 }
00485
00487 ~circular_buffer() { destroy(); }
00488
00489 private:
00490
00491
00492
00493 struct assign_n {
00494 size_type m_n;
00495 param_value_type m_item;
00496 allocator_type& m_alloc;
00497 explicit assign_n(size_type n, param_value_type item, allocator_type& alloc) : m_n(n), m_item(item), m_alloc(alloc) {}
00498 void operator () (pointer p) const {
00499 cb_details::uninitialized_fill_n(p, m_n, m_item, m_alloc);
00500 }
00501 private:
00502 assign_n& operator = (const assign_n&);
00503 };
00504
00505
00506 template <class InputIterator>
00507 struct assign_range {
00508 InputIterator m_first;
00509 InputIterator m_last;
00510 allocator_type& m_alloc;
00511 explicit assign_range(InputIterator first, InputIterator last, allocator_type& alloc) : m_first(first), m_last(last), m_alloc(alloc) {}
00512 void operator () (pointer p) const {
00513 cb_details::uninitialized_copy(m_first, m_last, p, m_alloc);
00514 }
00515 private:
00516 assign_range& operator = (const assign_range&);
00517 };
00518
00519 public:
00520
00521
00523
00529 circular_buffer<T, Alloc>& operator = (const circular_buffer<T, Alloc>& cb) {
00530 if (this == &cb)
00531 return *this;
00532 pointer buff = allocate(cb.capacity());
00533 BOOST_CB_TRY
00534 pointer last = cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, m_alloc);
00535 destroy();
00536 m_size = cb.size();
00537 m_first = m_buff = buff;
00538 m_end = m_buff + cb.capacity();
00539 m_last = full() ? m_buff : last;
00540 BOOST_CB_UNWIND(deallocate(buff, cb.capacity()))
00541 return *this;
00542 }
00543
00545
00555 void assign(size_type n, param_value_type item) { do_assign(n, assign_n(n, item, m_alloc)); }
00556
00558
00568 template <class InputIterator>
00569 void assign(InputIterator first, InputIterator last) {
00570 assign(first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
00571 }
00572
00574
00578 void swap(circular_buffer& cb) {
00579 std::swap(m_alloc, cb.m_alloc);
00580
00581 std::swap(m_buff, cb.m_buff);
00582 std::swap(m_end, cb.m_end);
00583 std::swap(m_first, cb.m_first);
00584 std::swap(m_last, cb.m_last);
00585 std::swap(m_size, cb.m_size);
00586 #if BOOST_CB_ENABLE_DEBUG
00587 invalidate_all_iterators();
00588 cb.invalidate_all_iterators();
00589 #endif
00590 }
00591
00592
00593
00595
00601 void push_back(param_value_type item) {
00602 if (full()) {
00603 if (empty())
00604 return;
00605 replace_last(item);
00606 increment(m_last);
00607 m_first = m_last;
00608 } else {
00609 m_alloc.construct(m_last, item);
00610 increment(m_last);
00611 ++m_size;
00612 }
00613 }
00614
00616
00622 void push_back() { push_back(value_type()); }
00623
00625
00631 void push_front(param_value_type item) {
00632 if (full()) {
00633 if (empty())
00634 return;
00635 replace_first(item);
00636 m_last = m_first;
00637 } else {
00638 decrement(m_first);
00639 BOOST_CB_TRY
00640 m_alloc.construct(m_first, item);
00641 BOOST_CB_UNWIND(increment(m_first))
00642 ++m_size;
00643 }
00644 }
00645
00647
00653 void push_front() { push_front(value_type()); }
00654
00656
00662 void pop_back() {
00663 BOOST_CB_ASSERT(!empty());
00664 decrement(m_last);
00665 destroy_item(m_last);
00666 --m_size;
00667 }
00668
00670
00676 void pop_front() {
00677 BOOST_CB_ASSERT(!empty());
00678 destroy_item(m_first);
00679 increment(m_first);
00680 --m_size;
00681 }
00682
00683 private:
00684
00685
00686
00687 template <class InputIterator>
00688 struct iterator_wrapper {
00689 mutable InputIterator m_it;
00690 explicit iterator_wrapper(InputIterator it) : m_it(it) {}
00691 InputIterator get_reference() const { return m_it++; }
00692 };
00693
00694
00695 struct item_wrapper {
00696 const_pointer m_item;
00697 explicit item_wrapper(param_value_type item) : m_item(&item) {}
00698 const_pointer get_reference() const { return m_item; }
00699 };
00700
00701 public:
00702
00703
00705
00714 iterator insert(iterator pos, param_value_type item) {
00715 BOOST_CB_ASSERT(pos.is_valid());
00716 if (full() && pos == begin())
00717 return begin();
00718 if (pos.m_it == 0) {
00719 if (full())
00720 replace_last(item);
00721 else
00722 m_alloc.construct(m_last, item);
00723 pos.m_it = m_last;
00724 } else {
00725 pointer src = m_last;
00726 pointer dest = m_last;
00727 BOOST_CB_TRY
00728 while (src != pos.m_it) {
00729 decrement(src);
00730 if (dest == m_last && !full())
00731 m_alloc.construct(dest, *src);
00732 else
00733 replace(dest, *src);
00734 decrement(dest);
00735 }
00736 replace(pos.m_it, item);
00737 BOOST_CB_UNWIND(
00738 if (dest == m_last) {
00739 if (full()) {
00740 increment(m_first);
00741 --m_size;
00742 }
00743 } else {
00744 if (!full()) {
00745 increment(m_last);
00746 ++m_size;
00747 }
00748 tidy(dest);
00749 }
00750 )
00751 }
00752 increment(m_last);
00753 if (full())
00754 m_first = m_last;
00755 else
00756 ++m_size;
00757 return iterator(this, pos.m_it);
00758 }
00759
00761
00769 iterator insert(iterator pos) { return insert(pos, value_type()); }
00770
00772
00790 void insert(iterator pos, size_type n, param_value_type item) {
00791 BOOST_CB_ASSERT(pos.is_valid());
00792 if (n == 0)
00793 return;
00794 size_type copy = capacity() - (end() - pos);
00795 if (copy == 0)
00796 return;
00797 if (n > copy)
00798 n = copy;
00799 insert_n_item(pos, n, item_wrapper(item));
00800 }
00801
00803
00824 template <class InputIterator>
00825 void insert(iterator pos, InputIterator first, InputIterator last) {
00826 BOOST_CB_ASSERT(pos.is_valid());
00827 insert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
00828 }
00829
00831
00840 iterator rinsert(iterator pos, param_value_type item) {
00841 BOOST_CB_ASSERT(pos.is_valid());
00842 if (full() && pos == end())
00843 return end();
00844 if (pos == begin()) {
00845 if (full()) {
00846 replace_first(item);
00847 } else {
00848 decrement(m_first);
00849 BOOST_CB_TRY
00850 m_alloc.construct(m_first, item);
00851 BOOST_CB_UNWIND(increment(m_first))
00852 }
00853 } else {
00854 pointer src = m_first;
00855 pointer dest = m_first;
00856 decrement(dest);
00857 pointer it = map_pointer(pos.m_it);
00858 pointer first = m_first;
00859 decrement(first);
00860 BOOST_CB_TRY
00861 while (src != it) {
00862 if (dest == first && !full())
00863 m_alloc.construct(dest, *src);
00864 else
00865 replace(dest, *src);
00866 increment(src);
00867 increment(dest);
00868 }
00869 replace((--pos).m_it, item);
00870 BOOST_CB_UNWIND(
00871 if (dest == first) {
00872 if (full()) {
00873 decrement(m_last);
00874 --m_size;
00875 }
00876 } else {
00877 if (!full()) {
00878 m_first = first;
00879 ++m_size;
00880 }
00881 tidy(dest);
00882 }
00883 )
00884 decrement(m_first);
00885 }
00886 if (full())
00887 m_last = m_first;
00888 else
00889 ++m_size;
00890 return iterator(this, pos.m_it);
00891 }
00892
00894
00902 iterator rinsert(iterator pos) { return rinsert(pos, value_type()); }
00903
00905
00923 void rinsert(iterator pos, size_type n, param_value_type item) {
00924 BOOST_CB_ASSERT(pos.is_valid());
00925 rinsert_n_item(pos, n, item_wrapper(item));
00926 }
00927
00929
00950 template <class InputIterator>
00951 void rinsert(iterator pos, InputIterator first, InputIterator last) {
00952 BOOST_CB_ASSERT(pos.is_valid());
00953 rinsert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
00954 }
00955
00956
00957
00959
00968 iterator erase(iterator pos) {
00969 BOOST_CB_ASSERT(pos.is_valid());
00970 BOOST_CB_ASSERT(pos.m_it != 0);
00971 pointer next = pos.m_it;
00972 increment(next);
00973 for (pointer p = pos.m_it; next != m_last; p = next, increment(next))
00974 replace(p, *next);
00975 decrement(m_last);
00976 destroy_item(m_last);
00977 --m_size;
00978 #if BOOST_CB_ENABLE_DEBUG
00979 return empty() ? end() : iterator(this, pos.m_it);
00980 #else
00981 return empty() ? end() : pos;
00982 #endif
00983 }
00984
00986
00995 iterator erase(iterator first, iterator last) {
00996 BOOST_CB_ASSERT(first.is_valid());
00997 BOOST_CB_ASSERT(last.is_valid());
00998 BOOST_CB_ASSERT(first.m_buff == last.m_buff);
00999 BOOST_CB_ASSERT(first <= last);
01000 if (first == last)
01001 return first;
01002 pointer tmp = first.m_it;
01003 difference_type diff = last - first;
01004 while (last.m_it != 0)
01005 replace((first++).m_it, *last++);
01006 while (first.m_it != 0)
01007 destroy_item((first++).m_it);
01008 m_last = sub(m_last, diff);
01009 m_size -= diff;
01010 return empty() ? end() : iterator(this, tmp);
01011 }
01012
01014
01018 void clear() {
01019 destroy_content();
01020 m_first = m_last = m_buff;
01021 m_size = 0;
01022 }
01023
01024 private:
01025
01026
01027 #if BOOST_CB_ENABLE_DEBUG
01028
01029
01030 struct is_invalid_condition {
01031 pointer m_p;
01032 explicit is_invalid_condition(pointer p) : m_p(p) {}
01033 bool operator () (const cb_details::cb_iterator_base* p) const {
01034 return ((iterator*)p)->m_it == m_p;
01035 }
01036 };
01037
01038 #endif // #if BOOST_CB_ENABLE_DEBUG
01039
01040
01041
01043 void check_position(size_type index) const {
01044 if (index >= size())
01045 throw_exception(std::out_of_range("circular_buffer"));
01046 }
01047
01049 template <class Pointer0>
01050 void increment(Pointer0& p) const {
01051 if (++p == m_end)
01052 p = m_buff;
01053 }
01054
01056 template <class Pointer0>
01057 void decrement(Pointer0& p) const {
01058 if (p == m_buff)
01059 p = m_end;
01060 --p;
01061 }
01062
01064 template <class Pointer0>
01065 Pointer0 add(Pointer0 p, difference_type n) const {
01066 return p + (n < (m_end - p) ? n : n - capacity());
01067 }
01068
01070 template <class Pointer0>
01071 Pointer0 sub(Pointer0 p, difference_type n) const {
01072 return p - (n > (p - m_buff) ? n - capacity() : n);
01073 }
01074
01076 pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; }
01077
01079 bool is_uninitialized(const_pointer p) const {
01080 return p >= m_last && (m_first < m_last || p < m_first);
01081 }
01082
01084
01087 void create_or_replace(pointer pos, param_value_type item) {
01088 if (is_uninitialized(pos))
01089 m_alloc.construct(pos, item);
01090 else
01091 replace(pos, item);
01092 }
01093
01095
01098 void destroy_created(pointer pos) {
01099 if (is_uninitialized(pos))
01100 destroy_item(pos);
01101 }
01102
01104 void replace(pointer pos, param_value_type item) {
01105 replace(pos, item, cb_details::cb_replace_category_traits<value_type>::tag());
01106 #if BOOST_CB_ENABLE_DEBUG
01107 invalidate_iterators(is_invalid_condition(pos));
01108 #endif
01109 }
01110
01112 void replace(pointer pos, param_value_type item, cb_details::cb_destroy_tag) {
01113 m_alloc.destroy(pos);
01114 m_alloc.construct(pos, item);
01115 }
01116
01118 void replace(pointer pos, param_value_type item, cb_details::cb_assign_tag) {
01119 *pos = item;
01120 }
01121
01123 void replace_first(param_value_type item) {
01124 decrement(m_first);
01125 BOOST_CB_TRY
01126 replace(m_first, item);
01127 BOOST_CB_UNWIND(
01128 increment(m_first);
01129 decrement(m_last);
01130 --m_size;
01131 )
01132 }
01133
01135 void replace_last(param_value_type item) {
01136 BOOST_CB_TRY
01137 replace(m_last, item);
01138 BOOST_CB_UNWIND(
01139 decrement(m_last);
01140 --m_size;
01141 )
01142 }
01143
01145 void tidy(pointer p) {
01146 for (; m_first != p; increment(m_first), --m_size)
01147 destroy_item(m_first);
01148 increment(m_first);
01149 --m_size;
01150 }
01151
01153 pointer allocate(size_type n) {
01154 if (n > max_size())
01155 throw_exception(std::length_error("circular_buffer"));
01156 #if BOOST_CB_ENABLE_DEBUG
01157 pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0);
01158 ::memset(p, cb_details::CB_Unitialized, sizeof(value_type) * n);
01159 return p;
01160 #else
01161 return (n == 0) ? 0 : m_alloc.allocate(n, 0);
01162 #endif
01163 }
01164
01166 void deallocate(pointer p, size_type n) {
01167 if (p != 0)
01168 m_alloc.deallocate(p, n);
01169 }
01170
01172 void destroy_item(pointer p) {
01173 m_alloc.destroy(p);
01174 #if BOOST_CB_ENABLE_DEBUG
01175 invalidate_iterators(is_invalid_condition(p));
01176 ::memset(p, cb_details::CB_Unitialized, sizeof(value_type));
01177 #endif
01178 }
01179
01181 void destroy_content() {
01182 for (size_type ii = 0; ii < size(); ++ii, increment(m_first))
01183 destroy_item(m_first);
01184 }
01185
01187 void destroy() {
01188 destroy_content();
01189 deallocate(m_buff, capacity());
01190 #if BOOST_CB_ENABLE_DEBUG
01191 invalidate_all_iterators();
01192 m_buff = 0;
01193 m_first = 0;
01194 m_last = 0;
01195 m_end = 0;
01196 #endif
01197 }
01198
01200 template <class InputIterator>
01201 void assign(InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
01202 assign((size_type)n, item);
01203 }
01204
01206 template <class InputIterator>
01207 void assign(InputIterator first, InputIterator last, std::input_iterator_tag) {
01208 BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
01209 BOOST_CB_ASSERT(std::distance(first, last) >= 0);
01210 do_assign(std::distance(first, last), assign_range<InputIterator>(first, last, m_alloc));
01211 }
01212
01214 template <class Functor>
01215 void do_assign(size_type n, const Functor& fnc) {
01216 if (n > capacity()) {
01217 pointer buff = allocate(n);
01218 BOOST_CB_TRY
01219 fnc(buff);
01220 BOOST_CB_UNWIND(deallocate(buff, n))
01221 destroy();
01222 m_buff = buff;
01223 m_end = m_buff + n;
01224 } else {
01225 destroy_content();
01226 BOOST_CB_TRY
01227 fnc(m_buff);
01228 BOOST_CB_UNWIND(m_size = 0)
01229 }
01230 m_size = n;
01231 m_first = m_buff;
01232 m_last = add(m_buff, size());
01233 }
01234
01236 template <class InputIterator>
01237 void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
01238 insert(pos, (size_type)n, item);
01239 }
01240
01242 template <class InputIterator>
01243 void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
01244 BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
01245 BOOST_CB_ASSERT(std::distance(first, last) >= 0);
01246 difference_type n = std::distance(first, last);
01247 if (n == 0)
01248 return;
01249 difference_type copy = capacity() - (end() - pos);
01250 if (copy == 0)
01251 return;
01252 if (n > copy) {
01253 std::advance(first, n - copy);
01254 n = copy;
01255 }
01256 insert_n_item(pos, n, iterator_wrapper<InputIterator>(first));
01257 }
01258
01260 template <class Wrapper>
01261 void insert_n_item(iterator pos, size_type n, const Wrapper& wrapper) {
01262 size_type construct = capacity() - size();
01263 if (construct > n)
01264 construct = n;
01265 if (pos.m_it == 0) {
01266 size_type ii = 0;
01267 pointer p = m_last;
01268 BOOST_CB_TRY
01269 for (; ii < construct; ++ii, increment(p))
01270 m_alloc.construct(p, *wrapper.get_reference());
01271 for (;ii < n; ++ii, increment(p))
01272 replace(p, *wrapper.get_reference());
01273 BOOST_CB_UNWIND(
01274 size_type constructed = std::min(ii, construct);
01275 m_last = add(m_last, constructed);
01276 m_size += constructed;
01277 if (ii >= construct)
01278 tidy(p);
01279 )
01280 } else {
01281 pointer src = m_last;
01282 pointer dest = add(m_last, n - 1);
01283 size_type ii = 0;
01284 BOOST_CB_TRY
01285 while (src != pos.m_it) {
01286 decrement(src);
01287 create_or_replace(dest, *src);
01288 decrement(dest);
01289 }
01290 for (dest = pos.m_it; ii < n; ++ii, increment(dest))
01291 create_or_replace(dest, *wrapper.get_reference());
01292 BOOST_CB_UNWIND(
01293 for (pointer p1 = m_last, p2 = add(m_last, n - 1); p1 != src; decrement(p2)) {
01294 decrement(p1);
01295 destroy_created(p2);
01296 }
01297 for (n = 0, src = pos.m_it; n < ii; ++n, increment(src))
01298 destroy_created(src);
01299 if (!is_uninitialized(dest))
01300 tidy(dest);
01301 )
01302 }
01303 m_last = add(m_last, n);
01304 m_first = add(m_first, n - construct);
01305 m_size += construct;
01306 }
01307
01309 template <class InputIterator>
01310 void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
01311 rinsert(pos, (size_type)n, item);
01312 }
01313
01315 template <class InputIterator>
01316 void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
01317 BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
01318 BOOST_CB_ASSERT(std::distance(first, last) >= 0);
01319 rinsert_n_item(pos, std::distance(first, last), iterator_wrapper<InputIterator>(first));
01320 }
01321
01323 template <class Wrapper>
01324 void rinsert_n_item(iterator pos, size_type n, const Wrapper& wrapper) {
01325 if (n == 0)
01326 return;
01327 size_type copy = capacity() - (pos - begin());
01328 if (copy == 0)
01329 return;
01330 if (n > copy)
01331 n = copy;
01332 size_type construct = capacity() - size();
01333 if (construct > n)
01334 construct = n;
01335 if (pos == begin()) {
01336 pointer p = sub(map_pointer(pos.m_it), n);
01337 size_type ii = n;
01338 BOOST_CB_TRY
01339 for (;ii > construct; --ii, increment(p))
01340 replace(p, *wrapper.get_reference());
01341 for (; ii > 0; --ii, increment(p))
01342 m_alloc.construct(p, *wrapper.get_reference());
01343 BOOST_CB_UNWIND(
01344 size_type unwind = ii < construct ? construct - ii : 0;
01345 pointer tmp = sub(map_pointer(pos.m_it), construct);
01346 for (n = 0; n < unwind; ++n, increment(tmp))
01347 destroy_item(tmp);
01348 if (ii > construct)
01349 tidy(p);
01350 )
01351 } else {
01352 pointer src = m_first;
01353 pointer dest = sub(m_first, n);
01354 pointer p = map_pointer(pos.m_it);
01355 size_type ii = 0;
01356 BOOST_CB_TRY
01357 while (src != p) {
01358 create_or_replace(dest, *src);
01359 increment(src);
01360 increment(dest);
01361 }
01362 dest = sub(p, n);
01363 for (; ii < n; ++ii, increment(dest))
01364 create_or_replace(dest, *wrapper.get_reference());
01365 BOOST_CB_UNWIND(
01366 for (pointer p1 = m_first, p2 = sub(m_first, n); p1 != src; increment(p1), increment(p2))
01367 destroy_created(p2);
01368 p = sub(p, n);
01369 for (n = 0; n < ii; ++n, increment(p))
01370 destroy_created(p);
01371 if (!is_uninitialized(dest))
01372 tidy(dest);
01373 )
01374 }
01375 m_first = sub(m_first, n);
01376 m_last = sub(m_last, n - construct);
01377 m_size += construct;
01378 }
01379 };
01380
01381
01382
01384 template <class T, class Alloc>
01385 inline bool operator == (const circular_buffer<T, Alloc>& lhs,
01386 const circular_buffer<T, Alloc>& rhs) {
01387 return lhs.size() == rhs.size() &&
01388 std::equal(lhs.begin(), lhs.end(), rhs.begin());
01389 }
01390
01392 template <class T, class Alloc>
01393 inline bool operator < (const circular_buffer<T, Alloc>& lhs,
01394 const circular_buffer<T, Alloc>& rhs) {
01395 return std::lexicographical_compare(
01396 lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
01397 }
01398
01399 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC)
01400
01402 template <class T, class Alloc>
01403 inline bool operator != (const circular_buffer<T, Alloc>& lhs,
01404 const circular_buffer<T, Alloc>& rhs) {
01405 return !(lhs == rhs);
01406 }
01407
01409 template <class T, class Alloc>
01410 inline bool operator > (const circular_buffer<T, Alloc>& lhs,
01411 const circular_buffer<T, Alloc>& rhs) {
01412 return rhs < lhs;
01413 }
01414
01416 template <class T, class Alloc>
01417 inline bool operator <= (const circular_buffer<T, Alloc>& lhs,
01418 const circular_buffer<T, Alloc>& rhs) {
01419 return !(rhs < lhs);
01420 }
01421
01423 template <class T, class Alloc>
01424 inline bool operator >= (const circular_buffer<T, Alloc>& lhs,
01425 const circular_buffer<T, Alloc>& rhs) {
01426 return !(lhs < rhs);
01427 }
01428
01430 template <class T, class Alloc>
01431 inline void swap(circular_buffer<T, Alloc>& lhs, circular_buffer<T, Alloc>& rhs) {
01432 lhs.swap(rhs);
01433 }
01434
01435 #endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC)
01436
01437 }
01438
01439 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)