#pragma once #include #include #include #include /* This file defines a simple "RollingBuffer" class, based on the implementation of SampleBuffer in ncmpcpp. */ template struct RollingBuffer { public: typedef typename std::vector::iterator Iterator; RollingBuffer() : m_offset(0) { } void put(Iterator begin, Iterator end); size_t get(size_t elems, std::vector &dest); void resize(size_t n); void clear(); size_t size() const; const std::vector &buffer() const; private: size_t m_offset; std::vector m_buffer; }; template void RollingBuffer::put( RollingBuffer::Iterator begin, RollingBuffer::Iterator end ) { // How many elements to put size_t elems = end - begin; if (elems > m_buffer.size()) { throw std::out_of_range("Size of the buffer is smaller than the amount of elements"); } // How much space we have for new elements size_t free_elems = m_buffer.size() - m_offset; // If we don't have enough free space, // make more by moving the buffer forwards. if (elems > free_elems) { size_t to_remove = elems - free_elems; std::copy( m_buffer.begin() + to_remove, m_buffer.end() - free_elems, m_buffer.begin() ); m_offset -= to_remove; } // Add new elements to buffer std::copy(begin, end, m_buffer.begin() + m_offset); m_offset += elems; } template size_t RollingBuffer::get( size_t elems, std::vector &dest ) { // elems: how many samples to get // dest: where to put them // (m_offset == 0) => we have no data if (m_offset == 0) { return 0; } // If too many elements are requested, // give as much as we can. if (elems > m_offset) { elems = m_offset; } if (elems >= dest.size()) { // If dest is smaller than request size, // discard earlier elements to fit. size_t elems_lost = elems - dest.size(); std::copy(m_buffer.begin() + elems_lost, m_buffer.begin() + elems, dest.begin()); } else { // otherwise, copy samples to the destination buffer. std::copy(dest.begin() + elems, dest.end(), dest.begin()); std::copy(m_buffer.begin(), m_buffer.begin() + elems, dest.end() - elems); } // Remove elements from the internal buffer. std::copy(m_buffer.begin() + elems, m_buffer.begin() + m_offset, m_buffer.begin()); m_offset -= elems; return elems; } template void RollingBuffer::resize(size_t n) { m_buffer.resize(n); clear(); } template void RollingBuffer::clear() { m_offset = 0; } template size_t RollingBuffer::size() const { return m_offset; } template const std::vector &RollingBuffer::buffer() const { return m_buffer; }