Skip to content

Instantly share code, notes, and snippets.

@dgodfrey206
Created September 27, 2016 19:10
Show Gist options
  • Save dgodfrey206/be9dfa6c42bc9548c1bb4e5fdbba7a4a to your computer and use it in GitHub Desktop.
Save dgodfrey206/be9dfa6c42bc9548c1bb4e5fdbba7a4a to your computer and use it in GitHub Desktop.
Test
#include <stdexcept>
#include <iostream>
#include <memory>
#include <cstring>
#include <cmath>
using namespace std;
template<class T>
class RingBuffer;
template<class V>struct X;
template<class T>
struct wrap_iterator {
using iterator=wrap_iterator;
template<class I>struct range_t{I b,e;};
range_t<size_t> r;
T& obj;
auto& operator*(){return obj.buffer[r.b];}
auto const& operator*()const{return obj.buffer[r.b];}
iterator operator+(int i) const {
iterator copy(*this);
return (copy.r.b + 1) % copy.r.e;
}
iterator operator-(int i) const {
iterator copy(*this);
if (copy.r.b == 0)
copy.r.b = copy.r.e - 1;
else
copy.r.b--;
return copy;
}
iterator& operator++() {
r.b = (r.b + 1) % r.e;
return *this;
}
iterator operator++(int) {
iterator copy(*this);
operator++();
return copy;
}
friend bool operator==(iterator const&lhs,iterator const&rhs){
return lhs.r.b==rhs.r.b;
}
friend bool operator!=(iterator const&lhs,iterator const&rhs){
return !(lhs==rhs);
}
};
template<class I,class T>
auto make_iterator(I beg, I end,T&& obj) {
using iterator=::wrap_iterator<remove_reference_t<T>>;
return iterator{typename iterator::template range_t<I>
{move(beg),
move(end)},
obj};
}
template<class T>
class RingBuffer {
friend struct wrap_iterator<RingBuffer<T>>;
friend struct wrap_iterator<RingBuffer<T> const>;
friend struct wrap_iterator<RingBuffer<T> const&>;
public:
RingBuffer() = delete;
RingBuffer(size_t);
RingBuffer(size_t, T const&);
// modifiers
T get() const;
void push_back(T const&);
void pop_back();
void pop_front();
// access
T& front();
T const& front() const;
T& back();
T const& back() const;
// iterators
auto begin();
auto const begin() const;
auto end();
auto const end() const;
// size
size_t size() const;
bool empty() const;
bool full() const;
private:
void push_back(T const&, true_type);
void push_back(T const&, false_type);
void set_next_write_position() const;
void set_next_read_position() const;
private:
unique_ptr<T[]> buffer = nullptr;
mutable size_t read, write, length, capacity = 0;
};
template<class T>
RingBuffer<T>::RingBuffer(size_t capacity)
: buffer(make_unique<T[]>(capacity+1))
, read(0)
, write(0)
, length(0)
, capacity(capacity+1)
{}
template<class T>
RingBuffer<T>::RingBuffer(size_t capacity, T const& value)
: RingBuffer(capacity)
{
for (int i = 0; i < capacity; ++i)
push_back(value);
}
template<class T>
void RingBuffer<T>::push_back(T const& value) {
if (!full()) {
push_back(value, is_trivially_copyable<T>{});
write = (write + 1) % capacity;
++length;
}
}
template<class T>
void RingBuffer<T>::push_back(T const& value, true_type) {
memcpy(reinterpret_cast<void*>(&buffer[write]), reinterpret_cast<void*>(const_cast<T*>(&value)), sizeof(value));
}
template<class T>
void RingBuffer<T>::push_back(T const& value, false_type) {
buffer[write] = value;
}
template<class T>
T RingBuffer<T>::get() const {
if (!empty()) {
T tmp = buffer[read];
read = (read + 1) % capacity;
--length;
return tmp;
}
throw logic_error("empty buffer");
}
template<class T>
void RingBuffer<T>::pop_front() {
if (!empty()) {
read = (read + 1) % capacity;
--length;
}
else {
throw logic_error("empty");
}
}
template<class T>
void RingBuffer<T>::pop_back() {
if (!empty()) {
if (--write < 0) write = length - 1;
--length;
}
throw logic_error("empty");
}
template<class T>
auto const RingBuffer<T>::begin() const {
return make_iterator(read,size(),*this);
}
template<class T>
auto RingBuffer<T>::begin() {
return make_iterator(read,size(),*this);
}
template<class T>
auto const RingBuffer<T>::end() const {
return make_iterator(write,size(),*this);
}
template<class T>
auto RingBuffer<T>::end() {
return make_iterator(write,size(),*this);
}
template<class T>
T const& RingBuffer<T>::front() const {
return *begin();
}
template<class T>
T& RingBuffer<T>::front() {
return *begin();
}
template<class T>
T& RingBuffer<T>::back() {
if (size() <= 1)
return *begin();
return *(end() - 1);
}
template<class T>
T const& RingBuffer<T>::back() const {
return const_cast<RingBuffer<T>&>(*this).back();
}
template<class T>
size_t RingBuffer<T>::size() const {
return length;
}
template<class T>
bool RingBuffer<T>::full() const {
return read == (write + 1) % capacity;
}
template<class T>
bool RingBuffer<T>::empty() const {
return length == 0;
}
void print(RingBuffer<int>const&rb){
for(auto x:rb)cout<<3<<' ';
cout<<'\n';
}
template<class T>
void f(T& x){
cout<<x.r.b<<' '<<*x<<'\n';
x++;
}
int main() {
RingBuffer<int> rb(10);
int i;
for(i=1;i<=10;++i)rb.push_back(i);
//rb.pop_front();
auto it=rb.begin();
f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);f(it);
cout<<rb.end().r.b<<' '<<it.r.b;
//print(rb);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment