Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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(const T *current, const T *cbegin, const T *cend, const T *begin)
00157 : m_current(current), m_cbegin(cbegin), m_cend(cend), m_begin(begin)
00158 { }
00159
00160 const T *m_current;
00162 const T *m_cbegin;
00164 const T *m_cend;
00166 const T *m_begin;
00167 };
00168
00174 class iterator : public const_iterator
00175 {
00176 friend class RingBuffer;
00177
00178 public:
00179 iterator(const iterator& other)
00180 : const_iterator(other)
00181 { }
00182
00183 iterator& operator = (const iterator& other)
00184 {
00185 const_iterator::m_current = other.m_current;
00186 const_iterator::m_cbegin = other.m_cbegin;
00187 const_iterator::m_cend = other.m_cend;
00188 const_iterator::m_begin = other.m_begin;
00189 return *this;
00190 }
00191
00192 T& operator * () const { return *const_cast<T *>(const_iterator::m_current); }
00193 T *operator -> () const { return const_cast<T *>(const_iterator::m_current); }
00194
00195 protected:
00196 iterator(const T *current, const T *cbegin, const T *cend, const T *begin)
00197 : const_iterator(current, cbegin, cend, begin)
00198 { }
00199 };
00200
00202 RingBuffer(size_type capacity = cDEFAULT_CAPACITY)
00203 : m_buffer(capacity+1), m_write(0), m_read(0)
00204 { }
00205
00207 RingBuffer(const RingBuffer<T>& other)
00208 : m_buffer(other.m_buffer), m_write(other.m_write), m_read(other.m_read)
00209 { }
00210
00212 RingBuffer& operator = (const RingBuffer<T>& other)
00213 {
00214 m_buffer = other.m_buffer;
00215 m_write = other.m_write;
00216 m_read = other.m_read;
00217 return *this;
00218 }
00219
00221 void clear() { m_write = 0; m_read = 0; }
00222
00224 bool empty() const { return m_write == m_read; }
00225
00227 bool full() const { return ((m_write+1) % m_buffer.size()) == m_read; }
00228
00230
00234 void write(const T& val, bool overwrite=false)
00235 {
00236 size_type new_write_pos = m_write+1;
00237 if (new_write_pos >= m_buffer.size())
00238 {
00239 new_write_pos = 0;
00240 }
00241 if (new_write_pos == m_read)
00242 {
00243 if (overwrite)
00244 {
00245 skip();
00246 }
00247 else
00248 {
00249 throw std::out_of_range("RingBuffer::write: capacity exceeded");
00250 }
00251 }
00252 m_buffer[m_write] = val;
00253 m_write = new_write_pos;
00254 }
00255
00262 void fakeWrite(size_t count);
00263
00265
00269 const T& at(size_type pos) const
00270 {
00271 if (pos < size())
00272 {
00273 pos += m_read;
00274 if (pos >= m_buffer.size())
00275 {
00276 pos -= m_buffer.size();
00277 }
00278 return m_buffer[pos];
00279 }
00280 else
00281 {
00282 throw std::out_of_range("RingBuffer::at: out of range");
00283 }
00284 }
00285
00287
00291 T& at(size_type pos)
00292 {
00293 if (pos < size())
00294 {
00295 pos += m_read;
00296 if (pos >= m_buffer.size())
00297 {
00298 pos -= m_buffer.size();
00299 }
00300 return m_buffer[pos];
00301 }
00302 else
00303 {
00304 throw std::out_of_range("RingBuffer::at: out of range");
00305 }
00306 }
00307
00308 const T& front() const { return at(0); }
00309 T& front() { return at(0); }
00310
00312 void skip()
00313 {
00314 if (m_write == m_read)
00315 {
00316 throw std::out_of_range("RingBuffer::skip: buffer empty");
00317 }
00318 m_read++;
00319 if (m_read >= m_buffer.size())
00320 {
00321 m_read = 0;
00322 }
00323 }
00324
00328 void skip(size_type count);
00329
00331
00333 T read()
00334 {
00335 if (m_write == m_read)
00336 {
00337 throw std::out_of_range("RingBuffer::read: buffer empty");
00338 }
00339 size_type read_pos = m_read;
00340 m_read++;
00341 if (m_read >= m_buffer.size())
00342 {
00343 m_read = 0;
00344 }
00345 return m_buffer[read_pos];
00346 }
00347
00349 inline size_type size() const
00350 {
00351 if (m_write >= m_read)
00352 {
00353 return m_write-m_read;
00354 }
00355 else
00356 {
00357 return m_write+m_buffer.size()-m_read;
00358 }
00359 }
00360
00362 size_type capacity() const { return m_buffer.size()-1; }
00363
00365 size_type reserve() const
00366 {
00367 return capacity() - size();
00368 }
00369
00371
00375 void setCapacity(size_type capacity)
00376 {
00377 size_type old_size = size();
00378 size_type new_size = (capacity < old_size) ? capacity : old_size;
00379 std::vector<T> old_buffer(m_buffer);
00380 size_type old_read = m_read;
00381
00382
00383 m_buffer.resize(capacity+1);
00384
00385 old_read += old_size-new_size;
00386 if (old_read >= old_buffer.size())
00387 {
00388 old_read -= old_buffer.size();
00389 }
00390
00391 for (size_type i=0; i<new_size; i++)
00392 {
00393 m_buffer[i] = old_buffer[old_read];
00394 old_read++;
00395 if (old_read >= old_buffer.size())
00396 {
00397 old_read = 0;
00398 }
00399 }
00400
00401 m_read = 0;
00402 m_write = new_size;
00403 }
00404
00408 ~RingBuffer()
00409 { }
00410
00411 const_iterator begin() const
00412 { return const_iterator(&m_buffer[m_read], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00413 iterator begin()
00414 { return iterator(&m_buffer[m_read], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00415
00416 const_iterator end() const
00417 { return const_iterator(&m_buffer[m_write], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00418 iterator end()
00419 { return iterator(&m_buffer[m_write], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
00420
00436 array_range arrayOne();
00441 const_array_range arrayOne() const;
00442
00447 array_range arrayTwo();
00452 const_array_range arrayTwo() const;
00453
00458 array_range emptyArrayOne();
00463 const_array_range emptyArrayOne() const;
00468 array_range emptyArrayTwo();
00473 const_array_range emptyArrayTwo() const;
00474
00476 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00477
00481 ICL_CORE_VC_DEPRECATE_STYLE void Clear() ICL_CORE_GCC_DEPRECATE_STYLE;
00482
00484
00489 ICL_CORE_VC_DEPRECATE_STYLE
00490 void Write(const T& val, bool overwrite=false) ICL_CORE_GCC_DEPRECATE_STYLE;
00491
00493
00498 ICL_CORE_VC_DEPRECATE_STYLE const T& At(size_type pos) const ICL_CORE_GCC_DEPRECATE_STYLE;
00499
00501
00506 ICL_CORE_VC_DEPRECATE_STYLE T& At(size_type pos) ICL_CORE_GCC_DEPRECATE_STYLE;
00507
00511 ICL_CORE_VC_DEPRECATE_STYLE void Skip() ICL_CORE_GCC_DEPRECATE_STYLE;
00512
00514
00517 ICL_CORE_VC_DEPRECATE_STYLE T Read() ICL_CORE_GCC_DEPRECATE_STYLE;
00518
00522 inline ICL_CORE_VC_DEPRECATE_STYLE size_type Size() const ICL_CORE_GCC_DEPRECATE_STYLE;
00523
00527 ICL_CORE_VC_DEPRECATE_STYLE size_type Capacity() const ICL_CORE_GCC_DEPRECATE_STYLE;
00528
00530
00535 ICL_CORE_VC_DEPRECATE_STYLE void SetCapacity(size_type capacity) ICL_CORE_GCC_DEPRECATE_STYLE;
00536
00537 #endif
00538
00539
00540 private:
00541 std::vector<T> m_buffer;
00542 size_type m_write;
00543 size_type m_read;
00544 };
00545
00546 }
00547
00548 #include "icl_core/RingBuffer.hpp"
00549
00550 #endif