Skip to content

Commit

Permalink
Merge pull request #17 from vinitjames/develop
Browse files Browse the repository at this point in the history
Merging first release version
  • Loading branch information
vinitjames authored May 7, 2021
2 parents bd60506 + 067eb60 commit 9f75274
Show file tree
Hide file tree
Showing 6 changed files with 733 additions and 39 deletions.
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 [email protected]"
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

0 comments on commit 9f75274

Please sign in to comment.