循环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;
}