circular.h

Go to the documentation of this file.
00001 /*
00002  * circular.h
00003  *
00004  * Copyright (C) 2008   Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Template for a circular buffer
00032  */
00033 
00034 #ifndef WAVEPACKET_UTIL_CIRCULAR_H__
00035 #define WAVEPACKET_UTIL_CIRCULAR_H__
00036 
00037 
00038 /// \ingroup util
00039 /// Simple circular buffer.
00040 /// You can repeatedly add samples, and this class will keep only the most
00041 /// current N samples in the buffer.  You can ask for the number of samples in
00042 /// the buffer, and iterate through them.  Starting at index 0 means you will
00043 /// always walk forward from the oldest to the newest sample in the buffer.
00044 template <class T>
00045 class circular_buffer_t {
00046 public:
00047         // constructor ---------------------------------------------------------
00048         circular_buffer_t(IN int size) {
00049                         ASSERT(size > 0, "Bad size: %d", size);
00050                         m_buffer.reserve(size);
00051                         m_idx = 0;
00052                         m_max = size;
00053                         m_size = 0;
00054                 }
00055 
00056         // circular_buffer_t - public class methods ----------------------------
00057         void addSample(IN const T& t) {
00058                         m_buffer[m_idx] = t;
00059 
00060                         // if buffer isn't full, increment size
00061                         if (m_size < m_max) {
00062                                 ++m_size;
00063                         }
00064 
00065                         // increment index
00066                         m_idx = (m_idx + 1) % m_max;
00067                 }
00068 
00069         int size(void) const throw() { return m_size; }
00070 
00071         /// idx = 0 is the oldest sample, always
00072         const T& getSample(IN int idx) const throw() {
00073                         idx = this->getActualIndex(idx);
00074                         return m_buffer[idx];
00075                 }
00076 
00077         /// idx = 0 is the oldest sample, always
00078         T& getSample(IN int idx) throw() {
00079                         idx = this->getActualIndex(idx);
00080                         return m_buffer[idx];
00081                 }
00082 
00083 private:
00084         typedef std::vector<T> vec_type_t;
00085 
00086         int getActualIndex(IN int idx) const throw() {
00087                         ASSERT(idx >= 0, "Bad index: %d", idx);
00088                         ASSERT(idx < m_size, "Bad index: %d", idx);
00089 
00090                         if (m_size >= m_max) {
00091                                 idx += m_idx;
00092                                 idx = idx % m_max;
00093                         }
00094                         return idx;
00095                 }
00096 
00097         vec_type_t              m_buffer;
00098         int                     m_max;          ///<- max allowed size
00099         int                     m_idx;          ///<- current index
00100         int                     m_size;         ///<- current size
00101 };
00102 
00103 
00104 
00105 #endif  // WAVEPACKET_UTIL_CIRCULAR_H__
00106