1
1
#ifndef CIRCULAR_BUFFER_H
2
2
#define CIRCULAR_BUFFER_H
3
3
4
- #include < iostream>
4
+ #include < algorithm>
5
+ #include < iterator>
5
6
#include < mutex>
6
7
#include < memory>
7
- #include < iterator>
8
- #include < type_traits>
9
- #include < algorithm>
8
+ #include < stdexcept>
10
9
#include < utility>
11
10
11
+
12
12
template <typename T>
13
13
class CircularBuffer {
14
14
private:
@@ -20,13 +20,10 @@ class CircularBuffer {
20
20
typedef const T& const_reference;
21
21
typedef size_t size_type;
22
22
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
+
27
25
28
26
public:
29
-
30
27
explicit CircularBuffer (size_t size)
31
28
:_buff{std::unique_ptr<T[]>(new value_type[size])}, _max_size{size}{}
32
29
@@ -83,7 +80,7 @@ class CircularBuffer {
83
80
}
84
81
return *this ;
85
82
}
86
-
83
+
87
84
void push_back (const value_type& data);
88
85
void push_back (value_type&& data) noexcept ;
89
86
void pop_front ();
@@ -104,40 +101,53 @@ class CircularBuffer {
104
101
const_reference at (size_type index) const ;
105
102
reference at (size_type index);
106
103
104
+ typedef BufferIterator<false > iterator;
105
+ typedef BufferIterator<true > const_iterator;
106
+
107
107
iterator begin ();
108
108
const_iterator begin () const ;
109
109
iterator end ();
110
110
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
+
111
118
112
119
private:
113
120
void _increment_bufferstate ();
114
121
void _decrement_bufferstate ();
115
122
mutable std::mutex _mtx;
116
123
std::unique_ptr<value_type[]> _buff;
117
-
118
124
size_type _head = 0 ;
119
125
size_type _tail = 0 ;
120
126
size_type _size = 0 ;
121
127
size_type _max_size = 0 ;
122
-
128
+
123
129
template <bool isConst = false >
124
130
struct BufferIterator {
125
131
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;
128
136
typedef typename std::conditional<isConst, const value_type&, value_type&>::type reference;
129
137
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:
132
141
cbuf_pointer _ptrToBuffer;
133
142
size_type _offset;
134
143
size_type _index;
135
144
bool _reverse;
136
-
137
- bool _comparable (const BufferIterator& other){
145
+
146
+ bool _comparable (const BufferIterator<isConst> & other) const {
138
147
return (_ptrToBuffer == other._ptrToBuffer )&&(_reverse == other._reverse );
139
148
}
140
149
150
+ public:
141
151
BufferIterator ()
142
152
:_ptrToBuffer{nullptr }, _offset{0 }, _index{0 }, _reverse{false }{}
143
153
@@ -149,15 +159,16 @@ class CircularBuffer {
149
159
150
160
reference operator *(){
151
161
if (_reverse)
152
- return (*_ptrToBuffer)[(_ptrToBuffer->size () - _index)];
162
+ return (*_ptrToBuffer)[(_ptrToBuffer->size () - _index - 1 )];
153
163
return (*_ptrToBuffer)[_index];
154
164
}
155
165
156
166
pointer operator ->() { return &(operator *()); }
157
167
158
168
reference operator [](size_type index){
159
- this ->_index += index;
160
- return this ->operator *();
169
+ BufferIterator iter = *this ;
170
+ iter._index += index;
171
+ return *iter;
161
172
}
162
173
163
174
BufferIterator& operator ++(){
@@ -191,6 +202,7 @@ class CircularBuffer {
191
202
rhsiter._index += n;
192
203
return rhsiter;
193
204
}
205
+
194
206
195
207
BufferIterator& operator +=(difference_type n){
196
208
_index += n;
@@ -202,47 +214,51 @@ class CircularBuffer {
202
214
return lhsiter;
203
215
}
204
216
217
+ friend difference_type operator -(const BufferIterator& lhsiter, const BufferIterator& rhsiter){
218
+
219
+ return lhsiter._index - rhsiter._index ;
220
+ }
221
+
205
222
BufferIterator& operator -=(difference_type n){
206
223
_index -= n;
207
224
return *this ;
208
225
}
209
226
210
- bool operator ==(const BufferIterator& other){
227
+ bool operator ==(const BufferIterator& other) const {
211
228
if (!_comparable (other))
212
229
return false ;
213
230
return ((_index == other._index )&&(_offset == other._offset ));
214
231
}
215
232
216
- bool operator !=(const BufferIterator& other){
233
+ bool operator !=(const BufferIterator& other) const {
217
234
if (!_comparable (other))
218
235
return true ;
219
236
return ((_index != other._index )||(_offset != other._offset ));
220
237
}
221
238
222
- bool operator <(const BufferIterator& other){
239
+ bool operator <(const BufferIterator& other) const {
223
240
if (!_comparable (other))
224
241
return false ;
225
242
return ((_index + _offset)<(other._index +other._offset ));
226
243
}
227
244
228
- bool operator >(const BufferIterator& other){
245
+ bool operator >(const BufferIterator& other) const {
229
246
if (!_comparable (other))
230
247
return false ;
231
248
return ((_index + _offset)>(other._index +other._offset ));
232
249
}
233
250
234
- bool operator <=(const BufferIterator& other){
251
+ bool operator <=(const BufferIterator& other) const {
235
252
if (!_comparable (other))
236
253
return false ;
237
254
return ((_index + _offset)<=(other._index +other._offset ));
238
255
}
239
256
240
- bool operator >=(const BufferIterator& other){
257
+ bool operator >=(const BufferIterator& other) const {
241
258
if (!_comparable (other))
242
259
return false ;
243
260
return ((_index + _offset)>=(other._index +other._offset ));
244
261
}
245
-
246
262
};
247
263
};
248
264
@@ -268,7 +284,7 @@ template<typename T>
268
284
inline
269
285
void CircularBuffer<T>::clear(){
270
286
std::lock_guard<std::mutex> _lck (_mtx);
271
- _head = _tail = _size = _max_size = 0 ;
287
+ _head = _tail = _size = 0 ;
272
288
}
273
289
274
290
template <typename T>
@@ -363,8 +379,8 @@ template<typename T>
363
379
inline
364
380
typename CircularBuffer<T>::reference CircularBuffer<T>::operator [](size_t index) {
365
381
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 " );
368
384
index += _tail;
369
385
index %= _max_size;
370
386
return _buff[index];
@@ -374,8 +390,8 @@ template<typename T>
374
390
inline
375
391
typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator [](size_t index) const {
376
392
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 " );
379
395
index += _tail;
380
396
index %= _max_size;
381
397
return _buff[index];
@@ -419,7 +435,7 @@ template<typename T>
419
435
inline
420
436
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::begin() const {
421
437
std::lock_guard<std::mutex> _lck (_mtx);
422
- iterator iter;
438
+ const_iterator iter;
423
439
iter._ptrToBuffer = this ;
424
440
iter._offset = _tail;
425
441
iter._index = 0 ;
@@ -443,12 +459,84 @@ template<typename T>
443
459
inline
444
460
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::end() const {
445
461
std::lock_guard<std::mutex> _lck (_mtx);
446
- iterator iter;
462
+ const_iterator iter;
447
463
iter._ptrToBuffer = this ;
448
464
iter._offset = _tail;
449
465
iter._index = _size;
450
466
iter._reverse = false ;
451
467
return iter;
452
468
}
453
469
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
+
454
542
#endif /* CIRCULAR_BUFFER_H */
0 commit comments