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(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
00379 m_buffer.resize(capacity+1);
00380
00381 old_read += old_size-new_size;
00382 if (old_read >= old_buffer.size())
00383 {
00384 old_read -= old_buffer.size();
00385 }
00386
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
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