#ifndef _DERINGBUFFER_HPP #define _DERINGBUFFER_HPP /*------------------------------------------------------------------------- * drawElements C++ Base Library * ----------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Ring buffer template. *//*--------------------------------------------------------------------*/ #include "deDefs.hpp" namespace de { void RingBuffer_selfTest (void); /** Ring buffer template. */ template class RingBuffer { public: RingBuffer (int size); ~RingBuffer (void); void clear (void); void resize (int newSize); int getSize (void) const { return m_size; } int getNumElements (void) const { return m_numElements; } int getNumFree (void) const { return m_size - m_numElements; } void pushFront (const T& elem); void pushFront (const T* elemBuf, int count); void peekBack (T* elemBuf, int count) const; T peekBack (int offset) const; T popBack (void); void popBack (T* elemBuf, int count) { peekBack(elemBuf, count); popBack(count); } void popBack (int count); protected: int m_numElements; int m_front; int m_back; T* m_buffer; int m_size; }; // RingBuffer implementation. template RingBuffer::RingBuffer (int size) : m_numElements (0) , m_front (0) , m_back (0) , m_size (size) { DE_ASSERT(size > 0); m_buffer = new T[m_size]; } template RingBuffer::~RingBuffer () { delete[] m_buffer; } template void RingBuffer::clear (void) { m_numElements = 0; m_front = 0; m_back = 0; } template void RingBuffer::resize (int newSize) { DE_ASSERT(newSize >= m_numElements); T* buf = new T[newSize]; try { // Copy old elements. for (int ndx = 0; ndx < m_numElements; ndx++) buf[ndx] = m_buffer[(m_back + ndx) % m_size]; // Reset pointers. m_front = m_numElements; m_back = 0; m_size = newSize; DE_SWAP(T*, buf, m_buffer); delete[] buf; } catch (...) { delete[] buf; throw; } } template inline void RingBuffer::pushFront (const T& elem) { DE_ASSERT(getNumFree() > 0); m_buffer[m_front] = elem; m_front = (m_front + 1) % m_size; m_numElements += 1; } template void RingBuffer::pushFront (const T* elemBuf, int count) { DE_ASSERT(de::inRange(count, 0, getNumFree())); for (int i = 0; i < count; i++) m_buffer[(m_front + i) % m_size] = elemBuf[i]; m_front = (m_front + count) % m_size; m_numElements += count; } template inline T RingBuffer::popBack () { DE_ASSERT(getNumElements() > 0); int ndx = m_back; m_back = (m_back + 1) % m_size; m_numElements -= 1; return m_buffer[ndx]; } template inline T RingBuffer::peekBack (int offset) const { DE_ASSERT(de::inBounds(offset, 0, getNumElements())); return m_buffer[(m_back + offset) % m_size]; } template void RingBuffer::peekBack (T* elemBuf, int count) const { DE_ASSERT(de::inRange(count, 0, getNumElements())); for (int i = 0; i < count; i++) elemBuf[i] = m_buffer[(m_back + i) % m_size]; } template void RingBuffer::popBack (int count) { DE_ASSERT(de::inRange(count, 0, getNumElements())); m_back = (m_back + count) % m_size; m_numElements -= count; } } // de #endif // _DERINGBUFFER_HPP