1. 增加环状缓冲区

This commit is contained in:
coffee 2025-04-13 19:32:09 +08:00
parent c014737966
commit 28aa36f70f
2 changed files with 318 additions and 0 deletions

117
include/HRingBuffer.h Normal file
View File

@ -0,0 +1,117 @@
/**
* : 2025-04-13
* : coffee
* :
*/
#ifndef _H_RING_BUFFER_H_
#define _H_RING_BUFFER_H_
#include <stdint.h>
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_

201
src/HRingBuffer.c Normal file
View File

@ -0,0 +1,201 @@
#include <HRingBuffer.h>
#include <string.h>
#ifndef LogD
#if 0
#include <stdio.h>
#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;
}