Created
September 27, 2022 16:50
-
-
Save SteveBronder/456be1f1364f065e0f83e6962ff1ee51 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <iostream> | |
#include <type_traits> | |
#include <utility> | |
template <typename T> | |
struct circular_buffer { | |
using value_type = std::decay_t<T>; | |
using pointer = std::decay_t<T>*; | |
pointer data_; // value array | |
pointer first_; // virtual first position of buffer | |
pointer last_; // virtual end position of buffer | |
pointer end_; // true end of buffer | |
std::size_t size_; // Current virtual size | |
std::size_t max_size_; // max size | |
inline std::size_t size() const noexcept { return size_; } | |
inline std::size_t max_size() const noexcept { return max_size_; } | |
inline bool empty() const noexcept { return size_ == 0; } | |
inline bool full() const noexcept { return size_ == max_size_; } | |
circular_buffer(std::size_t max_size) | |
: data_(new value_type[max_size]), | |
first_(data_), | |
last_(data_), | |
end_(data_ + max_size), | |
size_(0), | |
max_size_(max_size) {} | |
~circular_buffer() { delete[] data_; } | |
inline void set_capacity(std::size_t new_size) noexcept { | |
if (new_size == max_size_) { | |
return; | |
} else { | |
pointer new_data = new value_type[new_size]; | |
for (std::size_t i = 0; i < size_; ++i) { | |
new_data[i] = data_[i]; | |
} | |
delete[] data_; | |
data_ = new_data; | |
} | |
} | |
/** | |
* Once we hit the end, roll around to the bottom | |
*/ | |
inline void increment(pointer& p) noexcept { | |
if (++p == end_) { | |
p = data_; | |
} | |
} | |
/** | |
* When not full, go as normal. | |
* Once it's full we set first to last | |
* to signify that we've rolled and to help with | |
* indexing later. | |
*/ | |
template <typename TT> | |
inline void push_back(TT&& item) noexcept { | |
if (this->full()) { | |
*last_ = std::forward<TT>(item); | |
increment(last_); | |
first_ = last_; | |
} else { | |
*last_ = std::forward<TT>(item); | |
increment(last_); | |
++size_; | |
} | |
} | |
/** | |
* Access elements in the order they were pushed. | |
* 0 is the least recent element. | |
*/ | |
inline T& operator[](std::size_t idx) noexcept { | |
return *(first_ + (idx < (end_ - first_) ? idx : idx - (end_ - data_))); | |
} | |
}; | |
int main() { | |
circular_buffer<int> xx(5); | |
xx.push_back(0); | |
xx.push_back(1); | |
xx.push_back(2); | |
xx.push_back(3); | |
xx.push_back(4); | |
xx.push_back(5); | |
xx.push_back(6); | |
for (int i = 0; i < xx.size_; ++i) { | |
std::cout << xx.data_[i] << ", "; | |
} | |
std::cout << "\n"; | |
for (int i = 0; i < xx.size_; ++i) { | |
std::cout << xx[i] << ", "; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment