You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
6.6 KiB
271 lines
6.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Circular Buffer |
|
// |
|
//=============================================================================// |
|
|
|
#include "tier0/dbg.h" |
|
#include "circularbuffer.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
CCircularBuffer::CCircularBuffer() |
|
{ |
|
SetSize( 0 ); |
|
} |
|
|
|
CCircularBuffer::CCircularBuffer(int size) |
|
{ |
|
SetSize(size); |
|
} |
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Sets the maximum size for a circular buffer. This does not do any |
|
// memory allocation, it simply informs the buffer of its size. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
void CCircularBuffer::SetSize(int size) |
|
{ |
|
Assert( this ); |
|
|
|
m_nSize = size; |
|
m_nRead = 0; |
|
m_nWrite = 0; |
|
m_nCount = 0; |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Empties a circular buffer. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
void CCircularBuffer::Flush() |
|
{ |
|
AssertValid(); |
|
|
|
m_nRead = 0; |
|
m_nWrite = 0; |
|
m_nCount = 0; |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Returns the available space in a circular buffer. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::GetWriteAvailable() |
|
{ |
|
AssertValid(); |
|
|
|
return(m_nSize - m_nCount); |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Returns the size of a circular buffer. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::GetSize() |
|
{ |
|
AssertValid(); |
|
|
|
return(m_nSize); |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Returns the number of bytes in a circular buffer. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::GetReadAvailable() |
|
{ |
|
AssertValid(); |
|
|
|
return(m_nCount); |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Reads a specified number of bytes from a circular buffer without |
|
// consuming them. They will still be available for future calls to |
|
// Read or Peek. |
|
//Input : pchDest - destination buffer. |
|
// m_nCount - number of bytes to place in destination buffer. |
|
//Output : Returns the number of bytes placed in the destination buffer. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::Peek(char *pchDest, int nCount) |
|
{ |
|
// If no data available, just return. |
|
if(m_nCount == 0) |
|
{ |
|
return(0); |
|
} |
|
|
|
// |
|
// Requested amount should not exceed the available amount. |
|
// |
|
nCount = MIN(m_nCount, nCount); |
|
|
|
// |
|
// Copy as many of the requested bytes as possible. |
|
// If buffer wrap occurs split the data into two chunks. |
|
// |
|
if (m_nRead + nCount > m_nSize) |
|
{ |
|
int nCount1 = m_nSize - m_nRead; |
|
memcpy(pchDest, &m_chData[m_nRead], nCount1); |
|
pchDest += nCount1; |
|
|
|
int nCount2 = nCount - nCount1; |
|
memcpy(pchDest, m_chData, nCount2); |
|
} |
|
// Otherwise copy it in one go. |
|
else |
|
{ |
|
memcpy(pchDest, &m_chData[m_nRead], nCount); |
|
} |
|
|
|
AssertValid(); |
|
return nCount; |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Advances the read index, consuming a specified number of bytes from |
|
// the circular buffer. |
|
//Input : m_nCount - number of bytes to consume. |
|
//Output : Returns the actual number of bytes consumed. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::Advance(int nCount) |
|
{ |
|
// If no data available, just return. |
|
if (m_nCount == 0) |
|
{ |
|
return(0); |
|
} |
|
|
|
// |
|
// Requested amount should not exceed the available amount. |
|
// |
|
nCount = MIN(m_nCount, nCount); |
|
|
|
// Advance the read pointer, checking for buffer |
|
//wrap. |
|
// |
|
m_nRead = (m_nRead + nCount) % m_nSize; |
|
m_nCount -= nCount; |
|
|
|
// |
|
// If we have emptied the buffer, reset the read and write indices |
|
// to minimize buffer wrap. |
|
// |
|
if (m_nCount == 0) |
|
{ |
|
m_nRead = 0; |
|
m_nWrite = 0; |
|
} |
|
|
|
AssertValid(); |
|
return nCount; |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Reads a specified number of bytes from a circular buffer. The bytes |
|
// will be consumed by the read process. |
|
//Input : pchDest - destination buffer. |
|
// m_nCount - number of bytes to place in destination buffer. |
|
//Output : Returns the number of bytes placed in the destination buffer. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::Read(void *pchDestIn, int nCount) |
|
{ |
|
int nPeeked; |
|
int nRead; |
|
|
|
char *pchDest = (char*)pchDestIn; |
|
|
|
nPeeked = Peek(pchDest, nCount); |
|
|
|
if (nPeeked != 0) |
|
{ |
|
nRead = Advance(nPeeked); |
|
|
|
assert( nRead == nPeeked); |
|
} |
|
else |
|
{ |
|
nRead = 0; |
|
} |
|
|
|
AssertValid(); |
|
return(nRead); |
|
} |
|
|
|
|
|
//------------------ Copyright (c) 1999 Valve, LLC. ---------------------------- |
|
//Purpose : Writes a specified number of bytes to the buffer. |
|
//Input : pm_chData - buffer containing bytes to bw written. |
|
// m_nCount - the number of bytes to write. |
|
//Output : Returns the number of bytes written. If there wa insufficient space |
|
// to write all requested bytes, the value returned will be less than |
|
// the requested amount. |
|
//Author : DSpeyrer |
|
//------------------------------------------------------------------------------ |
|
int CCircularBuffer::Write(void *pData, int nBytesRequested) |
|
{ |
|
// Write all the data. |
|
int nBytesToWrite = nBytesRequested; |
|
char *pDataToWrite = (char*)pData; |
|
|
|
while(nBytesToWrite) |
|
{ |
|
int from = m_nWrite; |
|
int to = m_nWrite + nBytesToWrite; |
|
|
|
if(to >= m_nSize) |
|
{ |
|
to = m_nSize; |
|
} |
|
|
|
memcpy(&m_chData[from], pDataToWrite, to - from); |
|
pDataToWrite += to - from; |
|
|
|
m_nWrite = to % m_nSize; |
|
nBytesToWrite -= to - from; |
|
} |
|
|
|
// Did it cross the read pointer? Then slide the read pointer up. |
|
// This way, we will discard the old data. |
|
if(nBytesRequested > (m_nSize - m_nCount)) |
|
{ |
|
m_nCount = m_nSize; |
|
m_nRead = m_nWrite; |
|
} |
|
else |
|
{ |
|
m_nCount += nBytesRequested; |
|
} |
|
|
|
AssertValid(); |
|
return nBytesRequested; |
|
} |
|
|
|
CCircularBuffer *AllocateCircularBuffer( int nSize ) |
|
{ |
|
char *pBuff = (char *)malloc( sizeof( CCircularBuffer ) + nSize - 1 ); |
|
|
|
CCircularBuffer *pCCircularBuffer = (CCircularBuffer *)pBuff; |
|
|
|
pCCircularBuffer->SetSize( nSize ); |
|
return pCCircularBuffer; |
|
} |
|
|
|
void FreeCircularBuffer( CCircularBuffer *pCircularBuffer ) |
|
{ |
|
free( (char*)pCircularBuffer ); |
|
} |
|
|
|
|