Loading...
Searching...
No Matches
circular_buffer.h
Go to the documentation of this file.
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2020 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef ETL_CIRCULAR_BUFFER_INCLUDED
#define ETL_CIRCULAR_BUFFER_INCLUDED
#include "platform.h"
#include "error_handler.h"
#include "exception.h"
#include "initializer_list.h"
#include "iterator.h"
#include "memory.h"
#include "memory_model.h"
#include "static_assert.h"
#include "type_traits.h"
#include "vector.h"
namespace etl
{
//***************************************************************************
//***************************************************************************
class circular_buffer_exception : public etl::exception
{
public:
circular_buffer_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class circular_buffer_empty : public etl::circular_buffer_exception
{
public:
circular_buffer_empty(string_type file_name_, numeric_type line_number_)
: etl::circular_buffer_exception(ETL_ERROR_TEXT("circular_buffer:empty", ETL_CIRCULAR_BUFFER_FILE_ID"A"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class circular_buffer_incompatible_type : public circular_buffer_exception
{
public:
circular_buffer_incompatible_type(string_type file_name_, numeric_type line_number_)
: circular_buffer_exception(ETL_ERROR_TEXT("circular_buffer:type", ETL_CIRCULAR_BUFFER_FILE_ID"B"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class circular_buffer_base
{
public:
typedef size_t size_type;
//*************************************************************************
size_type size() const
{
return (in >= out) ? in - out : buffer_size - (out - in);
}
//*************************************************************************
bool empty() const
{
return in == out;
}
//*************************************************************************
bool full() const
{
size_t i = in;
++i;
if (i == buffer_size) ETL_UNLIKELY
{
i = 0U;
}
return i == out;
}
//*************************************************************************
size_type available() const
{
return max_size() - size();
}
//*************************************************************************
size_type max_size() const
{
return buffer_size - 1U;
}
//*************************************************************************
size_type capacity() const
{
return buffer_size - 1U;
}
protected:
//*************************************************************************
circular_buffer_base(size_type buffer_size_)
: buffer_size(buffer_size_)
, in(0U)
, out(0U)
{
}
//*************************************************************************
void increment_in()
{
++in;
if (in == buffer_size) ETL_UNLIKELY
{
in = 0U;
}
}
//*************************************************************************
void increment_out()
{
++out;
if (out == buffer_size) ETL_UNLIKELY
{
out = 0U;
}
}
size_type buffer_size;
size_type in;
size_type out;
ETL_DECLARE_DEBUG_COUNT;
};
//***************************************************************************
//***************************************************************************
template <typename T>
class icircular_buffer : public circular_buffer_base
{
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
#if ETL_USING_CPP11
typedef T&& rvalue_reference;
#endif
typedef T* pointer;
typedef const T* const_pointer;
typedef typename etl::iterator_traits<pointer>::difference_type difference_type;
//*************************************************************************
//*************************************************************************
class iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, T>
{
public:
friend class icircular_buffer;
//*************************************************************************
//*************************************************************************
iterator()
: picb(ETL_NULLPTR)
, current(0U)
{
}
//*************************************************************************
//*************************************************************************
iterator(const iterator& other)
: picb(other.picb)
, current(other.current)
{
}
//*************************************************************************
//*************************************************************************
iterator& operator=(const iterator& other)
{
picb = other.picb;
current = other.current;
return *this;
}
//*************************************************************************
//*************************************************************************
reference operator*() const
{
return picb->pbuffer[current];
}
//*************************************************************************
//*************************************************************************
pointer operator->() const
{
return &picb->pbuffer[current];
}
//*************************************************************************
//*************************************************************************
reference operator[](size_t index)
{
return picb->pbuffer[(current + index) % picb->buffer_size];
}
//*************************************************************************
//*************************************************************************
const_reference operator[](size_t index) const
{
return picb->pbuffer[(current + index) % picb->buffer_size];
}
//*************************************************************************
//*************************************************************************
iterator& operator++()
{
++current;
// Did we reach the end of the buffer?
if (current == picb->buffer_size)
{
current = 0U;
}
return (*this);
}
//*************************************************************************
//*************************************************************************
iterator operator++(int)
{
iterator original(*this);
++(*this);
return (original);
}
//*************************************************************************
//*************************************************************************
iterator& operator--()
{
// Are we at the end of the buffer?
if (current == 0U)
{
current = picb->buffer_size - 1;
}
else
{
--current;
}
return (*this);
}
//*************************************************************************
//*************************************************************************
iterator operator--(int)
{
iterator original(*this);
--(*this);
return (original);
}
//*************************************************************************
//*************************************************************************
iterator& operator+=(int n)
{
current += size_type(static_cast<int>(picb->buffer_size) + n);
current %= picb->buffer_size;
return (*this);
}
//*************************************************************************
//*************************************************************************
iterator& operator-=(int n)
{
return (this->operator+=(-n));
}
//*************************************************************************
//*************************************************************************
friend iterator operator+(const iterator& lhs, int n)
{
iterator temp = lhs;
temp += n;
return temp;
}
//*************************************************************************
//*************************************************************************
friend iterator operator+(int n, const iterator& rhs)
{
iterator temp = rhs;
temp += n;
return temp;
}
//*************************************************************************
//*************************************************************************
friend iterator operator-(const iterator& lhs, int n)
{
iterator temp = lhs;
temp -= n;
return temp;
}
//*************************************************************************
//*************************************************************************
friend bool operator==(const iterator& lhs, const iterator& rhs)
{
return (lhs.current == rhs.current);
}
//*************************************************************************
//*************************************************************************
friend bool operator!=(const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
//***************************************************
friend bool operator<(const iterator& lhs, const iterator& rhs)
{
const difference_type lhs_index = lhs.get_index();
const difference_type rhs_index = rhs.get_index();
const difference_type reference_index = lhs.container().begin().get_index();
const difference_type buffer_size = static_cast<difference_type>(lhs.container().max_size() + 1UL);
const difference_type lhs_distance = (lhs_index < reference_index) ? buffer_size + lhs_index - reference_index : lhs_index - reference_index;
const difference_type rhs_distance = (rhs_index < reference_index) ? buffer_size + rhs_index - reference_index : rhs_index - reference_index;
return lhs_distance < rhs_distance;
}
//***************************************************
friend bool operator<=(const iterator& lhs, const iterator& rhs)
{
return !(lhs > rhs);
}
//***************************************************
friend bool operator>(const iterator& lhs, const iterator& rhs)
{
return (rhs < lhs);
}
//***************************************************
friend bool operator>=(const iterator& lhs, const iterator& rhs)
{
return !(lhs < rhs);
}
//***************************************************
difference_type get_index() const
{
return static_cast<difference_type>(current);
}
//***************************************************
const icircular_buffer& container() const
{
return *picb;
}
//***************************************************
pointer get_buffer() const
{
return picb->pbuffer;
}
protected:
//***************************************************
difference_type distance(difference_type firstIndex, difference_type index) const
{
if (index < firstIndex)
{
return picb->buffer_size + current - firstIndex;
}
else
{
return index - firstIndex;
}
}
//*************************************************************************
//*************************************************************************
iterator(const icircular_buffer<T>* picb_, size_type current_)
: picb(picb_)
, current(current_)
{
}
private:
const icircular_buffer<T>* picb;
size_type current;
};
//*************************************************************************
//*************************************************************************
class const_iterator : public etl::iterator<ETL_OR_STD::random_access_iterator_tag, const T>
{
public:
friend class icircular_buffer;
//*************************************************************************
//*************************************************************************
const_iterator()
: picb(ETL_NULLPTR)
, current(0U)
{
}
//*************************************************************************
//*************************************************************************
const_iterator(const typename icircular_buffer::iterator& other)
: picb(other.picb)
, current(other.current)
{
}
//*************************************************************************
//*************************************************************************
const_iterator(const const_iterator& other)
: picb(other.picb)
, current(other.current)
{
}
//*************************************************************************
//*************************************************************************
const_iterator& operator=(const typename icircular_buffer::iterator& other)
{
picb = other.picb;
current = other.current;
return *this;
}
//*************************************************************************
//*************************************************************************
const_iterator& operator=(const const_iterator& other)
{
picb = other.picb;
current = other.current;
return *this;
}
//*************************************************************************
//*************************************************************************
const_reference operator*() const
{
return picb->pbuffer[current];
}
//*************************************************************************
//*************************************************************************
const_pointer operator->() const
{
return &(picb->pbuffer[current]);
}
//*************************************************************************
//*************************************************************************
const_reference operator[](size_t index) const
{
return picb->pbuffer[(current + index) % picb->buffer_size];
}
//*************************************************************************
//*************************************************************************
const_iterator& operator++()
{
++current;
// Did we reach the end of the buffer?
if (current == picb->buffer_size)
{
current = 0U;
}
return (*this);
}
//*************************************************************************
//*************************************************************************
const_iterator operator++(int)
{
const_iterator original(*this);
++(*this);
return (original);
}
//*************************************************************************
//*************************************************************************
const_iterator& operator--()
{
// Are we at the end of the buffer?
if (current == 0U)
{
current = picb->buffer_size - 1;
}
else
{
--current;
}
return (*this);
}
//*************************************************************************
//*************************************************************************
const_iterator operator--(int)
{
const_iterator original(*this);
--(*this);
return (original);
}
//*************************************************************************
//*************************************************************************
const_iterator& operator+=(int n)
{
current += size_type(static_cast<int>(picb->buffer_size) + n);
current %= picb->buffer_size;
return (*this);
}
//*************************************************************************
//*************************************************************************
const_iterator& operator-=(int n)
{
return (this->operator+=(-n));
}
//*************************************************************************
//*************************************************************************
friend const_iterator operator+(const const_iterator& lhs, int n)
{
const_iterator temp = lhs;
temp += n;
return temp;
}
//*************************************************************************
//*************************************************************************
friend const_iterator operator-(const const_iterator& lhs, int n)
{
const_iterator temp = lhs;
temp -= n;
return temp;
}
//*************************************************************************
//*************************************************************************
friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
{
return (lhs.current == rhs.current);
}
//*************************************************************************
//*************************************************************************
friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
//***************************************************
friend bool operator<(const const_iterator& lhs, const const_iterator& rhs)
{
const difference_type lhs_index = lhs.get_index();
const difference_type rhs_index = rhs.get_index();
const difference_type reference_index = lhs.container().begin().get_index();
const difference_type buffer_size = static_cast<difference_type>(lhs.container().max_size() + 1UL);
const difference_type lhs_distance = (lhs_index < reference_index) ? buffer_size + lhs_index - reference_index : lhs_index - reference_index;
const difference_type rhs_distance = (rhs_index < reference_index) ? buffer_size + rhs_index - reference_index : rhs_index - reference_index;
return lhs_distance < rhs_distance;
}
//***************************************************
friend bool operator<=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs > rhs);
}
//***************************************************
friend bool operator>(const const_iterator& lhs, const const_iterator& rhs)
{
return (rhs < lhs);
}
//***************************************************
friend bool operator>=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs < rhs);
}
//***************************************************
difference_type get_index() const
{
return static_cast<difference_type>(current);
}
//***************************************************
const icircular_buffer& container() const
{
return *picb;
}
//***************************************************
pointer get_buffer() const
{
return picb->pbuffer;
}
protected:
//*************************************************************************
//*************************************************************************
const_iterator(const icircular_buffer<T>* picb_, size_type current_)
: picb(picb_)
, current(current_)
{
}
private:
const icircular_buffer<T>* picb;
size_type current;
};
friend class iterator;
friend class const_iterator;
typedef etl::reverse_iterator<iterator> reverse_iterator;
typedef etl::reverse_iterator<const_iterator> const_reverse_iterator;
//*************************************************************************
//*************************************************************************
iterator begin()
{
return iterator(this, out);
}
//*************************************************************************
//*************************************************************************
const_iterator begin() const
{
return const_iterator(this, out);
}
//*************************************************************************
//*************************************************************************
const_iterator cbegin() const
{
return const_iterator(this, out);
}
//*************************************************************************
//*************************************************************************
iterator end()
{
return iterator(this, in);
}
//*************************************************************************
//*************************************************************************
const_iterator end() const
{
return const_iterator(this, in);
}
//*************************************************************************
//*************************************************************************
const_iterator cend() const
{
return const_iterator(this, in);
}
//*************************************************************************
//*************************************************************************
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(end());
}
//*************************************************************************
//*************************************************************************
reverse_iterator rend()
{
return reverse_iterator(begin());
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator crend() const
{
return const_reverse_iterator(begin());
}
//*************************************************************************
//*************************************************************************
reference front()
{
ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
return pbuffer[out];
}
//*************************************************************************
//*************************************************************************
const_reference front() const
{
ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
return pbuffer[out];
}
//*************************************************************************
//*************************************************************************
reference back()
{
ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
return pbuffer[in == 0U ? buffer_size - 1 : in - 1U];
}
//*************************************************************************
//*************************************************************************
const_reference back() const
{
ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
return pbuffer[in == 0U ? buffer_size - 1 : in - 1U];
}
//*************************************************************************
//*************************************************************************
reference operator[](size_t index)
{
return pbuffer[(out + index) % buffer_size];
}
//*************************************************************************
//*************************************************************************
const_reference operator[](size_t index) const
{
return pbuffer[(out + index) % buffer_size];
}
//*************************************************************************
//*************************************************************************
void push(const_reference item)
{
::new (&pbuffer[in]) T(item);
increment_in();
// Did we catch up with the 'out' index?
if (in == out)
{
// Forget about the oldest one.
pbuffer[out].~T();
this->increment_out();
}
else
{
ETL_INCREMENT_DEBUG_COUNT;
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void push(rvalue_reference item)
{
::new (&pbuffer[in]) T(etl::move(item));
increment_in();
// Did we catch up with the 'out' index?
if (in == out)
{
// Forget about the oldest item.
pbuffer[out].~T();
increment_out();
}
else
{
ETL_INCREMENT_DEBUG_COUNT;
}
}
#endif
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void push(TIterator first, const TIterator& last)
{
while (first != last)
{
push(*first);
++first;
}
}
//*************************************************************************
//*************************************************************************
void pop()
{
ETL_ASSERT(!empty(), ETL_ERROR(circular_buffer_empty));
pbuffer[out].~T();
increment_out();
ETL_DECREMENT_DEBUG_COUNT;
}
//*************************************************************************
//*************************************************************************
void pop(size_type n)
{
while (n-- != 0U)
{
pop();
}
}
//*************************************************************************
//*************************************************************************
void clear()
{
if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
{
in = 0U;
out = 0U;
ETL_RESET_DEBUG_COUNT;
}
else
{
while (!empty())
{
pop();
}
}
}
//*************************************************************************
//*************************************************************************
void fill(const T& value)
{
etl::fill(begin(), end(), value);
}
#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
//*************************************************************************
//*************************************************************************
virtual void repair() = 0;
#endif
//*************************************************************************
//*************************************************************************
friend difference_type operator-(const iterator& lhs, const iterator& rhs)
{
return distance(rhs, lhs);
}
//*************************************************************************
//*************************************************************************
friend difference_type operator-(const const_iterator& lhs, const const_iterator& rhs)
{
return distance(rhs, lhs);
}
protected:
//*************************************************************************
//*************************************************************************
icircular_buffer(pointer pbuffer_, size_type max_length)
: circular_buffer_base(max_length + 1U)
, pbuffer(pbuffer_)
{
}
//*************************************************************************
//*************************************************************************
template <typename TIterator1, typename TIterator2>
static difference_type distance(const TIterator1& range_begin, const TIterator2& range_end)
{
difference_type distance1 = distance(range_begin);
difference_type distance2 = distance(range_end);
return distance2 - distance1;
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
static difference_type distance(const TIterator& other)
{
const difference_type index = other.get_index();
const difference_type reference_index = static_cast<difference_type>(other.container().out);
const difference_type buffer_size = static_cast<difference_type>(other.container().buffer_size);
if (index < reference_index)
{
return buffer_size + index - reference_index;
}
else
{
return index - reference_index;
}
}
//*************************************************************************
//*************************************************************************
void repair_buffer(T* pbuffer_)
{
pbuffer = pbuffer_;
}
pointer pbuffer;
private:
//*************************************************************************
//*************************************************************************
#if defined(ETL_POLYMORPHIC_CIRCULAR_BUFFER) || defined(ETL_POLYMORPHIC_CONTAINERS)
public:
virtual ~icircular_buffer() {}
#else
protected:
~icircular_buffer() {}
#endif
};
//***************************************************************************
//***************************************************************************
template <typename T, size_t MAX_SIZE_>
class circular_buffer : public icircular_buffer<T>
{
public:
ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::circular_buffer is not valid");
static ETL_CONSTANT typename icircular_buffer<T>::size_type MAX_SIZE = typename icircular_buffer<T>::size_type(MAX_SIZE_);
//*************************************************************************
//*************************************************************************
circular_buffer()
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
{
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
circular_buffer(TIterator first, const TIterator& last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
{
while (first != last)
{
this->push(*first);
++first;
}
}
#if ETL_HAS_INITIALIZER_LIST
//*************************************************************************
//*************************************************************************
circular_buffer(std::initializer_list<T> init)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
{
this->push(init.begin(), init.end());
}
#endif
//*************************************************************************
//*************************************************************************
circular_buffer(const circular_buffer& other)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
{
if (this != &other)
{
this->push(other.begin(), other.end());
}
}
//*************************************************************************
//*************************************************************************
circular_buffer& operator=(const circular_buffer& other)
{
if (this != &other)
{
this->clear();
this->push(other.begin(), other.end());
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
circular_buffer(circular_buffer&& other)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer.raw), MAX_SIZE)
{
if (this != &other)
{
typename etl::icircular_buffer<T>::iterator itr = other.begin();
while (itr != other.end())
{
this->push(etl::move(*itr));
++itr;
}
}
}
//*************************************************************************
//*************************************************************************
circular_buffer& operator=(circular_buffer&& other)
{
if (this != &other)
{
this->clear();
for (typename etl::icircular_buffer<T>::iterator itr = other.begin(); itr != other.end(); ++itr)
{
this->push(etl::move(*itr));
}
}
return *this;
}
#endif
//*************************************************************************
//*************************************************************************
~circular_buffer()
{
this->clear();
}
//*************************************************************************
//*************************************************************************
#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
virtual void repair() ETL_OVERRIDE
#else
void repair()
#endif
{
ETL_ASSERT(etl::is_trivially_copyable<T>::value, ETL_ERROR(etl::circular_buffer_incompatible_type));
etl::icircular_buffer<T>::repair_buffer(buffer);
}
private:
etl::uninitialized_buffer_of<T, MAX_SIZE + 1> buffer;
};
template <typename T, size_t MAX_SIZE_>
ETL_CONSTANT typename icircular_buffer<T>::size_type circular_buffer<T, MAX_SIZE_>::MAX_SIZE;
//***************************************************************************
//***************************************************************************
template <typename T>
class circular_buffer_ext : public icircular_buffer<T>
{
public:
//*************************************************************************
//*************************************************************************
circular_buffer_ext(void* buffer, size_t max_size)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
{
}
//*************************************************************************
//*************************************************************************
circular_buffer_ext(size_t max_size)
: icircular_buffer<T>(ETL_NULLPTR, max_size)
{
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
circular_buffer_ext(TIterator first, const TIterator& last, void* buffer, size_t max_size,
typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
{
while (first != last)
{
this->push(*first);
++first;
}
}
#if ETL_HAS_INITIALIZER_LIST
//*************************************************************************
//*************************************************************************
circular_buffer_ext(std::initializer_list<T> init, void* buffer, size_t max_size)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
{
this->push(init.begin(), init.end());
}
#endif
//*************************************************************************
//*************************************************************************
circular_buffer_ext(const circular_buffer_ext& other, void* buffer, size_t max_size)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
{
if (this != &other)
{
this->push(other.begin(), other.end());
}
}
//*************************************************************************
//*************************************************************************
circular_buffer_ext(const circular_buffer_ext& other) ETL_DELETE;
//*************************************************************************
//*************************************************************************
circular_buffer_ext& operator=(const circular_buffer_ext& other)
{
if (this != &other)
{
this->clear();
this->push(other.begin(), other.end());
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
circular_buffer_ext(circular_buffer_ext&& other, void* buffer, size_t max_size)
: icircular_buffer<T>(reinterpret_cast<T*>(buffer), max_size)
{
if (this != &other)
{
typename etl::icircular_buffer<T>::iterator itr = other.begin();
while (itr != other.end())
{
this->push(etl::move(*itr));
++itr;
}
}
}
//*************************************************************************
//*************************************************************************
circular_buffer_ext& operator=(circular_buffer_ext&& other)
{
if (this != &other)
{
this->clear();
for (typename etl::icircular_buffer<T>::iterator itr = other.begin(); itr != other.end(); ++itr)
{
this->push(etl::move(*itr));
}
}
return *this;
}
#endif
//*************************************************************************
//*************************************************************************
void swap(circular_buffer_ext& other) ETL_NOEXCEPT
{
using ETL_OR_STD::swap; // Allow ADL
swap(this->in, other.in);
swap(this->out, other.out);
swap(this->pbuffer, other.pbuffer);
swap(this->buffer_size, other.buffer_size);
#if defined(ETL_DEBUG_COUNT)
this->etl_debug_count.swap(other.etl_debug_count);
#endif
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void swap(circular_buffer_ext&& other) ETL_NOEXCEPT
{
using ETL_OR_STD::swap; // Allow ADL
swap(this->in, other.in);
swap(this->out, other.out);
swap(this->pbuffer, other.pbuffer);
swap(this->buffer_size, other.buffer_size);
#if defined(ETL_DEBUG_COUNT)
this->etl_debug_count.swap(other.etl_debug_count);
#endif
}
#endif
//*************************************************************************
//*************************************************************************
void set_buffer(void* buffer)
{
this->pbuffer = reinterpret_cast<T*>(buffer);
}
//*************************************************************************
//*************************************************************************
bool is_valid() const
{
return this->pbuffer != ETL_NULLPTR;
}
//*************************************************************************
//*************************************************************************
~circular_buffer_ext()
{
this->clear();
}
//*************************************************************************
//*************************************************************************
#ifdef ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE
virtual void repair() ETL_OVERRIDE
#else
void repair()
#endif
{
}
};
//*************************************************************************
//*************************************************************************
#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
template <typename T, typename... Ts>
circular_buffer(T, Ts...) -> circular_buffer<etl::enable_if_t<(etl::is_same_v<T, Ts> && ...), T>, 1U + sizeof...(Ts)>;
#endif
//*************************************************************************
//*************************************************************************
template <typename T>
void swap(etl::circular_buffer_ext<T>& lhs, etl::circular_buffer_ext<T>& rhs)
{
lhs.swap(rhs);
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
template <typename T>
void swap(etl::circular_buffer_ext<T>& lhs, etl::circular_buffer_ext<T>&& rhs)
{
lhs.swap(rhs);
}
#endif
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator==(const icircular_buffer<T>& lhs, const icircular_buffer<T>& rhs)
{
return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
}
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator!=(const icircular_buffer<T>& lhs, const icircular_buffer<T>& rhs)
{
return !(lhs == rhs);
}
} // namespace etl
#endif
etl::circular_buffer_base::size_type
size_t size_type
The type used for determining the size of queue.
Definition circular_buffer.h:94
etl::circular_buffer_base::out
size_type out
Index to the next read.
Definition circular_buffer.h:172
etl::circular_buffer_base::ETL_DECLARE_DEBUG_COUNT
ETL_DECLARE_DEBUG_COUNT
Internal debugging.
Definition circular_buffer.h:173
etl::circular_buffer_base::in
size_type in
Index to the next write.
Definition circular_buffer.h:171
etl::circular_buffer_empty
Empty exception for the circular_buffer.
Definition circular_buffer.h:64
etl::circular_buffer_exception
Exception for the circular_buffer.
Definition circular_buffer.h:51
etl::circular_buffer_ext
Definition circular_buffer.h:1257
etl::circular_buffer_ext::swap
void swap(circular_buffer_ext &other) ETL_NOEXCEPT
Swap with another circular buffer.
Definition circular_buffer.h:1375
etl::circular_buffer_ext::operator=
circular_buffer_ext & operator=(const circular_buffer_ext &other)
Assignment operator.
Definition circular_buffer.h:1324
etl::circular_buffer_ext::circular_buffer_ext
circular_buffer_ext(size_t max_size)
Definition circular_buffer.h:1272
etl::circular_buffer_ext::set_buffer
void set_buffer(void *buffer)
set_buffer
Definition circular_buffer.h:1411
etl::circular_buffer_ext::circular_buffer_ext
circular_buffer_ext(const circular_buffer_ext &other) ETL_DELETE
Copy Constructor (Deleted).
etl::circular_buffer_ext::is_valid
bool is_valid() const
set_buffer
Definition circular_buffer.h:1419
etl::circular_buffer_ext::circular_buffer_ext
circular_buffer_ext(void *buffer, size_t max_size)
Constructor.
Definition circular_buffer.h:1263
etl::circular_buffer_ext::circular_buffer_ext
circular_buffer_ext(const circular_buffer_ext &other, void *buffer, size_t max_size)
Construct a copy.
Definition circular_buffer.h:1307
etl::circular_buffer_ext::~circular_buffer_ext
~circular_buffer_ext()
Destructor.
Definition circular_buffer.h:1427
etl::circular_buffer_ext::circular_buffer_ext
circular_buffer_ext(TIterator first, const TIterator &last, void *buffer, size_t max_size, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition circular_buffer.h:1282
etl::circular_buffer_ext::repair
void repair()
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1438
etl::circular_buffer_incompatible_type
Incompatible type exception.
Definition circular_buffer.h:77
etl::circular_buffer
Definition circular_buffer.h:1115
etl::circular_buffer::circular_buffer
circular_buffer(TIterator first, const TIterator &last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition circular_buffer.h:1135
etl::circular_buffer::operator=
circular_buffer & operator=(const circular_buffer &other)
Assignment operator.
Definition circular_buffer.h:1171
etl::circular_buffer::circular_buffer
circular_buffer(const circular_buffer &other)
Copy Constructor.
Definition circular_buffer.h:1159
etl::circular_buffer::~circular_buffer
~circular_buffer()
Destructor.
Definition circular_buffer.h:1223
etl::circular_buffer::repair
void repair()
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1234
etl::circular_buffer::circular_buffer
circular_buffer()
Constructor.
Definition circular_buffer.h:1125
etl::icircular_buffer::const_iterator
Iterator iterating through the circular buffer.
Definition circular_buffer.h:478
etl::icircular_buffer::const_iterator::operator-=
const_iterator & operator-=(int n)
Subtract offset.
Definition circular_buffer.h:628
etl::icircular_buffer::const_iterator::const_iterator
const_iterator()
Constructor.
Definition circular_buffer.h:486
etl::icircular_buffer::const_iterator::const_iterator
const_iterator(const icircular_buffer< T > *picb_, size_type current_)
Protected constructor. Only icircular_buffer can create one.
Definition circular_buffer.h:728
etl::icircular_buffer::const_iterator::const_iterator
const_iterator(const typename icircular_buffer::iterator &other)
Copy Constructor from iterator.
Definition circular_buffer.h:495
etl::icircular_buffer::const_iterator::operator[]
const_reference operator[](size_t index) const
[] operator
Definition circular_buffer.h:551
etl::icircular_buffer::const_iterator::operator!=
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Inequality operator.
Definition circular_buffer.h:668
etl::icircular_buffer::const_iterator::operator++
const_iterator operator++(int)
Post increment.
Definition circular_buffer.h:575
etl::icircular_buffer::const_iterator::operator+=
const_iterator & operator+=(int n)
Add offset.
Definition circular_buffer.h:617
etl::icircular_buffer::const_iterator::operator--
const_iterator & operator--()
Pre-decrement.
Definition circular_buffer.h:587
etl::icircular_buffer::const_iterator::operator--
const_iterator operator--(int)
Post increment.
Definition circular_buffer.h:605
etl::icircular_buffer::const_iterator::operator==
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Equality operator.
Definition circular_buffer.h:660
etl::icircular_buffer::const_iterator::const_iterator
const_iterator(const const_iterator &other)
Copy Constructor from const iterator.
Definition circular_buffer.h:504
etl::icircular_buffer::const_iterator::operator++
const_iterator & operator++()
Pre-increment.
Definition circular_buffer.h:559
etl::icircular_buffer::const_iterator::operator*
const_reference operator*() const
Definition circular_buffer.h:535
etl::icircular_buffer::const_iterator::operator-
friend const_iterator operator-(const const_iterator &lhs, int n)
Subtract offset.
Definition circular_buffer.h:648
etl::icircular_buffer::const_iterator::operator->
const_pointer operator->() const
-> operator
Definition circular_buffer.h:543
etl::icircular_buffer::const_iterator::operator+
friend const_iterator operator+(const const_iterator &lhs, int n)
Add offset.
Definition circular_buffer.h:636
etl::icircular_buffer::const_iterator::operator=
const_iterator & operator=(const typename icircular_buffer::iterator &other)
Assignment operator.
Definition circular_buffer.h:513
etl::icircular_buffer::const_iterator::operator=
const_iterator & operator=(const const_iterator &other)
Assignment operator.
Definition circular_buffer.h:524
etl::icircular_buffer::iterator
Iterator iterating through the circular buffer.
Definition circular_buffer.h:199
etl::icircular_buffer::iterator::iterator
iterator(const icircular_buffer< T > *picb_, size_type current_)
Protected constructor. Only icircular_buffer can create one.
Definition circular_buffer.h:462
etl::icircular_buffer::iterator::operator+=
iterator & operator+=(int n)
Add offset.
Definition circular_buffer.h:326
etl::icircular_buffer::iterator::operator==
friend bool operator==(const iterator &lhs, const iterator &rhs)
Equality operator.
Definition circular_buffer.h:381
etl::icircular_buffer::iterator::operator--
iterator & operator--()
Pre-decrement.
Definition circular_buffer.h:296
etl::icircular_buffer::iterator::operator[]
const_reference operator[](size_t index) const
[] operator
Definition circular_buffer.h:260
etl::icircular_buffer::iterator::operator-
friend iterator operator-(const iterator &lhs, int n)
Subtract offset.
Definition circular_buffer.h:369
etl::icircular_buffer::iterator::operator->
pointer operator->() const
-> operator
Definition circular_buffer.h:244
etl::icircular_buffer::iterator::operator-=
iterator & operator-=(int n)
Subtract offset.
Definition circular_buffer.h:337
etl::icircular_buffer::iterator::operator+
friend iterator operator+(const iterator &lhs, int n)
Add offset.
Definition circular_buffer.h:345
etl::icircular_buffer::iterator::operator*
reference operator*() const
Definition circular_buffer.h:236
etl::icircular_buffer::iterator::operator=
iterator & operator=(const iterator &other)
Assignment operator.
Definition circular_buffer.h:225
etl::icircular_buffer::iterator::operator--
iterator operator--(int)
Post increment.
Definition circular_buffer.h:314
etl::icircular_buffer::iterator::operator++
iterator operator++(int)
Post increment.
Definition circular_buffer.h:284
etl::icircular_buffer::iterator::iterator
iterator()
Constructor.
Definition circular_buffer.h:207
etl::icircular_buffer::iterator::operator[]
reference operator[](size_t index)
[] operator
Definition circular_buffer.h:252
etl::icircular_buffer::iterator::operator!=
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Inequality operator.
Definition circular_buffer.h:389
etl::icircular_buffer::iterator::operator+
friend iterator operator+(int n, const iterator &rhs)
Add offset.
Definition circular_buffer.h:357
etl::icircular_buffer::iterator::operator++
iterator & operator++()
Pre-increment.
Definition circular_buffer.h:268
etl::icircular_buffer::iterator::iterator
iterator(const iterator &other)
Copy Constructor.
Definition circular_buffer.h:216
etl::icircular_buffer
Definition circular_buffer.h:181
etl::icircular_buffer::distance
static difference_type distance(const TIterator1 &range_begin, const TIterator2 &range_end)
Measures the distance between two iterators.
Definition circular_buffer.h:1052
etl::icircular_buffer::operator[]
const_reference operator[](size_t index) const
Definition circular_buffer.h:898
etl::icircular_buffer::fill
void fill(const T &value)
Fills the buffer.
Definition circular_buffer.h:1009
etl::icircular_buffer::rend
const_reverse_iterator rend() const
Gets a const reverse iterator to the end of the buffer.
Definition circular_buffer.h:829
etl::icircular_buffer::pop
void pop()
pop
Definition circular_buffer.h:967
etl::icircular_buffer::rend
reverse_iterator rend()
Gets a reverse iterator to the end of the buffer.
Definition circular_buffer.h:821
etl::icircular_buffer::rbegin
const_reverse_iterator rbegin() const
Gets a const reverse iterator to the start of the buffer.
Definition circular_buffer.h:805
etl::icircular_buffer::push
void push(TIterator first, const TIterator &last)
Push a buffer from an iterator range.
Definition circular_buffer.h:955
etl::icircular_buffer::operator-
friend difference_type operator-(const iterator &lhs, const iterator &rhs)
Definition circular_buffer.h:1024
etl::icircular_buffer::end
const_iterator end() const
Gets a const iterator to the end of the buffer.
Definition circular_buffer.h:781
etl::icircular_buffer::back
const_reference back() const
Definition circular_buffer.h:879
etl::icircular_buffer::end
iterator end()
Gets an iterator to the end of the buffer.
Definition circular_buffer.h:773
etl::icircular_buffer::begin
iterator begin()
Gets an iterator to the start of the buffer.
Definition circular_buffer.h:749
etl::icircular_buffer::begin
const_iterator begin() const
Gets a const iterator to the start of the buffer.
Definition circular_buffer.h:757
etl::icircular_buffer::cbegin
const_iterator cbegin() const
Gets a const iterator to the start of the buffer.
Definition circular_buffer.h:765
etl::icircular_buffer::crend
const_reverse_iterator crend() const
Gets a const reverse iterator to the end of the buffer.
Definition circular_buffer.h:837
etl::icircular_buffer::front
reference front()
Definition circular_buffer.h:846
etl::icircular_buffer::operator-
friend difference_type operator-(const const_iterator &lhs, const const_iterator &rhs)
Definition circular_buffer.h:1032
etl::icircular_buffer::clear
void clear()
Clears the buffer.
Definition circular_buffer.h:989
etl::icircular_buffer::repair_buffer
void repair_buffer(T *pbuffer_)
Fix the internal pointers after a low level memory copy.
Definition circular_buffer.h:1084
etl::icircular_buffer::back
reference back()
Definition circular_buffer.h:868
etl::icircular_buffer::icircular_buffer
icircular_buffer(pointer pbuffer_, size_type max_length)
Protected constructor.
Definition circular_buffer.h:1042
etl::icircular_buffer::rbegin
reverse_iterator rbegin()
Gets a reverse iterator to the start of the buffer.
Definition circular_buffer.h:797
etl::icircular_buffer::pop
void pop(size_type n)
pop(n)
Definition circular_buffer.h:978
etl::icircular_buffer::operator[]
reference operator[](size_t index)
Get a reference to the item.
Definition circular_buffer.h:889
etl::icircular_buffer::push
void push(const_reference item)
Definition circular_buffer.h:908
etl::icircular_buffer::cend
const_iterator cend() const
Gets a const iterator to the end of the buffer.
Definition circular_buffer.h:789
etl::icircular_buffer::crbegin
const_reverse_iterator crbegin() const
Gets a const reverse iterator to the start of the buffer.
Definition circular_buffer.h:813
etl::icircular_buffer::distance
static difference_type distance(const TIterator &other)
Definition circular_buffer.h:1065
etl::icircular_buffer::~icircular_buffer
~icircular_buffer()
Destructor.
Definition circular_buffer.h:1105
etl::icircular_buffer::front
const_reference front() const
Definition circular_buffer.h:857
etl::reverse_iterator
Definition iterator.h:310
error_handler.h
exception.h
etl::uninitialized_buffer_of
Definition memory.h:3153
etl::const_iterator
ETL_ASSERT
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
etl::exception::exception
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
etl::exception
Definition exception.h:59
initializer_list.h
iterator.h
memory.h
memory_model.h
etl
Definition absolute.h:40
etl::swap
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
etl::operator==
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1078
etl::operator!=
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
etl::operator<
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
etl::operator<=
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
platform.h
etl::pointer
etl::iterator
iterator
Definition iterator.h:482
etl::type
type_traits.h
vector.h