C++环形缓冲区RingBuffer的简单实现
为了项目中编写上位机软件,刚开始学习C++,把C语言中用到的环形缓冲区封装成了类。
为什么需要缓冲区,参考生产者 消费者模式
ringbuffer.h
#ifndef QRINGBUFFER_H
#define QRINGBUFFER_H
#include <cstring>
#ifndef RB_MAX_LEN
#define RB_MAX_LEN 2048
#endif
#define min(a, b) (a)<(b)?(a):(b) //求最小
class QRingBuffer
{
public:
QRingBuffer(int size = RB_MAX_LEN);
~QRingBuffer();
int canRead(); //how much can read
int canWrite(); //how much can write
int read(void *data, int count); //read data frome ringbuffer
int write(const void *data, int count);
int size();
private:
int bufferSize; //buffer size
unsigned char *rbBuf = new unsigned char [bufferSize];
/*环形缓冲区变量*/
int rbCapacity; //容量
unsigned char *rbHead;
unsigned char *rbTail;
unsigned char *rbBuff;
};
#endif // QRINGBUFFER_H
ringbuffer.cpp
#include "qringbuffer.h"
/**
* @brief QRingBuffer::QRingBuffer
* @param buffersize Byte
*/
QRingBuffer::QRingBuffer(int size)
{
bufferSize = size;
rbCapacity = size;
rbBuff = rbBuf;
rbHead = rbBuff;
rbTail = rbBuff;
}
QRingBuffer::~QRingBuffer()
{
rbBuff = nullptr;
rbHead = nullptr;
rbTail = nullptr;
rbCapacity = 0;
delete []rbBuf; //释放缓冲区
}
/**
* @brief QRingBuffer::rbCanRead
* @return 缓冲区可读字节数
*/
int QRingBuffer::canRead()
{
//ring buufer is null, return -1
if((nullptr == rbBuff)||(nullptr == rbHead)||(nullptr == rbTail))
{
return -1;
}
if (rbHead == rbTail)
{
return 0;
}
if (rbHead < rbTail)
{
return rbTail - rbHead;
}
return rbCapacity - (rbHead - rbTail);
}
/**
* @brief QRingBuffer::rbCanWrite 缓冲区剩余可写字节数
* @return 可写字节数
*/
int QRingBuffer::canWrite()
{
if((nullptr == rbBuff)||(nullptr == rbHead)||(nullptr == rbTail))
{
return -1;
}
return rbCapacity - canRead();
}
/**
* @brief QRingBuffer::read 从缓冲区读数据
* @param 目标数组地址
* @param 读的字节数
* @return
*/
int QRingBuffer::read(void *data, int count)
{
int copySz = 0;
if((nullptr == rbBuff)||(nullptr == rbHead)||(nullptr == rbTail))
{
return -1;
}
if(nullptr == data)
{
return -1;
}
if (rbHead < rbTail)
{
copySz = min(count, canRead());
memcpy(data, rbHead, copySz);
rbHead += copySz;
return copySz;
}
else
{
if (count < rbCapacity-(rbHead - rbBuff))
{
copySz = count;
memcpy(data, rbHead, copySz);
rbHead += copySz;
return copySz;
}
else
{
copySz = rbCapacity - (rbHead - rbBuff);
memcpy(data, rbHead, copySz);
rbHead = rbBuff;
copySz += read((unsigned char *)data+copySz, count-copySz);
return copySz;
}
}
}
/**
* @brief QRingBuffer::write
* @param 数据地址
* @param 要写的字节数
* @return 写入的字节数
*/
int QRingBuffer::write(const void *data, int count)
{
int tailAvailSz = 0;
if((nullptr == rbBuff)||(nullptr == rbHead)||(nullptr == rbTail))
{
return -1;
}
if(nullptr == data)
{
return -1;
}
if (count >= canWrite())
{
return -1;
}
if (rbHead <= rbTail)
{
tailAvailSz = rbCapacity - (rbTail - rbBuff);
if (count <= tailAvailSz)
{
memcpy(rbTail, data, count);
rbTail += count;
if (rbTail == rbBuff+rbCapacity)
{
rbTail = rbBuff;
}
return count;
}
else
{
memcpy(rbTail, data, tailAvailSz);
rbTail = rbBuff;
return tailAvailSz + write((char*)data+tailAvailSz, count-tailAvailSz);
}
}
else
{
memcpy(rbTail, data, count);
rbTail += count;
return count;
}
}
/**
* @brief QRingBuffer::size
* @return 缓冲区大小
*/
int QRingBuffer::size()
{
return bufferSize;
}
简单测试一下:
main.cpp
#include <QCoreApplication>
#include <iostream>
#include "qringbuffer.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QRingBuffer buffer;
cout<<"buffer size:"<<buffer.size()<<endl;
char data1[48] = {0x55};
char data2[8] = {0};
cout<<"buffer can read:"<<buffer.canRead()<<endl;
cout<<"buffer can write:"<<buffer.canWrite()<<endl;
cout<<"buffer writing..."<<endl;
buffer.write(data1,sizeof(data1));
cout<<"buffer can read:"<<buffer.canRead()<<endl;
cout<<"buffer can write:"<<buffer.canWrite()<<endl;
cout<<"buffer reading..."<<endl;
buffer.read(data2,8);
cout<<"buffer can read:"<<buffer.canRead()<<endl;
cout<<"buffer can write:"<<buffer.canWrite()<<endl;
cout<<"HelloWorld!"<<endl;
return a.exec();
}