环形缓冲区在平时开发中很常用到,尤其是网络编程中。
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#define BUFFER_SIZE 1024 //初始缓冲区大小
class RingBuffer
{
public:
RingBuffer();
~RingBuffer();
public:
int getDataLen(); //获得缓冲区中数据大小
bool reBufferSize(int nLen); //调整缓冲区大小
bool addMsg(char *pBuf, int nLen); //添加消息到缓冲区
void poll(int nLen); //移除缓冲区首部的第一个数据包
void reset(); //缓冲区复位
private:
char *m_pBuffer; //缓冲区
int m_nBufferSize; //缓冲区大小
int m_nStart; //数据开始位置
int m_nEnd; //数据结束位置
bool m_isFull; //缓冲区是否已满
bool m_isEmpty; //缓冲区是否为空
};
#endif // RINGBUFFER_H
#include "ringbuffer.h"
#include "string.h"
#include <QException>
RingBuffer::RingBuffer()
{
m_nBufferSize = BUFFER_SIZE; //缓冲区大小
m_nStart = 0; //数据开始位置
m_nEnd = 0; //数据结束位置
m_isFull = false; //缓冲区是否已满
m_isEmpty = true; //缓冲区是否为空
m_pBuffer = new char[m_nBufferSize]; //分配缓冲区
memset(m_pBuffer, 0, sizeof(m_pBuffer)); //清空缓冲区
}
RingBuffer::~RingBuffer()
{
delete [] m_pBuffer;
m_pBuffer = NULL;
m_nBufferSize = 0;
}
int RingBuffer::getDataLen()
{
if(m_isFull)
{
return m_nBufferSize;
}
else if(m_nEnd < m_nStart)
{
return (m_nBufferSize - m_nStart) + m_nEnd;
}
else
{
return m_nEnd - m_nStart;
}
}
bool RingBuffer::reBufferSize(int nLen)
{
char *oBuffer = m_pBuffer; //保存原缓冲区地址
try
{
nLen = nLen < 64 ? 64: nLen; //保证最小大小
while(m_nBufferSize < nLen)
{
m_nBufferSize *= 2;
}
m_pBuffer = new char[m_nBufferSize]; //分配新缓冲区
memset(m_pBuffer, 0, sizeof(m_pBuffer));
//将原缓冲区中的内容拷贝到新缓冲区
if(m_nStart < m_nEnd)
{
memcpy(m_pBuffer, oBuffer + m_nStart, m_nEnd - m_nStart);
}
else
{
int len1 = m_nBufferSize - m_nStart;
memcpy(m_pBuffer, oBuffer + m_nStart, len1);
memcpy(m_pBuffer + len1, oBuffer, m_nEnd);
}
delete []oBuffer;
}
catch(QException e)
{
return false;
}
return true;
}
bool RingBuffer::addMsg(char *pBuf, int nLen)
{
try
{
if(nLen == 0 || pBuf == NULL)
{
return false;
}
if(getDataLen() + nLen > m_nBufferSize) //如果缓冲区过小,重新调整其大小
{
reBufferSize(getDataLen() + nLen);
memcpy(m_pBuffer + m_nEnd, pBuf, nLen); //将数据添加到缓冲区尾
m_nEnd += nLen;
m_isFull = m_nStart == m_nEnd;
}
else if(m_nStart <= m_nEnd)
{
int rightLen = m_nBufferSize - m_nEnd; //缓冲区右半部分长度
if(nLen <= rightLen)
{
memcpy(m_pBuffer + m_nEnd, pBuf, nLen);
m_nEnd += nLen;
m_isFull = m_nStart == m_nEnd;
}
else
{
int leftLen = nLen - rightLen; //剩余数据长度
memcpy(m_pBuffer + m_nEnd, pBuf, rightLen);
memcpy(m_pBuffer, pBuf, leftLen);
m_nEnd = leftLen;
m_isFull = m_nStart == m_nEnd;
}
}
else
{
memcpy(m_pBuffer + m_nEnd, pBuf, nLen);
m_nEnd += nLen;
m_isFull = m_nStart == m_nEnd;
}
m_isEmpty = false;
}
catch(QException e)
{
return false;
}
return true;
}
void RingBuffer::reset()
{
if(!m_isEmpty)
{
memset(m_pBuffer, 0, sizeof(m_pBuffer));
m_nStart = 0;
m_nEnd = 0;
}
}
//移除缓冲区首部第一个数据包
void RingBuffer::poll(int nLen)
{
if(m_isEmpty || getDataLen() < nLen || nLen == 0 || m_pBuffer == NULL)
{
return;
}
if(m_nStart < m_nEnd)
{
m_nStart += nLen;
m_isEmpty = m_nStart == m_nEnd;
}
else
{
int rightLen;
if(m_nStart == m_nEnd)
{
rightLen = m_nBufferSize - m_nEnd;
}
else
{
rightLen = m_nBufferSize - m_nStart;
}
if(nLen <= rightLen)
{
m_nStart += nLen;
m_isEmpty = m_nStart == m_nEnd;
}
else
{
int leftLen = nLen - rightLen;
m_nStart = leftLen;
m_isEmpty = m_nStart == m_nEnd;
}
}
}