CircularBuffer.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003, 2004 Zentaro Kavanagh
00003 //
00004 //Redistribution and use in source and binary forms, with or without
00005 //modification, are permitted provided that the following conditions
00006 //are met:
00007 //
00008 //- Redistributions of source code must retain the above copyright
00009 //  notice, this list of conditions and the following disclaimer.
00010 //
00011 //- Redistributions in binary form must reproduce the above copyright
00012 //  notice, this list of conditions and the following disclaimer in the
00013 //  documentation and/or other materials provided with the distribution.
00014 //
00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 
00016 //  may be used to endorse or promote products derived from this software 
00017 //  without specific prior written permission.
00018 //
00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00022 //PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 //===========================================================================
00031 
00032 #include "stdafx.h"
00033 #include <libOOOgg/CircularBuffer.h>
00034 
00035 //Leak checked : 20041017 - OK
00036 CircularBuffer::CircularBuffer(unsigned long inBufferSize)
00037         :       mBufferSize(inBufferSize)
00038         ,       mBuffer(NULL)
00039         ,       mReadPtr(0)
00040         ,       mWritePtr(0)
00041 
00042 {
00043         mBuffer = new unsigned char[inBufferSize + 1];                  //Deleted in destructor.
00044 }
00045 
00046 CircularBuffer::~CircularBuffer(void)
00047 {
00048         delete[] mBuffer;
00049 }
00050 
00051 unsigned long CircularBuffer::read(unsigned char* outData, unsigned long inBytesToRead) {
00052 
00053         //Returns early.
00054         if (inBytesToRead >  spaceLeft()) {
00055                 return 0;
00056         }
00057         
00058         unsigned long locBytesToRead =  inBytesToRead;
00059         
00060         bufASSERT(locBytesToRead <= mBufferSize);
00061                 //      (inBytesToRead <= numBytesAvail())      ?       inBytesToRead
00062                 //                                                                                      :       numBytesAvail();
00063         //locBytesToRead = the lower of numBytesAvail() and inBytesToRead
00064         bufASSERT(locBytesToRead <= inBytesToRead);
00065         bufASSERT(locBytesToRead <= numBytesAvail());
00066         
00067 
00068         //When mReadPtr = 0, there are mBufferSize + 1 bytes from the end, but we are only allowed to
00069         // write mBufferSize. Below where locEndDistabnce is used as a parameter to memcpy
00070         // but that branch is only taken where locEndDistance is less than the number of bytes to
00071         // read. Because we have already established above that the number of bytes to read is less
00072         // than the size of the buffer, this should not be a problem.
00073         unsigned long locEndDistance = (mBufferSize + 1 - mReadPtr);
00074         
00075         //bufASSERT(locEndDistance <= mBufferSize);
00076         if (locEndDistance >= locBytesToRead) {
00077                 //Within the buffer
00078                 bufASSERT(mReadPtr <= mBufferSize);
00079                 
00080                 memcpy((void*)outData, (const void*)(mBuffer + mReadPtr), locBytesToRead);
00081         } else {
00082                 bufASSERT(locEndDistance <= mBufferSize);
00083 
00084                 //Copy from the end of the raw buffer as much as we can into outdtata
00085                 memcpy((void*)outData, (const void*)(mBuffer + mReadPtr), locEndDistance);
00086 
00087                 //Copy from the start of the raw buffer whatever is left
00088                 memcpy((void*)(outData + locEndDistance), (const void*)(mBuffer), locBytesToRead - locEndDistance);
00089         }
00090         mReadPtr = (mReadPtr + locBytesToRead) % (mBufferSize + 1);
00091 
00092         return locBytesToRead;
00093 }
00094 
00095 unsigned long CircularBuffer::write(const unsigned char* inData, unsigned long inBytesToWrite) {
00096         if (inBytesToWrite >  spaceLeft()) {
00097                 return 0;
00098         }
00099 
00100         unsigned long locBytesToWrite = inBytesToWrite;
00101                 
00102                 //              (inBytesToWrite >  spaceLeft())         ?       spaceLeft()
00103                 //                                                                              :       inBytesToWrite;
00104 
00105         bufASSERT(locBytesToWrite <= spaceLeft());
00106         bufASSERT(locBytesToWrite <= inBytesToWrite);
00107         bufASSERT(locBytesToWrite <= mBufferSize);
00108         bufASSERT(mWritePtr <= mBufferSize);
00109 
00110         unsigned long locEndDistance = (mBufferSize + 1 - mWritePtr);
00111 
00112         //bufASSERT(locEndDistance <= mBufferSize + 1);
00113         //Where we will be, in relation to the end of the raw buffer if we wrote the buffer out from here.
00114         //Negative values indicate bytes past the end ofthe buffer.
00115         //signed long locEndOffset = locEndDistance - locBytesToWrite;
00116 
00117 
00118         if (locEndDistance >= locBytesToWrite) {
00119                 //Within the buffer
00120                 memcpy((void*)(mBuffer + mWritePtr), ((const void*)inData), locBytesToWrite);
00121         } else {
00122                 bufASSERT(locEndDistance <= mBufferSize);
00123 
00124                 //Copy from the end of the raw buffer as much as we can into outdtata
00125                 memcpy((void*)(mBuffer + mWritePtr), (const void*)inData, locEndDistance);
00126 
00127                 //Copy from the start of the raw buffer whatever is left
00128                 memcpy((void*)(mBuffer), (const void*)(inData + locEndDistance), locBytesToWrite - locEndDistance);
00129                 
00130                 //Advance the write pointer wrapping voer the end.
00131                 
00132         }
00133         mWritePtr = (mWritePtr + locBytesToWrite) % (mBufferSize + 1);
00134 
00135         return locBytesToWrite;
00136 
00137         
00138 
00139 }
00140 
00141 unsigned long CircularBuffer::spaceLeft() {
00142         bufASSERT(mReadPtr <= mBufferSize);
00143         bufASSERT(mWritePtr <= mBufferSize);
00144 
00145         //The write pointer is always treated as being equal to or in front of the read pointer.
00146         //return mBufferSize - numBytesAvail() - 1;
00147         if (mReadPtr > mWritePtr) {
00148                 //Read pointer is to the right of the Write pointer
00149                 // Since the write pointer is always in front, this means all the data from the read ptr
00150                 // to the end of the buffer, plus everything from the start up to the write pointer is
00151                 // available
00152                 //
00154 
00155                 bufASSERT(mReadPtr > mWritePtr);
00156                 return  (mReadPtr - mWritePtr - 1);
00157         } else {
00158                 bufASSERT(mReadPtr <= mWritePtr);
00159                 return mBufferSize + mReadPtr - mWritePtr ;
00160         }
00161 }
00162 unsigned long CircularBuffer::numBytesAvail() {
00163         bufASSERT(mReadPtr <= mBufferSize);
00164         bufASSERT(mWritePtr <= mBufferSize);
00165 
00166         if (mReadPtr > mWritePtr) {
00167                 //Read pointer is to the right of the Write pointer
00168                 // Since the write pointer is always in front, this means all the data from the read ptr
00169                 // to the end of the buffer, plus everything from the start up to the write pointer is
00170                 // available
00171                 //
00173 
00174                 bufASSERT(mReadPtr > mWritePtr);
00175 
00176                 //Here
00177                 return  (mBufferSize + 1 + mWritePtr - mReadPtr);
00178         } else {
00179                 //if (mReadPtr <= mWritePtr)
00180                 return mWritePtr - mReadPtr;
00181         }
00182 }
00183 
00184 void CircularBuffer::reset() {
00185         mWritePtr = 0;
00186         mReadPtr = 0;
00187 }
00188 

Generated on Tue Feb 15 14:54:20 2005 for oggdsf by  doxygen 1.3.9