Home Libraries People FAQ More

Main Page | Class Hierarchy | Class List | File List | Class Members

adaptor.hpp

00001 // Implementation of the circular buffer adaptor.
00002 
00003 // Copyright (c) 2003-2004 Jan Gaspar
00004 
00005 // Use, modification, and distribution is subject to the Boost Software
00006 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
00007 // http://www.boost.org/LICENSE_1_0.txt)
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 // Typedefs
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 // Inherited
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 // Member variables
00074 
00076     size_type m_capacity;
00077 
00079     size_type m_min_capacity;
00080 
00081 public:
00082 // Overridden
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); // check for too large 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()); // check for too low new 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); // check for capacity lower than 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); // check for capacity lower than min_capacity
00201     }
00202 
00203     // Default copy constructor
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);        // check for capacity lower than min_capacity
00239         BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
00240     }
00241 
00242     // Default destructor
00243 
00244     // Default assign operator
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 // Helper methods
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; // ensure at least 20% reserve
00451         if (new_capacity > capacity())
00452             return capacity();
00453         return new_capacity;
00454     }
00455 
00457     /*
00458         \post If the capacity is low it will be increased.
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         \post If the capacity is high it will be decreased.
00475     */
00476     void check_high_capacity() {
00477         size_type new_capacity = circular_buffer<T, Alloc>::capacity();
00478         while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations
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 // Non-member functions
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 } // namespace boost
00584 
00585 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)