11#ifndef CIRCULAR_BUFFER_H
22#define CIRCULAR_BUFFER_H
33
4- #include < iostream>
4+ #include < algorithm>
5+ #include < iterator>
56#include < mutex>
67#include < memory>
7- #include < iterator>
8- #include < type_traits>
9- #include < algorithm>
8+ #include < stdexcept>
109#include < utility>
1110
11+
1212template <typename T>
1313class CircularBuffer {
1414private:
@@ -20,13 +20,10 @@ class CircularBuffer {
2020 typedef const T& const_reference;
2121 typedef size_t size_type;
2222 typedef ptrdiff_t difference_type;
23- template <bool isConst>
24- struct BufferIterator ;
25- typedef BufferIterator<false > iterator;
26- typedef BufferIterator<true > const_iterator;
23+ template <bool isConst> struct BufferIterator ;
24+
2725
2826public:
29-
3027 explicit CircularBuffer (size_t size)
3128 :_buff{std::unique_ptr<T[]>(new value_type[size])}, _max_size{size}{}
3229
@@ -83,7 +80,7 @@ class CircularBuffer {
8380 }
8481 return *this ;
8582 }
86-
83+
8784 void push_back (const value_type& data);
8885 void push_back (value_type&& data) noexcept ;
8986 void pop_front ();
@@ -104,40 +101,53 @@ class CircularBuffer {
104101 const_reference at (size_type index) const ;
105102 reference at (size_type index);
106103
104+ typedef BufferIterator<false > iterator;
105+ typedef BufferIterator<true > const_iterator;
106+
107107 iterator begin ();
108108 const_iterator begin () const ;
109109 iterator end ();
110110 const_iterator end () const ;
111+ const_iterator cbegin () const noexcept ;
112+ const_iterator cend () const noexcept ;
113+ iterator rbegin () noexcept ;
114+ const_iterator rbegin () const noexcept ;
115+ iterator rend () noexcept ;
116+ const_iterator rend () const noexcept ;
117+
111118
112119private:
113120 void _increment_bufferstate ();
114121 void _decrement_bufferstate ();
115122 mutable std::mutex _mtx;
116123 std::unique_ptr<value_type[]> _buff;
117-
118124 size_type _head = 0 ;
119125 size_type _tail = 0 ;
120126 size_type _size = 0 ;
121127 size_type _max_size = 0 ;
122-
128+
123129 template <bool isConst = false >
124130 struct BufferIterator {
125131 public:
126-
127- typedef std::random_access_iterator_tag iterator_type;
132+ friend class CircularBuffer <T>;
133+ typedef std::random_access_iterator_tag iterator_category;
134+ typedef ptrdiff_t difference_type;
135+ typedef T value_type;
128136 typedef typename std::conditional<isConst, const value_type&, value_type&>::type reference;
129137 typedef typename std::conditional<isConst, const value_type*, value_type*>::type pointer;
130- typedef CircularBuffer* cbuf_pointer;
131-
138+ typedef typename std::conditional<isConst, const CircularBuffer<value_type>*,
139+ CircularBuffer<value_type>*>::type cbuf_pointer;
140+ private:
132141 cbuf_pointer _ptrToBuffer;
133142 size_type _offset;
134143 size_type _index;
135144 bool _reverse;
136-
137- bool _comparable (const BufferIterator& other){
145+
146+ bool _comparable (const BufferIterator<isConst> & other) const {
138147 return (_ptrToBuffer == other._ptrToBuffer )&&(_reverse == other._reverse );
139148 }
140149
150+ public:
141151 BufferIterator ()
142152 :_ptrToBuffer{nullptr }, _offset{0 }, _index{0 }, _reverse{false }{}
143153
@@ -149,15 +159,16 @@ class CircularBuffer {
149159
150160 reference operator *(){
151161 if (_reverse)
152- return (*_ptrToBuffer)[(_ptrToBuffer->size () - _index)];
162+ return (*_ptrToBuffer)[(_ptrToBuffer->size () - _index - 1 )];
153163 return (*_ptrToBuffer)[_index];
154164 }
155165
156166 pointer operator ->() { return &(operator *()); }
157167
158168 reference operator [](size_type index){
159- this ->_index += index;
160- return this ->operator *();
169+ BufferIterator iter = *this ;
170+ iter._index += index;
171+ return *iter;
161172 }
162173
163174 BufferIterator& operator ++(){
@@ -191,6 +202,7 @@ class CircularBuffer {
191202 rhsiter._index += n;
192203 return rhsiter;
193204 }
205+
194206
195207 BufferIterator& operator +=(difference_type n){
196208 _index += n;
@@ -202,47 +214,51 @@ class CircularBuffer {
202214 return lhsiter;
203215 }
204216
217+ friend difference_type operator -(const BufferIterator& lhsiter, const BufferIterator& rhsiter){
218+
219+ return lhsiter._index - rhsiter._index ;
220+ }
221+
205222 BufferIterator& operator -=(difference_type n){
206223 _index -= n;
207224 return *this ;
208225 }
209226
210- bool operator ==(const BufferIterator& other){
227+ bool operator ==(const BufferIterator& other) const {
211228 if (!_comparable (other))
212229 return false ;
213230 return ((_index == other._index )&&(_offset == other._offset ));
214231 }
215232
216- bool operator !=(const BufferIterator& other){
233+ bool operator !=(const BufferIterator& other) const {
217234 if (!_comparable (other))
218235 return true ;
219236 return ((_index != other._index )||(_offset != other._offset ));
220237 }
221238
222- bool operator <(const BufferIterator& other){
239+ bool operator <(const BufferIterator& other) const {
223240 if (!_comparable (other))
224241 return false ;
225242 return ((_index + _offset)<(other._index +other._offset ));
226243 }
227244
228- bool operator >(const BufferIterator& other){
245+ bool operator >(const BufferIterator& other) const {
229246 if (!_comparable (other))
230247 return false ;
231248 return ((_index + _offset)>(other._index +other._offset ));
232249 }
233250
234- bool operator <=(const BufferIterator& other){
251+ bool operator <=(const BufferIterator& other) const {
235252 if (!_comparable (other))
236253 return false ;
237254 return ((_index + _offset)<=(other._index +other._offset ));
238255 }
239256
240- bool operator >=(const BufferIterator& other){
257+ bool operator >=(const BufferIterator& other) const {
241258 if (!_comparable (other))
242259 return false ;
243260 return ((_index + _offset)>=(other._index +other._offset ));
244261 }
245-
246262 };
247263};
248264
@@ -268,7 +284,7 @@ template<typename T>
268284inline
269285void CircularBuffer<T>::clear(){
270286 std::lock_guard<std::mutex> _lck (_mtx);
271- _head = _tail = _size = _max_size = 0 ;
287+ _head = _tail = _size = 0 ;
272288}
273289
274290template <typename T>
@@ -363,8 +379,8 @@ template<typename T>
363379inline
364380typename CircularBuffer<T>::reference CircularBuffer<T>::operator [](size_t index) {
365381 std::lock_guard<std::mutex> _lck (_mtx);
366- if ((index<0 )||(index>=_max_size ))
367- throw std::out_of_range (" Index is out of Range of buffer capacity " );
382+ if ((index<0 )||(index>=_size ))
383+ throw std::out_of_range (" Index is out of Range of buffer size " );
368384 index += _tail;
369385 index %= _max_size;
370386 return _buff[index];
@@ -374,8 +390,8 @@ template<typename T>
374390inline
375391typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator [](size_t index) const {
376392 std::lock_guard<std::mutex> _lck (_mtx);
377- if ((index<0 )||(index>=_max_size ))
378- throw std::out_of_range (" Index is out of Range of buffer capacity " );
393+ if ((index<0 )||(index>=_size ))
394+ throw std::out_of_range (" Index is out of Range of buffer size " );
379395 index += _tail;
380396 index %= _max_size;
381397 return _buff[index];
@@ -419,7 +435,7 @@ template<typename T>
419435inline
420436typename CircularBuffer<T>::const_iterator CircularBuffer<T>::begin() const {
421437 std::lock_guard<std::mutex> _lck (_mtx);
422- iterator iter;
438+ const_iterator iter;
423439 iter._ptrToBuffer = this ;
424440 iter._offset = _tail;
425441 iter._index = 0 ;
@@ -443,12 +459,84 @@ template<typename T>
443459inline
444460typename CircularBuffer<T>::const_iterator CircularBuffer<T>::end() const {
445461 std::lock_guard<std::mutex> _lck (_mtx);
446- iterator iter;
462+ const_iterator iter;
447463 iter._ptrToBuffer = this ;
448464 iter._offset = _tail;
449465 iter._index = _size;
450466 iter._reverse = false ;
451467 return iter;
452468}
453469
470+ template <typename T>
471+ inline
472+ typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cbegin() const noexcept {
473+ std::lock_guard<std::mutex> _lck (_mtx);
474+ const_iterator iter;
475+ iter._ptrToBuffer = this ;
476+ iter._offset = _tail;
477+ iter._index = 0 ;
478+ iter._reverse = false ;
479+ return iter;
480+ }
481+
482+ template <typename T>
483+ inline
484+ typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cend() const noexcept {
485+ std::lock_guard<std::mutex> _lck (_mtx);
486+ const_iterator iter;
487+ iter._ptrToBuffer = this ;
488+ iter._offset = _tail;
489+ iter._index = _size;
490+ iter._reverse = false ;
491+ return iter;
492+ }
493+
494+ template <typename T>
495+ inline
496+ typename CircularBuffer<T>::iterator CircularBuffer<T>::rbegin() noexcept {
497+ std::lock_guard<std::mutex> _lck (_mtx);
498+ iterator iter;
499+ iter._ptrToBuffer = this ;
500+ iter._offset = _tail;
501+ iter._index = 0 ;
502+ iter._reverse = true ;
503+ return iter;
504+ }
505+
506+ template <typename T>
507+ inline
508+ typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rbegin() const noexcept {
509+ std::lock_guard<std::mutex> _lck (_mtx);
510+ const_iterator iter;
511+ iter._ptrToBuffer = this ;
512+ iter._offset = _tail;
513+ iter._index = 0 ;
514+ iter._reverse = true ;
515+ return iter;
516+ }
517+
518+ template <typename T>
519+ inline
520+ typename CircularBuffer<T>::iterator CircularBuffer<T>::rend() noexcept {
521+ std::lock_guard<std::mutex> _lck (_mtx);
522+ iterator iter;
523+ iter._ptrToBuffer = this ;
524+ iter._offset = _tail;
525+ iter._index = _size;
526+ iter._reverse = true ;
527+ return iter;
528+ }
529+
530+ template <typename T>
531+ inline
532+ typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rend() const noexcept {
533+ std::lock_guard<std::mutex> _lck (_mtx);
534+ const_iterator iter;
535+ iter._ptrToBuffer = this ;
536+ iter._offset = _tail;
537+ iter._index = _size;
538+ iter._reverse = true ;
539+ return iter;
540+ }
541+
454542#endif /* CIRCULAR_BUFFER_H */
0 commit comments