-
Notifications
You must be signed in to change notification settings - Fork 0
/
CircularBuffer.h
149 lines (133 loc) · 3.92 KB
/
CircularBuffer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#ifndef CIRCULARBUFFER_H
#define CIRCULARBUFFER_H
#include <vector>
#include <functional>
namespace util {
template <typename T>
class CircularBuffer {
public:
struct Iterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
Iterator(std::vector<T>& items, size_t startIndex, size_t iterationCount)
: underlyingContainer_(items)
, iterationCount_(0)
, iterationWrapIndex_(items.size() - startIndex)
, iterationMax_(iterationCount)
{
if (iterationCount == 0) {
iter_ = std::end(underlyingContainer_);
} else {
iter_ = std::begin(underlyingContainer_);
std::advance(iter_, startIndex);
}
}
reference operator*() const { return *iter_; }
pointer operator->() { return iter_; }
Iterator& operator++()
{
++iter_;
++iterationCount_;
if (iterationCount_ >= iterationMax_) {
iter_ = std::end(underlyingContainer_);
} else if (iterationCount_ == iterationWrapIndex_) {
iter_ = std::begin(underlyingContainer_);
}
return *this;
}
Iterator operator++(int) { Iterator copy = *this; ++(*this); return copy; }
friend bool operator== (const Iterator& a, const Iterator& b) { return a.iter_ == b.iter_; };
friend bool operator!= (const Iterator& a, const Iterator& b) { return a.iter_ != b.iter_; };
private:
std::vector<T>& underlyingContainer_;
typename std::vector<T>::iterator iter_;
size_t iterationCount_; // counts up sequentially
const size_t iterationWrapIndex_; // count where dataPointer jumps from end of container to start
const size_t iterationMax_; // indication that we should equal end()
};
Iterator begin()
{
bool full = fill_ == items_.size();
size_t startIndex = full ? next_ : 0;
return Iterator(items_, startIndex, fill_);
}
Iterator end()
{
return Iterator(items_, items_.size(), 0);
}
CircularBuffer(size_t capacity)
: items_(capacity, T{})
, next_(0)
, fill_(0)
{
items_.shrink_to_fit();
}
size_t Size() const { return fill_; }
size_t Capacity() const { return items_.size(); }
bool Full() const { return Size() == Capacity(); }
bool Empty() const { return Size() == 0; }
T Oldest() const
{
if (!items_.empty()) {
if (Full()) {
return items_[next_];
} else {
return items_.front();
}
} else {
return {};
}
}
T Newest() const
{
if (!items_.empty()) {
if (next_ > 0) {
return items_[next_ - 1];
} else {
return items_.back();
}
} else {
return {};
}
}
void Resize(size_t size)
{
CircularBuffer copy(items_.size());
copy.items_.swap(items_);
copy.next_ = next_;
copy.fill_ = fill_;
items_.resize(size);
Clear();
for (const T& item : copy) {
PushBack(item);
}
}
void PushBack(const T& item)
{
if (items_.size() > 0) {
items_[next_++] = item;
if (next_ == items_.size()) {
next_ = 0;
}
if (fill_ < items_.size()) {
++fill_;
}
}
}
void Clear()
{
std::fill(std::begin(items_), std::end(items_), T{});
next_ = 0;
fill_ = 0;
}
private:
std::vector<T> items_;
size_t next_;
size_t fill_;
};
} // end namespace util
#endif // CIRCULARBUFFER_H