循环缓冲区(循环buffer)的原理及实现

循环buffer的实现方式多种多样,我这里主要讲一种基于数组的循环buffer实现方式。
在这里插入图片描述
循环buffer原理如上图,在数据写满整个数组后将数据放入最开始再次写入。需要保证读指针小于等于写指针。
话不多说,直接上代码:

ringbuffer.h
#ifndef RING_BUFFER_H_
#define RING_BUFFER_H_
#include <cstring>
#include <cstdio>
#define BUFFER_SIZE 1024*1024
typedef struct {
    int   size; 									//缓冲区大小
    int   wr_point;  							//写指针
    int   rd_point;    						//读指针
    char  elems[0];  						//数据
} RingBuffer;

class CRingBuffer
{
    public:
        CRingBuffer();
        ~CRingBuffer();
        void RBInit(RingBuffer* rb, int size);						//循环buffer初始化
        void RBWrite(RingBuffer* rb, char *buf, int len);			//写入数据,需要RingBuffer类型指针、写入的数据以及数据长度
        void RBRead(RingBuffer* rb, char *buf, int len);			//读出数据,需要RingBuffer类型指针、读出数据缓冲区以及数据长度
        int  RBDataSize(RingBuffer* rb);							//有效数据的大小
        void Rd_Point(RingBuffer* rb, int num);						//将读指针回调num个数据

    private:
        int    RBFreeSize(RingBuffer* rb);
};
#endif
ringbuffer.cpp
#include "ringbuffer.h"
using namespace std;

CRingBuffer::CRingBuffer()
{

}

CRingBuffer::~CRingBuffer()
{

}

/*对结构体进行初始化,还需要对存储数据的数组分配内存,可以放入初始化,也可以写在外面*/
void CRingBuffer::RBInit(RingBuffer* rb, int size)
{
    rb->rd_point = 0;
    rb->wr_point = 0;
    rb->size = size;
}

/*获取数据大小*/
int  CRingBuffer::RBDataSize(RingBuffer* rb)
{
    return (rb->wr_point - rb->rd_point) & (rb->size - 1);
}
/*获取空闲大小*/
int  CRingBuffer::RBFreeSize(RingBuffer* rb)
{
    return rb->size -1 - RBDataSize(rb);
}
/*写入len长度的数据*/
void CRingBuffer::RBWrite(RingBuffer* rb, char *buf, int len)
{
    int freeSize = RBFreeSize(rb);  
    int point = 0;          				//指针位置
    //printf("free size:%d\n",freeSize);
    
    if (len > freeSize)     
    {
        len = freeSize;  					//输入超过空闲空间,自动截断
    }
    else
    {
        freeSize = len;
    }

    point = rb->wr_point;

    if (point + len > rb->size)    			//如果写入的数据加上超过循环buf大小
    {
        memcpy(rb->elems + point, buf, rb->size - point);   //先拷贝未超过那部分,剩下的写入前面那部分空闲空间
        buf += rb->size-point; 
        len -= rb->size-point;
        point = 0;
    }

    memcpy(rb->elems + point,buf,len);
    rb->wr_point = point + len;   //设置写指针位置
    //printf("rb write:%d\n",rb->wr_point);
}
/*读出len长度的数据*/
void CRingBuffer::RBRead(RingBuffer* rb, char *buf, int len)
{
    int dataSize = RBDataSize(rb);
    int point = 0;

    if (len > dataSize)
    {
        len = dataSize;
    }
    else 
    {
        dataSize = len;
    }

    point = rb->rd_point;
    if (point + len > rb->size)
    {   

        memcpy(buf,rb->elems + point,rb->size - point);
        buf +=rb->size - point;
        len -=rb->size - point;
        point = 0;
    }

    memcpy(buf,rb->elems + point,len);
    rb->rd_point = point + len;
}
/*将读指针向后偏移num个数据*/
void CRingBuffer::Rd_Point(RingBuffer* rb, int num)
{
    if (rb->rd_point < num)
    {
        num = num - rb->rd_point;
        rb->rd_point = BUFFER_SIZE - 1;
    }
    rb->rd_point = rb->rd_point - num;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值