リングバッファringbuffer c++クラステンプレート実装
27333 ワード
@ringbuffer
リングバッファringbuffer c++クラステンプレート実装
使用方法:1、ringBuffer.hファイルを開発工程にコピーし、対応するヘッダファイル2を追加し、g++コンパイラを必要とし(開発したプロジェクト工程はサポートが必要)、このようなテンプレート3、int、char、boolなどのタイプをコンパイルするは、組み込み型のusart、spi、iic、canなどの通信バッファなどの小型データ量の通信バッファ確立に適している.
リングバッファringbuffer c++クラステンプレート実装
使用方法:1、ringBuffer.hファイルを開発工程にコピーし、対応するヘッダファイル2を追加し、g++コンパイラを必要とし(開発したプロジェクト工程はサポートが必要)、このようなテンプレート3、int、char、boolなどのタイプをコンパイルする
#pragma once
#include "stdlib.h"
#include
#define MAX_ASK_FOR_CAP (1 << 16) // 64K
struct BufferInfo{
BufferInfo(unsigned int r = 0, unsigned int w = 0, unsigned int c = 0)
: read(r)
, write(w)
, capacity(c)
, mask(c - 1)
{
}
unsigned int read; // read index in buffer
unsigned int write; // write index in buffer
unsigned int capacity; // capacity of the buffer
unsigned int mask; // mask of the capacity
};
template <typename T>
class RingBuffer
{
public:
RingBuffer(unsigned int bufCap = 0)
: buffer(NULL)
{
create(bufCap);
}
~RingBuffer()
{
destroy();
}
/**
* @brief create create one buffer
* @param bufCap buffer capacity
* @return return true if successful
*/
bool create(unsigned int bufCap)
{
if (bufCap == 0)
{
return false;
}
if (buffer != NULL)
{
delete buffer;
buffer = NULL;
}
unsigned int length = bufCap;
unsigned int n = 1;
while (length > n)
{
n *= 2;
if (n > MAX_ASK_FOR_CAP)
{
return false;
}
}
length = n;
buffer = new T[length];
bufferInfo.read = 0;
bufferInfo.write = 0;
bufferInfo.capacity = length;
bufferInfo.mask = bufferInfo.capacity - 1;
return true;
}
/**
* @brief push write one data of T type into the buffer
* @param data one data of T type
* @return return true if successful
*/
bool push(const T &data)
{
if (isFull() == true)
{
return false;
}
int num = memcpy((buffer + bufferInfo.write * sizeof(T)),
reinterpret_cast<void*>(&data), sizeof(T));
if (num == sizeof(T))
{
bufferInfo.write += 1;
return true;
}
return false;
}
/**
* @brief push write serival data of T type into the buffer
* @param data serival data of T type
* @param len length of data
* @return num of writing to buffer successfully
*/
unsigned int push(const T *data, unsigned int len)
{
if (isFull() == true)
{
return 0;
}
unsigned int space = availableToWrite();
if (len > space)
{
len = space;
}
int num = memcpy((buffer + bufferInfo.write * sizeof(T)),
reinterpret_cast<void*>(data), len * sizeof(T));
bufferInfo.write += num;
return num;
}
/**
* @brief pop remove oldest data of the buffer
* @param num num of the removed data
* @return num of the successful removed data
*/
unsigned int pop(unsigned int num)
{
if (isEmpty() == true)
{
return 0;
}
unsigned int count = availableToRead();
if (num < count)
{
bufferInfo.read += num;
return num;
}
bufferInfo.read = bufferInfo.write = 0;
return count;
}
/**
* @brief takeTail get oldest data of the buffer and remove it
* @return the data of T type
*/
T takeTail()
{
if (isEmpty() == true)
{
return;
}
T data = buffer[bufferInfo.read * sizeof(T)];
pop(1);
return data;
}
/**
* @brief read read some oldest data of the buffer and remove them
* @param buf read the data to this buf.
* @param len read length
* @return read legth successfully
*/
unsigned int read(T &buf, unsigned int len)
{
if (sizeof(buf) < len)
{
len = sizeof(buf);
}
unsigned int count = 0;
while (isEmpty() == false)
{
buf[count++] = this->buffer[bufferInfo.read * sizeof(T)];
pop(1);
if (count >= len)
{
break;
}
}
return count;
}
private:
/**
* @brief destroy destroy the buffer created
*/
void destroy()
{
if (buffer == NULL)
{
return;
}
delete buffer;
buffer = NULL;
}
/**
* @brief isFull if be full of the buffer
* @return return true if successful
*/
inline bool isFull() const
{
if (0 == availableToWrite())
{
return true;
}
return false;
}
/**
* @brief isEmpty if be empty of the buffer
* @return return true if successful
*/
inline bool isEmpty() const
{
if (0 == availableToRead())
{
return true;
}
return false;
}
/**
* @brief availableToRead available buffer to read
* @return num of available buffer to read
*/
inline unsigned int availableToRead() const
{
return (bufferInfo.write & bufferInfo.mask) - (bufferInfo.read & bufferInfo.mask);
}
/**
* @brief availableToWrite available buffer to write
* @return num of available buffer to write
*/
inline unsigned int availableToWrite() const
{
return bufferInfo.mask - bufferInfo.mask & bufferInfo.write;
}
T *buffer;
BufferInfo bufferInfo;
};