RingBuffer.h
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2014 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00022 //----------------------------------------------------------------------
00023 #ifndef ICL_CORE_RING_BUFFER_H_INCLUDED
00024 #define ICL_CORE_RING_BUFFER_H_INCLUDED
00025 
00026 #include <stdexcept>
00027 #include <iterator>
00028 #include <vector>
00029 
00030 #include "icl_core/BaseTypes.h"
00031 
00032 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00033 # include "icl_core/Deprecate.h"
00034 #endif
00035 
00036 namespace icl_core {
00037 
00044 template <typename T>
00045 class RingBuffer
00046 {
00047 public:
00048   typedef T value_type;
00049   typedef typename std::vector<T>::size_type size_type;
00050   typedef typename std::vector<T>::difference_type difference_type;
00052   typedef std::pair<T*, size_type> array_range;
00054   typedef std::pair<const T*, size_type> const_array_range;
00055   static const size_type cDEFAULT_CAPACITY = 32;
00056 
00058   class const_iterator : public std::iterator<std::random_access_iterator_tag, T>
00059   {
00060     friend class RingBuffer;
00061 
00062   public:
00063     const_iterator(const const_iterator& other)
00064       : m_current(other.m_current), m_cbegin(other.m_cbegin), m_cend(other.m_cend), m_begin(other.m_begin)
00065     { }
00066 
00067     const_iterator& operator = (const const_iterator& other)
00068     {
00069       m_current = other.m_current; m_cbegin = other.m_cbegin; m_cend = other.m_cend; m_begin = other.m_begin;
00070       return *this;
00071     }
00072 
00073     const_iterator& operator ++ ()
00074     {
00075       ++m_current;
00076       if (m_current == m_cend) { m_current = m_cbegin; }
00077       return *this;
00078     }
00079     const_iterator operator ++ (int)
00080     {
00081       const_iterator answer = *this;
00082       operator ++ ();
00083       return answer;
00084     }
00085 
00086     const_iterator& operator -- ()
00087     {
00088       if (m_current == m_cbegin)
00089       {
00090         m_current = m_cend;
00091       }
00092       --m_current;
00093       return *this;
00094     }
00095     const_iterator operator -- (int)
00096     {
00097       const_iterator answer = *this;
00098       operator -- ();
00099       return answer;
00100     }
00101 
00102     const_iterator& operator += (difference_type offset)
00103     {
00104       m_current += offset;
00105       if (m_current > m_cend)
00106       {
00107         m_current -= m_cend - m_cbegin;
00108       }
00109       if (m_cbegin > m_current)
00110       {
00111         m_current += m_cend - m_cbegin;
00112       }
00113       return *this;
00114     }
00115     const_iterator& operator -= (difference_type offset)
00116     {
00117       return operator += (-offset);
00118     }
00119     const_iterator operator + (difference_type offset) const
00120     {
00121       const_iterator answer = *this;
00122       answer += offset;
00123       return answer;
00124     }
00125     const_iterator operator - (difference_type offset) const
00126     {
00127       const_iterator answer = *this;
00128       answer -= offset;
00129       return answer;
00130     }
00131 
00132     difference_type operator - (const const_iterator& other) const
00133     {
00134       if ((m_current >= m_begin && other.m_current >= other.m_begin)
00135           || (m_current < m_begin && other.m_current < other.m_begin))
00136       {
00137         return m_current - other.m_current;
00138       }
00139       else if (m_current >= m_begin)
00140       {
00141         return m_current - other.m_current + m_cbegin - m_cend;
00142       }
00143       else
00144       {
00145         return m_current - other.m_current + m_cend - m_cbegin;
00146       }
00147     }
00148 
00149     bool operator == (const const_iterator& other) const { return m_current == other.m_current; }
00150     bool operator != (const const_iterator& other) const { return m_current != other.m_current; }
00151 
00152     const T& operator * () const { return *m_current; }
00153     const T *operator -> () const { return m_current; }
00154 
00155   protected:
00156     const_iterator(T *current, T *cbegin, T *cend, T *begin)
00157       : m_current(current), m_cbegin(cbegin), m_cend(cend), m_begin(begin)
00158     { }
00159 
00160     T *m_current;
00162     T *m_cbegin;
00164     T *m_cend;
00166     T *m_begin;
00167   };
00168 
00170   class iterator : public const_iterator
00171   {
00172     friend class RingBuffer;
00173 
00174   public:
00175     iterator(const iterator& other)
00176       : const_iterator(other)
00177     { }
00178 
00179     iterator& operator = (const iterator& other)
00180     {
00181       const_iterator::m_current = other.m_current;
00182       const_iterator::m_cbegin = other.m_cbegin;
00183       const_iterator::m_cend = other.m_cend;
00184       const_iterator::m_begin = other.m_begin;
00185       return *this;
00186     }
00187 
00188     T& operator * () const { return *const_iterator::m_current; }
00189     T *operator -> () const { return const_iterator::m_current; }
00190 
00191   protected:
00192     iterator(T *current, T *cbegin, T *cend, T *begin)
00193       : const_iterator(current, cbegin, cend, begin)
00194     { }
00195   };
00196 
00198   RingBuffer(size_type capacity = cDEFAULT_CAPACITY)
00199     : m_buffer(capacity+1), m_write(0), m_read(0)
00200   { }
00201 
00203   RingBuffer(const RingBuffer<T>& other)
00204     : m_buffer(other.m_buffer), m_write(other.m_write), m_read(other.m_read)
00205   { }
00206 
00208   RingBuffer& operator = (const RingBuffer<T>& other)
00209   {
00210     m_buffer = other.m_buffer;
00211     m_write = other.m_write;
00212     m_read = other.m_read;
00213     return *this;
00214   }
00215 
00217   void clear() { m_write = 0; m_read = 0; }
00218 
00220   bool empty() const { return m_write == m_read; }
00221 
00223   bool full() const { return ((m_write+1) % m_buffer.size()) == m_read; }
00224 
00226 
00230   void write(const T& val, bool overwrite=false)
00231   {
00232     size_type new_write_pos = m_write+1;
00233     if (new_write_pos >= m_buffer.size())
00234     {
00235       new_write_pos = 0;
00236     }
00237     if (new_write_pos == m_read)
00238     {
00239       if (overwrite)
00240       {
00241         skip();
00242       }
00243       else
00244       {
00245         throw std::out_of_range("RingBuffer::write: capacity exceeded");
00246       }
00247     }
00248     m_buffer[m_write] = val;
00249     m_write = new_write_pos;
00250   }
00251 
00258   void fakeWrite(size_t count);
00259 
00261 
00265   const T& at(size_type pos) const
00266   {
00267     if (pos < size())
00268     {
00269       pos += m_read;
00270       if (pos >= m_buffer.size())
00271       {
00272         pos -= m_buffer.size();
00273       }
00274       return m_buffer[pos];
00275     }
00276     else
00277     {
00278       throw std::out_of_range("RingBuffer::at: out of range");
00279     }
00280   }
00281 
00283 
00287   T& at(size_type pos)
00288   {
00289     if (pos < size())
00290     {
00291       pos += m_read;
00292       if (pos >= m_buffer.size())
00293       {
00294         pos -= m_buffer.size();
00295       }
00296       return m_buffer[pos];
00297     }
00298     else
00299     {
00300       throw std::out_of_range("RingBuffer::at: out of range");
00301     }
00302   }
00303 
00304   const T& front() const { return at(0); }
00305   T& front() { return at(0); }
00306 
00308   void skip()
00309   {
00310     if (m_write == m_read)
00311     {
00312       throw std::out_of_range("RingBuffer::skip: buffer empty");
00313     }
00314     m_read++;
00315     if (m_read >= m_buffer.size())
00316     {
00317       m_read = 0;
00318     }
00319   }
00320 
00324   void skip(size_type count);
00325 
00327 
00329   T read()
00330   {
00331     if (m_write == m_read)
00332     {
00333       throw std::out_of_range("RingBuffer::read: buffer empty");
00334     }
00335     size_type read_pos = m_read;
00336     m_read++;
00337     if (m_read >= m_buffer.size())
00338     {
00339       m_read = 0;
00340     }
00341     return m_buffer[read_pos];
00342   }
00343 
00345   inline size_type size() const
00346   {
00347     if (m_write >= m_read)
00348     {
00349       return m_write-m_read;
00350     }
00351     else
00352     {
00353       return m_write+m_buffer.size()-m_read;
00354     }
00355   }
00356 
00358   size_type capacity() const { return m_buffer.size()-1; }
00359 
00361   size_type reserve() const
00362   {
00363     return capacity() - size();
00364   }
00365 
00367 
00371   void setCapacity(size_type capacity)
00372   {
00373     size_type old_size = size();
00374     size_type new_size = (capacity < old_size) ? capacity : old_size;
00375     std::vector<T> old_buffer(m_buffer);
00376     size_type old_read = m_read;
00377 
00378     // Adjust capacity.
00379     m_buffer.resize(capacity+1);
00380     // Skip elements that will not fit.
00381     old_read += old_size-new_size;
00382     if (old_read >= old_buffer.size())
00383     {
00384       old_read -= old_buffer.size();
00385     }
00386     // Copy the rest.
00387     for (size_type i=0; i<new_size; i++)
00388     {
00389       m_buffer[i] = old_buffer[old_read];
00390       old_read++;
00391       if (old_read >= old_buffer.size())
00392       {
00393         old_read = 0;
00394       }
00395     }
00396     // Update pointers.
00397     m_read = 0;
00398     m_write = new_size;
00399   }
00400 
00404   ~RingBuffer()
00405   { }
00406 
00407   const_iterator begin() const
00408   { return const_iterator(&m_buffer[m_read], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00409   iterator begin()
00410   { return iterator(&m_buffer[m_read], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00411 
00412   const_iterator end() const
00413   { return const_iterator(&m_buffer[m_write], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00414   iterator end()
00415   { return iterator(&m_buffer[m_write], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00416 
00432   array_range arrayOne();
00437   const_array_range arrayOne() const;
00438 
00443   array_range arrayTwo();
00448   const_array_range arrayTwo() const;
00449 
00454   array_range emptyArrayOne();
00459   const_array_range emptyArrayOne() const;
00464   array_range emptyArrayTwo();
00469   const_array_range emptyArrayTwo() const;
00470 
00472 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00473 
00477   ICL_CORE_VC_DEPRECATE_STYLE void Clear() ICL_CORE_GCC_DEPRECATE_STYLE;
00478 
00480 
00485   ICL_CORE_VC_DEPRECATE_STYLE
00486   void Write(const T& val, bool overwrite=false) ICL_CORE_GCC_DEPRECATE_STYLE;
00487 
00489 
00494   ICL_CORE_VC_DEPRECATE_STYLE const T& At(size_type pos) const ICL_CORE_GCC_DEPRECATE_STYLE;
00495 
00497 
00502   ICL_CORE_VC_DEPRECATE_STYLE T& At(size_type pos) ICL_CORE_GCC_DEPRECATE_STYLE;
00503 
00507   ICL_CORE_VC_DEPRECATE_STYLE void Skip() ICL_CORE_GCC_DEPRECATE_STYLE;
00508 
00510 
00513   ICL_CORE_VC_DEPRECATE_STYLE T Read() ICL_CORE_GCC_DEPRECATE_STYLE;
00514 
00518   inline ICL_CORE_VC_DEPRECATE_STYLE size_type Size() const ICL_CORE_GCC_DEPRECATE_STYLE;
00519 
00523   ICL_CORE_VC_DEPRECATE_STYLE size_type Capacity() const ICL_CORE_GCC_DEPRECATE_STYLE;
00524 
00526 
00531   ICL_CORE_VC_DEPRECATE_STYLE void SetCapacity(size_type capacity) ICL_CORE_GCC_DEPRECATE_STYLE;
00532 
00533 #endif
00534 
00535 
00536 private:
00537   std::vector<T> m_buffer;
00538   size_type m_write;
00539   size_type m_read;
00540 };
00541 
00542 }
00543 
00544 #include "icl_core/RingBuffer.hpp"
00545 
00546 #endif


schunk_svh_driver
Author(s): Georg Heppner
autogenerated on Fri Aug 28 2015 12:59:19