diff --git a/include/HRingBuffer.h b/include/HRingBuffer.h new file mode 100644 index 0000000..3f8f934 --- /dev/null +++ b/include/HRingBuffer.h @@ -0,0 +1,117 @@ +/** + * 日期: 2025-04-13 + * 作者: coffee + * 描述: 环转缓冲区 + */ + +#ifndef _H_RING_BUFFER_H_ +#define _H_RING_BUFFER_H_ + + +#include + + +enum eRingBufferFlag { + kHRingBufferFlag8 = 0x01, // 数据8位 + kHRingBufferFlag16 = 0x02, // 数据16位 + kHRingBufferFlag32 = 0x04, // 数据32位 + + kHRingBufferFlagAllMask = 0x07, // 数据掩码 + + kHRingBufferFull = 0x40, // 环转缓冲区满 + kHRingBufferNeedInit = 0x80, // 需要初始化 +}; + + +typedef uint8_t HRingBufferType; // 环转缓冲区类型 +typedef uint32_t HRingBufferDataType; // 环转缓冲区统一数据类型 + + +#ifdef _HRING_BUFFER_LEN_USE32 +#define HRING_BUFFER_ERROR (0xffffffff) +typedef uint32_t HRingBufferLenType; +#elif defined(_HRING_BUFFER_LEN_USE16) +#define HRING_BUFFER_ERROR (0xffff) +typedef uint16_t HRingBufferLenType; +#else +#define HRING_BUFFER_ERROR (0xff) +typedef uint8_t HRingBufferLenType; +#endif + +typedef struct __attribute__ ((__packed__)) _HRingBufferBase { + volatile uint8_t flag; + HRingBufferLenType len; + volatile HRingBufferLenType start; + volatile HRingBufferLenType end; +} _HRingBufferBase; + + +typedef struct __attribute__ ((__packed__)) _HRingBuffer8 { + _HRingBufferBase base; + uint8_t data[0]; +} _HRingBuffer8; + +typedef struct __attribute__ ((__packed__)) _HRingBuffer16 { + _HRingBufferBase base; + uint16_t data[0]; +} _HRingBuffer16; + +typedef struct __attribute__ ((__packed__)) _HRingBuffer32 { + _HRingBufferBase base; + uint32_t data[0]; +} _HRingBuffer32; + +// 用于辅助多类型数值计算 +#ifdef _HRING_BUFFER_LEN_USE32 +#define _HRING_BUFFER_INIT_SIZE(size) ((size >> 24) & 0xff), ((size >> 16) & 0xff), ((size >> 8) & 0xff), (size & 0xff) +#define _HRING_BUFFER_INIT_SIZE_INIT(size) ((size[0] << 24) | (size[1] << 16) | (size[2] << 8) | (size[3] & 0xff)) +#elif defined(_HRING_BUFFER_LEN_USE16) +#define _HRING_BUFFER_INIT_SIZE(size) ((size >> 8) & 0xff), (size & 0xff) +#define _HRING_BUFFER_INIT_SIZE_INIT(size) ((size[0] << 8) | (size[1] & 0xff)) +#else +#define _HRING_BUFFER_INIT_SIZE(size) (size & 0xff) +#define _HRING_BUFFER_INIT_SIZE_INIT(size) (size[0] & 0xff) +#endif + +// 计算环形缓冲区的内存大小 +#define _HRING_BUFFER_CALC_LEN8(len) (sizeof(_HRingBuffer8) + (len) * sizeof(uint8_t)) +#define _HRING_BUFFER_CALC_LEN16(len) (sizeof(_HRingBuffer16) + (len) * sizeof(uint16_t)) +#define _HRING_BUFFER_CALC_LEN32(len) (sizeof(_HRingBuffer32) + (len) * sizeof(uint32_t)) +#define _HRING_BUFFER_CALC_LEN(len, type) _HRING_BUFFER_CALC_LEN##type(len) + +// 初始化宏,处理不同的长度类型 +#define _HRING_BUFFER_INIT8(size) { kHRingBufferNeedInit | kHRingBufferFlag8, _HRING_BUFFER_INIT_SIZE(size), _HRING_BUFFER_INIT_SIZE(0), _HRING_BUFFER_INIT_SIZE(0) } +#define _HRING_BUFFER_INIT16(size) { kHRingBufferNeedInit | kHRingBufferFlag16, _HRING_BUFFER_INIT_SIZE(size), _HRING_BUFFER_INIT_SIZE(0), _HRING_BUFFER_INIT_SIZE(0) } +#define _HRING_BUFFER_INIT32(size) { kHRingBufferNeedInit | kHRingBufferFlag32, _HRING_BUFFER_INIT_SIZE(size), _HRING_BUFFER_INIT_SIZE(0), _HRING_BUFFER_INIT_SIZE(0) } +#define _HRING_BUFFER_INIT(size, type) _HRING_BUFFER_INIT##type(size) + +// 定义环形缓冲区变量 +#define HRING_BUFFER_DEFINE(name, size) HRingBufferType name[_HRING_BUFFER_CALC_LEN(size, 8)] = _HRING_BUFFER_INIT(size, 8) +#define HRING_BUFFER_DEFINE16(name, size) HRingBufferType name[_HRING_BUFFER_CALC_LEN(size, 16)] = _HRING_BUFFER_INIT(size, 16) +#define HRING_BUFFER_DEFINE32(name, size) HRingBufferType name[_HRING_BUFFER_CALC_LEN(size, 32)] = _HRING_BUFFER_INIT(size, 32) + +// 添加数据到环形缓冲区, 成功返回1, 失败返回0 +uint8_t HRingBufferAddData(HRingBufferType* buffer, HRingBufferDataType data); + +// 添加数据到环形缓冲区, 当环形缓冲区满时, 会覆盖旧数据, 成功返回1, 失败返回0 +uint8_t HRingBufferAddDataOver(HRingBufferType* buffer, HRingBufferDataType data); + +// 获取指定位置的环形缓冲区数据, 失败返回 HRING_BUFFER_ERROR +HRingBufferDataType HRingBufferGetData(HRingBufferType* buffer, HRingBufferLenType index); + +// 获取环形缓冲区数据, 失败返回 HRING_BUFFER_ERROR +HRingBufferDataType HRingBufferPopData(HRingBufferType* buffer); + +// 获取环形缓冲区数据长度 +HRingBufferLenType HRingBufferGetLen(HRingBufferType* buffer); + +// 获取环形缓冲区数据字节长度 +HRingBufferLenType HRingBufferGetByteLen(HRingBufferType* buffer); + +// 清空环形缓冲区 +void HRingBufferClear(HRingBufferType* buffer); + +// 判断环形缓冲区是否为空 +uint8_t HRingBufferEmpty(HRingBufferType* buffer); + +#endif // _H_RING_BUFFER_H_ diff --git a/src/HRingBuffer.c b/src/HRingBuffer.c new file mode 100644 index 0000000..758c73d --- /dev/null +++ b/src/HRingBuffer.c @@ -0,0 +1,201 @@ + + +#include +#include + + +#ifndef LogD +#if 0 +#include +#define LogD(format, ...) printf("[%s:%s:%d]"format "\r\n", __FILE_NAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define LogD(...) +#endif +#endif + + +static void InitRingBuffer(HRingBufferType *ringBuffer) { + if (ringBuffer == NULL) { + LogD("RingBuffer is NULL"); + return ; + } + + if ((ringBuffer[0] & kHRingBufferNeedInit) == 0) { + return ; + } + + _HRingBufferBase *base = (_HRingBufferBase *)ringBuffer; + base->flag &= ~kHRingBufferNeedInit; + uint8_t *len = (uint8_t *)&base->len; + base->len = _HRING_BUFFER_INIT_SIZE_INIT(len); + len = (uint8_t *)&base->start; + base->start = _HRING_BUFFER_INIT_SIZE_INIT(len); + len = (uint8_t *)&base->end; + base->end = _HRING_BUFFER_INIT_SIZE_INIT(len); +} + +static uint8_t GetRingBufferType(const HRingBufferType *ringBuffer) { + if (ringBuffer == NULL) { + return 0; + } + + InitRingBuffer((HRingBufferType *)ringBuffer); + const _HRingBufferBase *base = (const _HRingBufferBase *)ringBuffer; + return base->flag & kHRingBufferFlagAllMask; +} + +static HRingBufferLenType GetRingBufferTypeSize(const HRingBufferType *vector) { + switch(GetRingBufferType(vector)) { + case kHRingBufferFlag8: return sizeof(uint8_t); break; + case kHRingBufferFlag16: return sizeof(uint16_t); break; + case kHRingBufferFlag32: return sizeof(uint32_t); break; + } + + return 0; +} + +static HRingBufferDataType GetRingBufferData(const HRingBufferType *vector, HRingBufferLenType pos) { + switch(GetRingBufferType(vector)) { + case kHRingBufferFlag8: return ((const _HRingBuffer8 *)vector)->data[pos]; break; + case kHRingBufferFlag16: return ((const _HRingBuffer16 *)vector)->data[pos]; break; + case kHRingBufferFlag32: return ((const _HRingBuffer32 *)vector)->data[pos]; break; + } + + return HRING_BUFFER_ERROR; +} + +static void SetRingBufferData(HRingBufferType *vector, HRingBufferLenType pos, HRingBufferDataType data) { + switch(GetRingBufferType(vector)) { + case kHRingBufferFlag8: ((_HRingBuffer8 *)vector)->data[pos] = (uint8_t)data; break; + case kHRingBufferFlag16: ((_HRingBuffer16 *)vector)->data[pos] = (uint16_t)data; break; + case kHRingBufferFlag32: ((_HRingBuffer32 *)vector)->data[pos] = (uint32_t)data; break; + } +} + +static uint8_t IsRingBufferFull(const HRingBufferType *vector) { + InitRingBuffer((HRingBufferType *)vector); + const _HRingBufferBase *base = (const _HRingBufferBase *)vector; + return (base->flag & kHRingBufferFull) == kHRingBufferFull; +} + +static void SetRingBufferFull(HRingBufferType *vector, uint8_t full) { + InitRingBuffer((HRingBufferType *)vector); + _HRingBufferBase *base = (_HRingBufferBase *)vector; + if (full) { + base->flag |= kHRingBufferFull; + } else { + base->flag &= ~kHRingBufferFull; + } +} + +// 添加数据到环形缓冲区, 成功返回1, 失败返回0 +uint8_t HRingBufferAddData(HRingBufferType* buffer, HRingBufferDataType data) { + if (buffer == NULL) { + return 0; + } + + _HRingBufferBase *base = (_HRingBufferBase *)buffer; + InitRingBuffer(buffer); + if (base->len == 0) { + LogD("buffer len is 0"); + return 0; + } + + // 判断缓冲区是否已满 + if (IsRingBufferFull(buffer)) { + LogD("buffer is full, len[%d], start[%d], end[%d]", base->len, base->start, base->end); + return 0; + } + + SetRingBufferData(buffer, base->end, data); + base->end = (base->end + 1) % base->len; + if (base->end == base->start) { + SetRingBufferFull(buffer, 1); + } + + return 1; +} + +// 添加数据到环形缓冲区, 当环形缓冲区满时, 会覆盖旧数据, 成功返回1, 失败返回0 +uint8_t HRingBufferAddDataOver(HRingBufferType* buffer, HRingBufferDataType data) { + if (IsRingBufferFull(buffer)) { + _HRingBufferBase *base = (_HRingBufferBase *)buffer; + base->start = (base->start + 1) % base->len; + SetRingBufferFull(buffer, 0); + } + + return HRingBufferAddData(buffer, data); +} + +// 获取指定位置的环形缓冲区数据, 失败返回 HRING_BUFFER_ERROR +HRingBufferDataType HRingBufferGetData(HRingBufferType* buffer, HRingBufferLenType index) { + if (buffer == NULL) { + return HRING_BUFFER_ERROR; + } + + if (HRingBufferGetLen(buffer) <= index) { + LogD("error index[%d], len[%d]", index, HRingBufferGetLen(buffer)); + return HRING_BUFFER_ERROR; + } + + _HRingBufferBase *base = (_HRingBufferBase *)buffer; + return GetRingBufferData(buffer, (base->start + index) % base->len); +} + +// 获取环形缓冲区数据, 失败返回 HRING_BUFFER_ERROR +HRingBufferDataType HRingBufferPopData(HRingBufferType* buffer) { + if (HRingBufferGetLen(buffer) == 0) { + return HRING_BUFFER_ERROR; + } + + _HRingBufferBase *base = (_HRingBufferBase *)buffer; + HRingBufferDataType data = GetRingBufferData(buffer, base->start); + base->start = (base->start + 1) % base->len; + if (IsRingBufferFull(buffer)) { + SetRingBufferFull(buffer, 0); + } + + return data; +} + +// 获取环形缓冲区数据长度 +HRingBufferLenType HRingBufferGetLen(HRingBufferType* buffer) { + if (buffer == NULL) { + return 0; + } + + _HRingBufferBase *base = (_HRingBufferBase *)buffer; + InitRingBuffer(buffer); + if (base->end >= base->start) { + if (IsRingBufferFull(buffer)) { + return base->len; + } + + return base->end - base->start; + } + + return base->len - base->start + base->end; +} + +// 获取环形缓冲区数据字节长度 +HRingBufferLenType HRingBufferGetByteLen(HRingBufferType* buffer) { + return HRingBufferGetLen(buffer) * GetRingBufferTypeSize(buffer); +} + +// 清空环形缓冲区 +void HRingBufferClear(HRingBufferType* buffer) { + if (buffer == NULL) { + return ; + } + + _HRingBufferBase *base = (_HRingBufferBase *)buffer; + InitRingBuffer(buffer); + SetRingBufferFull(buffer, 0); + base->start = 0; + base->end = 0; +} + +// 判断环形缓冲区是否为空 +uint8_t HRingBufferEmpty(HRingBufferType* buffer) { + return HRingBufferGetLen(buffer) == 0; +}