Skip to content

Instantly share code, notes, and snippets.

@SteveBronder
Created September 27, 2022 16:50
Show Gist options
  • Save SteveBronder/456be1f1364f065e0f83e6962ff1ee51 to your computer and use it in GitHub Desktop.
Save SteveBronder/456be1f1364f065e0f83e6962ff1ee51 to your computer and use it in GitHub Desktop.
#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