topical media & game development

talk show tell print

professional-program-20-RingBuffer-RingBuffer.c

? / professional-program-20-RingBuffer-RingBuffer.c


  include <algorithm>
  include <iterator>
  include <iostream>
  include <RingBuffer.h>
  
  using namespace std;
  
  // Microsoft Visual Studio requires you to omit the following line.
  // However, some compilers require it.
  //const int RingBuffer::kDefaultNumEntries;
  
  //
  // Initialize the vector to hold exactly numEntries. The vector size
  // does not need to change during the lifetime of the object.
  //
  // Initialize the other members.
  //
  RingBuffer::RingBuffer(int numEntries, ostream* ostr) : mEntries(numEntries),
                                                          mOstr(ostr), mNumEntries(numEntries), mNext(0), mWrapped(false)
  {
  }
  
  RingBuffer::~RingBuffer()
  {
  }
  
  //
  // The algorithm is pretty simple: add the entry to the next
  // free spot, then reset mNext to indicate the free spot after
  // that. If mNext reaches the end of the vector, it starts over at 0.
  //
  // The buffer needs to know if the buffer has wrapped or not so
  // that it knows whether to print the entries past mNext in operator<<
  //
  void RingBuffer::addEntry(const string& entry)
  {
    // Add the entry to the next free spot and increment
    // mNext to point to the free spot after that.
    mEntries[mNext++] = entry;
  
    // Check if we've reached the end of the buffer. If so, we need to wrap.
    if (mNext >= mNumEntries) {
      mNext = 0;
      mWrapped = true;
    }
  
    // If there is a valid ostream, write this entry to it.
    if (mOstr != NULL) {
      *mOstr << entry << endl;
    }
  }
  
  ostream* RingBuffer::setOutput(ostream* newOstr)
  {
    ostream* ret = mOstr;
    mOstr = newOstr;
    return (ret);
  }
  
  //
  // This function uses an ostream_iterator to "copy" entries directly
  // from the vector to the output stream.
  //
  // This function must print the entries in order. If the buffer has wrapped,
  // the earliest entry is one past the most recent entry, which is the entry
  // indicated by mNext. So first print from entry mNext to the end.
  //
  // Then (even if the buffer hasn't wrapped) print from the beginning to mNext - 1.
  //
  ostream& operator<<(ostream& ostr, const RingBuffer& rb)
  {
    if (rb.mWrapped) {
      //
      // If the buffer has wrapped, print the elements from
      // the earliest entry to the end.
      //
      copy (rb.mEntries.begin() + rb.mNext, rb.mEntries.end(),
            ostream_iterator<string>(ostr, "\n"));
    }
  
    //
    // Now print up to the most recent entry.
    // Go up to begin() + mNext because the range is not inclusive on the
    // right side.
    //
    copy (rb.mEntries.begin(), rb.mEntries.begin() + rb.mNext,
          ostream_iterator<string>(ostr, "\n"));
  
    return (ostr);
  }
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.