CircularBuffer.hxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _CircularBuffer_
00023 #define _CircularBuffer_
00024
00025 #include "Array.hxx"
00026 #include "DataTypes.hxx"
00027 #include "Err.hxx"
00028
00029 namespace CLAM
00030 {
00031
00032
00046 template <class T> class CircularBuffer
00047 {
00048 protected:
00049 Array<T> mBuffer;
00050 TSize mLogicalSize;
00051 TSize mReadSize;
00052 TSize mWriteSize;
00053 TSize mWriteIndex;
00054 TSize mReadIndex;
00055 TSize mInitialReadOffset;
00056 TSize mInitialWriteOffset;
00057
00058 public:
00059
00066 CircularBuffer() : mBuffer()
00067 {
00068 mWriteIndex = 0;
00069 mReadIndex = 0;
00070 mReadSize = mWriteSize = 1;
00071 mInitialReadOffset = 0;
00072 mInitialWriteOffset = 0;
00073 SetBufferSize(0);
00074 mLogicalSize = 0;
00075 }
00076
00082 CircularBuffer(TSize bufferSize) : mBuffer(bufferSize)
00083 {
00084 CLAM_ASSERT(bufferSize > 0, "CircularBuffer:CircularBuffer: BufferSize has to be larger than zero");
00085 SetBufferSize(bufferSize);
00086 mWriteIndex = 0;
00087 mReadIndex = 0;
00088 mReadSize = mWriteSize = 1;
00089 mInitialReadOffset = 0;
00090 mInitialWriteOffset = 0;
00091 mLogicalSize = 0;
00092 }
00093
00094
00095
00099 TSize GetBufferSize() const
00100 {
00101 return mBuffer.Size()-GetReadSize();
00102 }
00103
00109 void SetBufferSize(TSize size)
00110 {
00111 mBuffer.Resize(size+GetReadSize());
00112 mBuffer.SetSize(size+GetReadSize());
00113 InitPointers();
00114 }
00115
00120 TSize GetWriteIndex() const
00121 {
00122 return mWriteIndex;
00123 }
00124
00129 TSize GetReadIndex() const
00130 {
00131 return mReadIndex;
00132 }
00133
00139 TSize GetInitialReadOffset() const
00140 {
00141 return mInitialReadOffset;
00142 }
00143
00150 void SetInitialReadOffset(TSize size)
00151 {
00152 CLAM_ASSERT((size >= 0)&&(size < GetBufferSize()-1),
00153 "CircularBuffer:SetInitialReadOffset: InitialReadOffset has to be larger than zero");
00154 mInitialReadOffset = size;
00155 }
00156
00162 TSize GetInitialWriteOffset() const
00163 {
00164 return mInitialWriteOffset;
00165 }
00166
00173 void SetInitialWriteOffset(TSize size)
00174 {
00175 CLAM_ASSERT((size >= 0)&&(size < GetBufferSize()-1),
00176 "CircularBuffer:SetInitialWriteOffset: InitialWriteOffset has to be larger than zero");
00177 mInitialWriteOffset = size;
00178 }
00179
00180
00181
00187 void Init()
00188 {
00189 SetBufferToZero();
00190 InitPointers();
00191 }
00192
00196 void SetBufferToZero()
00197 {
00198 T *pBuffer;
00199 pBuffer = mBuffer.GetPtr();
00200 memset(pBuffer, 0, GetBufferSize()*sizeof(T));
00201 }
00202
00207 void InitPointers()
00208 {
00209 if(mInitialReadOffset < 0)
00210 mReadIndex = GetBufferSize() + mInitialReadOffset;
00211 else
00212 mReadIndex = mInitialReadOffset;
00213 if(mInitialWriteOffset < 0)
00214 mWriteIndex = GetBufferSize() + mInitialWriteOffset;
00215 else
00216 mWriteIndex = mInitialWriteOffset;
00217 mLogicalSize=0;
00218 }
00219
00220
00221
00226 void Read(T& element)
00227 {
00228 element = mBuffer[mReadIndex];
00229 IncreaseReadIndex();
00230 }
00231
00232
00233 void NonCopyRead(Array<T>& buffer)
00234 {
00235 TSize limit;
00236 if((limit=mReadIndex+mReadSize)>GetBufferSize())
00237 {
00238
00239 memcpy(mBuffer.GetPtr()+GetBufferSize(),mBuffer.GetPtr(),mReadSize*sizeof(T));
00240 }
00241 buffer.SetPtr(mBuffer.GetPtr()+mReadIndex,mReadSize);
00242 IncreaseReadIndex(mReadSize);
00243
00244
00245 }
00246
00253 void Read(T* buffer)
00254 {
00255 TSize limit;
00256 if((limit=mReadIndex+mReadSize)>GetBufferSize())
00257 {
00258 TSize secondHalf=limit%GetBufferSize();
00259 TSize firstHalf=mReadSize-secondHalf;
00260 memcpy(buffer,mBuffer.GetPtr()+mReadIndex,firstHalf*sizeof(T));
00261 memcpy(buffer+firstHalf,mBuffer.GetPtr(),secondHalf*sizeof(T));
00262 }
00263 else
00264 {
00265 memcpy(buffer,mBuffer.GetPtr()+mReadIndex,mReadSize*sizeof(T));
00266 }
00267
00268 IncreaseReadIndex(mReadSize);
00269 }
00270
00280 void Read(Array<T>& in, TSize offset = 0)
00281 {
00282 CLAM_ASSERT(GetReadSize() <= in.Size()+offset, "Error, input buffer is not large enough");
00283
00284 #ifdef CLAM_HIGH_OPTIMIZATIONS
00285 Read(in.GetPtr()+offset);
00286 #else
00287 for(int i=0;i<mReadSize;i++)
00288 Read(in[i+offset]);
00289 #endif
00290 }
00291
00295 void Write(const T& element)
00296 {
00297 mBuffer[mWriteIndex] = element;
00298 IncreaseWriteIndex();
00299 }
00300
00306 void Write(const T* buffer)
00307 {
00308 TSize limit;
00309 if((limit=mWriteIndex+mWriteSize)>GetBufferSize())
00310 {
00311 TSize secondHalf=limit%GetBufferSize();
00312 TSize firstHalf=mWriteSize-secondHalf;
00313 memcpy(mBuffer.GetPtr()+mWriteIndex,buffer,firstHalf*sizeof(T));
00314 memcpy(mBuffer.GetPtr(),buffer+firstHalf,secondHalf*sizeof(T));
00315 }
00316 else
00317 {
00318 memcpy(mBuffer.GetPtr()+mWriteIndex,buffer,mWriteSize*sizeof(T));
00319 }
00320
00321 IncreaseWriteIndex(mWriteSize);
00322 }
00323
00331 void Write(const Array<T>& in, TSize offset = 0)
00332 {
00333 CLAM_ASSERT(GetWriteSize()<=in.Size()+offset,"Error, input buffer is not large enough");
00334 #ifdef CLAM_HIGH_OPTIMIZATIONS
00335 Write(in.GetPtr()+offset);
00336 #else
00337 for(int i=0;i<mWriteSize;i++)
00338 Write(in[i+offset]);
00339 #endif
00340 }
00341
00347 void Add(const T& elem)
00348 {
00349 mBuffer[mWriteIndex] += elem;
00350 IncreaseWriteIndex();
00351 }
00352
00360 void Add(const Array<T>& in, TSize offset = 0)
00361 {
00362 CLAM_ASSERT(GetWriteSize()<=in.Size()+offset,"Error, input buffer is not large enough");
00363 for(int i=0;i<mWriteSize;i++)
00364 Add(in[i+offset]);
00365
00366 }
00367
00372 void IncreaseReadIndex(TSize step = 1)
00373 {
00374 mReadIndex += step;
00375 mReadIndex=mReadIndex%GetBufferSize();
00376 mLogicalSize-=step;
00377 CLAM_ASSERT(mLogicalSize>=0,"Error:Read Index surpassed Write Index");
00378 }
00379
00384 void IncreaseWriteIndex(TSize step = 1)
00385 {
00386
00387 mWriteIndex += step;
00388 mWriteIndex =mWriteIndex%GetBufferSize();
00389 mLogicalSize+=step;
00390 CLAM_ASSERT(mLogicalSize<=GetBufferSize(),"Error:Write Index surpassed Read Index");
00391 }
00392
00397 void DecreaseReadIndex(TSize step = 1)
00398 {
00399
00400 mReadIndex -= step;
00401 mReadIndex =mReadIndex%GetBufferSize();
00402 if(mReadIndex<0) mReadIndex=GetBufferSize()+mReadIndex;
00403 mLogicalSize+=step;
00404 CLAM_ASSERT(mLogicalSize<=GetBufferSize(),"Error:Write Index surpassed Read Index");
00405 }
00406
00411 void DecreaseWriteIndex(TSize step = 1)
00412 {
00413
00414 mWriteIndex -= step;
00415 mWriteIndex =mWriteIndex%GetBufferSize();
00416 if(mWriteIndex<0) mWriteIndex =GetBufferSize()+mWriteIndex ;
00417 mLogicalSize-=step;
00418 CLAM_ASSERT(mLogicalSize>=0,"Error:Read Index surpassed Write Index");
00419 }
00420
00426 T& GetPtrToElement(int absPos)
00427 {
00428 int index = absPos%GetBufferSize();
00429
00430 return mBuffer[index];
00431 }
00432
00433
00434
00440 TSize GetReadSize() const
00441 {
00442 return mReadSize;
00443 }
00444
00450 TSize GetWriteSize() const
00451 {
00452 return mWriteSize;
00453 }
00454
00459 void SetReadSize(TSize size)
00460 {
00461 CLAM_ASSERT(size>=0&&size<=GetBufferSize(),"AudioCircularBuffer:SetReadSize: ReadSize has to be larger than zero");
00462 TSize previousBufferSize=GetBufferSize();
00463 mReadSize = size;
00464 SetBufferSize(previousBufferSize);
00465 }
00466
00471 void SetWriteSize(TSize size)
00472 {
00473 CLAM_ASSERT(size>=0&&size<=GetBufferSize(),"AudioCircularBuffer:SetWriteSize: WriteSize has to be larger than zero");
00474 mWriteSize = size;
00475 }
00476 };
00477
00478
00479
00480 };
00481
00482 #endif //_CircularBuffer_
00483