C++实现环形缓冲区

环形缓冲区在平时开发中很常用到,尤其是网络编程中。

#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;
        }
    }
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值