1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
#ifndef __XNCYCLICBUFFER_H__
#define __XNCYCLICBUFFER_H__
#include <XnOS.h>
namespace xn
{
class CyclicBuffer
{
public:
CyclicBuffer()
{
m_pBuffer = NULL;
m_nBegin = 0;
m_nEnd = 0;
m_nBufferSize = 0;
}
~CyclicBuffer()
{
Shutdown();
}
XnStatus Init(XnUInt32 nMaxSize)
{
//Allocate +1 byte for end marker
m_nBufferSize = nMaxSize + 1;
m_pBuffer = reinterpret_cast<XnUInt8*>(xnOSMallocAligned(m_nBufferSize, XN_DEFAULT_MEM_ALIGN));
XN_VALIDATE_ALLOC_PTR(m_pBuffer);
m_nBegin = 0;
m_nEnd = 0;
return XN_STATUS_OK;
}
void Shutdown()
{
XN_ALIGNED_FREE_AND_NULL(m_pBuffer);
}
XnBool IsFull() const
{
return (((m_nEnd + 1) % m_nBufferSize) == m_nBegin);
}
XnStatus Add(const XnUInt8* pSrc, XnUInt32 nSrcSize)
{
if (nSrcSize > m_nBufferSize - 1)
{
return XN_STATUS_INPUT_BUFFER_OVERFLOW;
}
//Make more room for new data by moving the beginning of the buffer forward if needed.
XnUInt32 nMissingSpace = XN_MAX((XnInt32)(nSrcSize - m_nBufferSize + GetSize()), 0);
m_nBegin = ((m_nBegin + nMissingSpace) % m_nBufferSize);
//First copy either whole source or as much of it that fits between m_nEnd and buffer end.
//Then we copy the remaining bytes (if any) to the beginning of the buffer.
XnUInt32 nSize1 = XN_MIN(nSrcSize, m_nBufferSize - m_nEnd);
XnUInt32 nSize2 = (nSrcSize - nSize1);
xnOSMemCopy(m_pBuffer + m_nEnd, pSrc, nSize1);
xnOSMemCopy(m_pBuffer, pSrc + nSize1, nSize2);
m_nEnd = (m_nEnd + nSrcSize) % m_nBufferSize;
return XN_STATUS_OK;
}
//nDestSize is max size on input, actual size on output.
XnStatus Flush(XnUInt8* pDest, XnUInt32& nDestSize)
{
XnInt32 nDiff = (m_nEnd - m_nBegin);
if (nDiff > 0)
{
if (XnUInt32(nDiff) > nDestSize)
{
return XN_STATUS_OUTPUT_BUFFER_OVERFLOW;
}
xnOSMemCopy(pDest, m_pBuffer + m_nBegin, nDiff);
nDestSize = nDiff;
}
else if (nDiff < 0)
{
if ((m_nBufferSize + nDiff) > nDestSize)
{
return XN_STATUS_OUTPUT_BUFFER_OVERFLOW;
}
xnOSMemCopy(pDest, m_pBuffer + m_nBegin, m_nBufferSize - m_nBegin);
xnOSMemCopy(pDest + m_nBufferSize - m_nBegin, m_pBuffer, m_nEnd);
nDestSize = m_nBufferSize + nDiff;
}
else
{
nDestSize = 0;
}
m_nBegin = 0;
m_nEnd = 0;
return XN_STATUS_OK;
}
XnUInt32 GetSize() const
{
XnInt32 nDiff = (m_nEnd - m_nBegin);
if (nDiff >= 0)
{
return nDiff;
}
else
{
return m_nBufferSize + nDiff;
}
}
private:
XnUInt8* m_pBuffer;
XnUInt32 m_nBufferSize;
XnUInt32 m_nBegin;
XnUInt32 m_nEnd;
};
}
#endif // __XNCYCLICBUFFER_H__
|