#pragma once #include "Logger.h" #include template class RingBuffer { private: T* m_items; /* data */ std::size_t m_head; std::size_t m_tail; bool m_is_full; bool m_is_empty; std::size_t m_size; void advance_pointer(); void retreat_pointer(); public: RingBuffer(std::size_t size); ~RingBuffer(); bool IsFull() { return m_is_full; } bool IsEmpty() { return m_is_empty; } std::size_t GetSize(); std::size_t GetCapacity() { return m_size; } void Reset(); void Write(T* data, size_t count); bool Read(T* output, size_t count); void Print(); }; template RingBuffer::RingBuffer(std::size_t size) { m_items = new T[size]; m_head = 0; m_tail = 0; m_is_full = 0; m_is_empty = 1; m_size = size; } template RingBuffer::~RingBuffer() { delete[] m_items; } template void RingBuffer::Reset() { m_head = 0; m_tail = 0; m_is_full = 0; } template void RingBuffer::advance_pointer() { if (m_is_full) { m_tail++; if (m_tail == m_size) { m_tail = 0; } } m_head++; if (m_head == m_size) { m_head = 0; } std::size_t p_is_full = m_head == m_tail ? 1 : 0; m_is_full = p_is_full; } template void RingBuffer::retreat_pointer() { m_is_full = 0; m_tail++; if (m_tail == m_size) { m_tail = 0; } } template void RingBuffer::Write(T* data, std::size_t count) { if (m_is_full || m_head + count > m_size) { write_log("[WARN] Trying to overfill the ring buffer: " "\n\tIsFull:%d\n\tHead:%zu\n\tCount:%zu\n\t", m_is_full, m_head, count); return; } m_is_empty = 0; for (std::size_t i = 0; i < count; i++) { m_items[m_head] = data[i]; advance_pointer(); } // m_is_empty = m_is_full && (m_head == m_tail); } template bool RingBuffer::Read(T* output, std::size_t count) { if (m_is_empty) { write_log("[WARN] Trying to read empty buffer"); return 0; } for (std::size_t i = 0; i < count; i++) { output[i] = m_items[m_tail]; retreat_pointer(); } m_is_empty = !m_is_full && (m_head == m_tail); return 1; } template std::size_t RingBuffer::GetSize() { size_t p_size = m_size; if (!m_is_full) { if (m_head >= m_tail) { p_size = (m_head - m_tail); } else { p_size = (m_size + m_head - m_tail); } } return p_size; } template void RingBuffer::Print() { write_log("[INFO] The ring buffer: " "\n\tIsFull:%d\n\tIsEmpty:%d\n\tHead:%zu\n\tTail:%zu\n\t", m_is_full, m_is_empty, m_head, m_tail); }