Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 123 additions & 35 deletions circular_buffer.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H

#include <iostream>
#include <algorithm>
#include <iterator>
#include <mutex>
#include <memory>
#include <iterator>
#include <type_traits>
#include <algorithm>
#include <stdexcept>
#include <utility>


template<typename T>
class CircularBuffer {
private:
Expand All @@ -20,13 +20,10 @@ class CircularBuffer {
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template <bool isConst>
struct BufferIterator;
typedef BufferIterator<false> iterator;
typedef BufferIterator<true> const_iterator;
template <bool isConst> struct BufferIterator;


public:

explicit CircularBuffer(size_t size)
:_buff{std::unique_ptr<T[]>(new value_type[size])}, _max_size{size}{}

Expand Down Expand Up @@ -83,7 +80,7 @@ class CircularBuffer {
}
return *this;
}

void push_back(const value_type& data);
void push_back(value_type&& data) noexcept;
void pop_front();
Expand All @@ -104,40 +101,53 @@ class CircularBuffer {
const_reference at(size_type index) const;
reference at(size_type index);

typedef BufferIterator<false> iterator;
typedef BufferIterator<true> const_iterator;

iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
iterator rbegin() noexcept;
const_iterator rbegin() const noexcept;
iterator rend() noexcept;
const_iterator rend() const noexcept;


private:
void _increment_bufferstate();
void _decrement_bufferstate();
mutable std::mutex _mtx;
std::unique_ptr<value_type[]> _buff;

size_type _head = 0;
size_type _tail = 0;
size_type _size = 0;
size_type _max_size = 0;

template<bool isConst = false>
struct BufferIterator{
public:

typedef std::random_access_iterator_tag iterator_type;
friend class CircularBuffer<T>;
typedef std::random_access_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef typename std::conditional<isConst, const value_type&, value_type&>::type reference;
typedef typename std::conditional<isConst, const value_type*, value_type*>::type pointer;
typedef CircularBuffer* cbuf_pointer;

typedef typename std::conditional<isConst, const CircularBuffer<value_type>*,
CircularBuffer<value_type>*>::type cbuf_pointer;
private:
cbuf_pointer _ptrToBuffer;
size_type _offset;
size_type _index;
bool _reverse;

bool _comparable(const BufferIterator& other){
bool _comparable(const BufferIterator<isConst>& other) const{
return (_ptrToBuffer == other._ptrToBuffer)&&(_reverse == other._reverse);
}

public:
BufferIterator()
:_ptrToBuffer{nullptr}, _offset{0}, _index{0}, _reverse{false}{}

Expand All @@ -149,15 +159,16 @@ class CircularBuffer {

reference operator*(){
if(_reverse)
return (*_ptrToBuffer)[(_ptrToBuffer->size() - _index)];
return (*_ptrToBuffer)[(_ptrToBuffer->size() - _index - 1)];
return (*_ptrToBuffer)[_index];
}

pointer operator->() { return &(operator*()); }

reference operator[](size_type index){
this->_index += index;
return this->operator*();
BufferIterator iter = *this;
iter._index += index;
return *iter;
}

BufferIterator& operator++(){
Expand Down Expand Up @@ -191,6 +202,7 @@ class CircularBuffer {
rhsiter._index += n;
return rhsiter;
}


BufferIterator& operator+=(difference_type n){
_index += n;
Expand All @@ -202,47 +214,51 @@ class CircularBuffer {
return lhsiter;
}

friend difference_type operator-(const BufferIterator& lhsiter, const BufferIterator& rhsiter){

return lhsiter._index - rhsiter._index;
}

BufferIterator& operator-=(difference_type n){
_index -= n;
return *this;
}

bool operator==(const BufferIterator& other){
bool operator==(const BufferIterator& other) const{
if (!_comparable(other))
return false;
return ((_index == other._index)&&(_offset == other._offset));
}

bool operator!=(const BufferIterator& other){
bool operator!=(const BufferIterator& other) const{
if (!_comparable(other))
return true;
return ((_index != other._index)||(_offset != other._offset));
}

bool operator<(const BufferIterator& other){
bool operator<(const BufferIterator& other) const {
if (!_comparable(other))
return false;
return ((_index + _offset)<(other._index+other._offset));
}

bool operator>(const BufferIterator& other){
bool operator>(const BufferIterator& other) const{
if (!_comparable(other))
return false;
return ((_index + _offset)>(other._index+other._offset));
}

bool operator<=(const BufferIterator& other){
bool operator<=(const BufferIterator& other) const {
if (!_comparable(other))
return false;
return ((_index + _offset)<=(other._index+other._offset));
}

bool operator>=(const BufferIterator& other){
bool operator>=(const BufferIterator& other) const {
if (!_comparable(other))
return false;
return ((_index + _offset)>=(other._index+other._offset));
}

};
};

Expand All @@ -268,7 +284,7 @@ template<typename T>
inline
void CircularBuffer<T>::clear(){
std::lock_guard<std::mutex> _lck(_mtx);
_head = _tail = _size = _max_size = 0;
_head = _tail = _size = 0;
}

template<typename T>
Expand Down Expand Up @@ -363,8 +379,8 @@ template<typename T>
inline
typename CircularBuffer<T>::reference CircularBuffer<T>::operator[](size_t index) {
std::lock_guard<std::mutex> _lck(_mtx);
if((index<0)||(index>=_max_size))
throw std::out_of_range("Index is out of Range of buffer capacity");
if((index<0)||(index>=_size))
throw std::out_of_range("Index is out of Range of buffer size");
index += _tail;
index %= _max_size;
return _buff[index];
Expand All @@ -374,8 +390,8 @@ template<typename T>
inline
typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator[](size_t index) const {
std::lock_guard<std::mutex> _lck(_mtx);
if((index<0)||(index>=_max_size))
throw std::out_of_range("Index is out of Range of buffer capacity");
if((index<0)||(index>=_size))
throw std::out_of_range("Index is out of Range of buffer size");
index += _tail;
index %= _max_size;
return _buff[index];
Expand Down Expand Up @@ -419,7 +435,7 @@ template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::begin() const{
std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
Expand All @@ -443,12 +459,84 @@ template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::end() const{
std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = false;
return iter;
}

template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cbegin() const noexcept{
std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = false;
return iter;
}

template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cend() const noexcept{
std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = false;
return iter;
}

template<typename T>
inline
typename CircularBuffer<T>::iterator CircularBuffer<T>::rbegin() noexcept{
std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = true;
return iter;
}

template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rbegin() const noexcept{
std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = 0;
iter._reverse = true;
return iter;
}

template<typename T>
inline
typename CircularBuffer<T>::iterator CircularBuffer<T>::rend() noexcept{
std::lock_guard<std::mutex> _lck(_mtx);
iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = true;
return iter;
}

template<typename T>
inline
typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rend() const noexcept{
std::lock_guard<std::mutex> _lck(_mtx);
const_iterator iter;
iter._ptrToBuffer = this;
iter._offset = _tail;
iter._index = _size;
iter._reverse = true;
return iter;
}

#endif /* CIRCULAR_BUFFER_H */
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

class CircularBufferConan(ConanFile):
name = "circular_buffer"
version = "0.0.1"
version = "0.1.0"
license = "MIT License"
author = "vinit james vinit.james24@gmail.com"
url = "https://github.com/vinitjames/circularbuffer"
Expand Down
20 changes: 17 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,23 @@ add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)

add_executable(circularbuffer_int circularbuffer_int.cpp)
target_link_libraries(circularbuffer_int
add_executable(simple_int_test simple_int_test.cpp)
target_link_libraries(simple_int_test
circularbuffer
gtest_main
)
add_test(NAME test_circularbuffer_int COMMAND circularbuffer_int)
add_test(NAME simple_int_test COMMAND simple_int_test)

add_executable(member_func_test member_func_test.cpp)
target_link_libraries(member_func_test
circularbuffer
gtest_main
)
add_test(NAME member_func_test COMMAND member_func_test)

add_executable(iterator_test iterator_test.cpp)
target_link_libraries(iterator_test
circularbuffer
gtest_main
)
add_test(NAME iterator_test COMMAND iterator_test)
Loading