| #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 <typename T> |
| 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 <typename T> |
| RingBuffer<T>::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 <typename T> |
| RingBuffer<T>::~RingBuffer () |
| { |
| delete[] m_buffer; |
| } |
| |
| template <typename T> |
| void RingBuffer<T>::clear (void) |
| { |
| m_numElements = 0; |
| m_front = 0; |
| m_back = 0; |
| } |
| |
| template <typename T> |
| void RingBuffer<T>::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 <typename T> |
| inline void RingBuffer<T>::pushFront (const T& elem) |
| { |
| DE_ASSERT(getNumFree() > 0); |
| m_buffer[m_front] = elem; |
| m_front = (m_front + 1) % m_size; |
| m_numElements += 1; |
| } |
| |
| template <typename T> |
| void RingBuffer<T>::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 <typename T> |
| inline T RingBuffer<T>::popBack () |
| { |
| DE_ASSERT(getNumElements() > 0); |
| int ndx = m_back; |
| m_back = (m_back + 1) % m_size; |
| m_numElements -= 1; |
| return m_buffer[ndx]; |
| } |
| |
| template <typename T> |
| inline T RingBuffer<T>::peekBack (int offset) const |
| { |
| DE_ASSERT(de::inBounds(offset, 0, getNumElements())); |
| return m_buffer[(m_back + offset) % m_size]; |
| } |
| |
| template <typename T> |
| void RingBuffer<T>::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 <typename T> |
| void RingBuffer<T>::popBack (int count) |
| { |
| DE_ASSERT(de::inRange(count, 0, getNumElements())); |
| m_back = (m_back + count) % m_size; |
| m_numElements -= count; |
| } |
| |
| } // de |
| |
| #endif // _DERINGBUFFER_HPP |