Skip to content

Instantly share code, notes, and snippets.

@yatharthb97
Created January 7, 2022 19:16
Show Gist options
  • Save yatharthb97/2211c7898382eb4f9ae819b8f490311b to your computer and use it in GitHub Desktop.
Save yatharthb97/2211c7898382eb4f9ae819b8f490311b to your computer and use it in GitHub Desktop.
Implementation of simple Circular Buffer with bounded index random accessor.
#pragma once
#include <sstream>
/* CIRCULAR BUFFER
Implementation of simple Circular Buffer with bounded index random accessor.
---
Author : Yatharth Bhasin
Licence : MIT Licence (Text → https://opensource.org/licenses/MIT)
---
*/
/** @brief Implementation of simple Circular Buffer with bounded index random accessor. */
template <typename Type, unsigned int MaxSize>
class CircularBuffer
{
public:
unsigned int head = 0; //! Index / Pointer of the first element of the buffer
unsigned int tail = 0; //! Index / Pointer to the last element of the buffer
bool is_full_flag = false; //! Flag indicates whether the buffer is running at full capacity
/** @brief Adjusts the pointer after addition or push_back() operation. */
void advance_pointer() __attribute__((always_inline))
{
if(is_full_flag)
{
if (++tail == MaxSize)
{ tail = 0; }
}
if (++head == MaxSize)
{ head = 0; }
is_full_flag = (head == tail);
}
/** @brief Adjusts the pointers after a removal or pop_back() operation. */
void retreat_pointer() __attribute__((always_inline))
{
is_full_flag = false;
if (++tail == MaxSize)
{ tail = 0; }
}
public:
Type buffer[MaxSize] = {0}; //! Fixed Size Buffer
/** @brief Resets the buffer (pointers) without clearing the elements. */
void reset() __attribute__((always_inline))
{
head = 0;
tail = 0;
is_full_flag = false;
}
/** @brief Returns whether the buffer is full. */
bool is_full() const __attribute__((always_inline))
{
return is_full_flag;
}
/** @brief Returns whether the buffer is empty. \note{!is_full() != is_empty()}*/
bool is_empty() const __attribute__((always_inline))
{
return ( head==tail && !is_full_flag );
}
/** @brief Returns the maximum capacity of the buffer. */
size_t capacity() const __attribute__((always_inline))
{
return MaxSize;
}
/** @brief Returns the current size of the buffer. */
size_t size() const __attribute__((always_inline))
{
if(is_full_flag)
{ return MaxSize; }
else if (head >= tail)
{ return (head - tail); }
else
{ return MaxSize + (head - tail); }
}
/** @brief Adds a datum to the circular buffer. */
void push_back(const Type data) __attribute__((flatten))
{
this->buffer[head] = data;
this->advance_pointer();
}
/** @brief Returns the last element from the buffer and deletes it - pop operation. */
Type pop_back() __attribute__((always_inline))
{
if(!is_empty())
{
Type temp = buffer[tail];
retreat_pointer();
return temp;
}
else
return Type();
}
/** @brief Random access operator can be used to retrive the nth element in the buffer at any state of the buffer. */
Type operator[] (const size_t index) const __attribute__((always_inline))
{
//assert(index < MaxSize);
size_t Remaining = MaxSize - head; //Indices servicible by adding to head pointer.
return (Remaining > index) * buffer[head + index] +
!(Remaining > index) * (buffer[index - Remaining]);
}
template <typename Type_, unsigned int MaxSize_>
friend std::ostream& operator<< (std::ostream &stream, const CircularBuffer<Type_, MaxSize_> &cbuffer);
};
/** @brief Defines a stream operator for the CircularBuffer. */
template <typename Type, unsigned int MaxSize>
std::ostream& operator<< (std::ostream &stream, const CircularBuffer<Type, MaxSize> &cbuffer)
{
for(unsigned int i = 0; i < cbuffer.size(); i++)
{
stream << cbuffer.buffer[i] << ' ';
}
return stream;
} //End of friend overload operator<<
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment