diff --git a/include/HSendBuffer.h b/include/HSendBuffer.h new file mode 100644 index 0000000..527a536 --- /dev/null +++ b/include/HSendBuffer.h @@ -0,0 +1,83 @@ +/** + * 日期: 2026-03-31 + * 作者: coffee + * 描述: 基于 HMem 的发送缓冲区 + * 默认预留前头空间, 便于上层先构建内容, 下层再补发包前头 + */ + +#ifndef __H_SEND_BUFFER_H__ +#define __H_SEND_BUFFER_H__ + +#include +#include + +/** + * @brief 默认预留的前头空间 + */ +#ifndef HSEND_BUFFER_FIRST_OFFSET +#define HSEND_BUFFER_FIRST_OFFSET 30u +#endif + +/** + * @brief 创建发送缓冲区 + * @param size 初始可用数据区大小 + * @return 成功返回数据区指针, 失败返回 NULL + */ +void *HSendBufferGet(size_t size); + +/** + * @brief 调整发送缓冲区当前使用长度 + * @param ptr 发送缓冲区指针 + * @param size 新的当前数据长度(包含已经补上的前头) + * @return 成功返回新的缓冲区指针, 失败返回 NULL + */ +void *HSendBufferRealloc(void *ptr, size_t size); + +/** + * @brief 往前头追加数据 + * @param ptr 发送缓冲区指针 + * @param data 要写入前头的数据, 传 NULL 时仅预留空间 + * @param size 前头追加长度 + * @return + * - 成功返回新的缓冲区指针 + * - 前头空间不足时返回原指针 + * - 非法指针返回 NULL + */ +void *HSendBufferAddHead(void *ptr, const void *data, uint8_t size); + +/** + * @brief 增加引用计数 + * @param ptr 发送缓冲区指针 + * @return 成功返回原指针, 失败返回 NULL + */ +void *HSendBufferAddRef(void *ptr); + +/** + * @brief 释放发送缓冲区 + * @param ptr 发送缓冲区指针 + * @return 成功返回1, 失败返回0 + */ +uint8_t HSendBufferFree(void *ptr); + +/** + * @brief 判断是否为 HSendBuffer + * @param ptr 待判断指针 + * @return 是返回1, 否返回0 + */ +uint8_t HSendBufferIsValid(const void *ptr); + +/** + * @brief 获取当前剩余前头偏移 + * @param ptr 发送缓冲区指针 + * @return 偏移量, 非法指针返回0 + */ +uint8_t HSendBufferGetFrontOffset(const void *ptr); + +/** + * @brief 获取当前前头剩余大小 + * @param ptr 发送缓冲区指针 + * @return 剩余前头大小, 非法指针返回0 + */ +uint8_t HSendBufferGetHeadRemainSize(const void *ptr); + +#endif // __H_SEND_BUFFER_H__ diff --git a/src/HSendBuffer.c b/src/HSendBuffer.c new file mode 100644 index 0000000..c62e563 --- /dev/null +++ b/src/HSendBuffer.c @@ -0,0 +1,189 @@ +/** + * 日期: 2026-03-31 + * 作者: coffee + * 描述: 基于 HMem 的发送缓冲区实现 + */ + +#include "HSendBuffer.h" +#include "HMem.h" + +#include + +#define HSEND_BUFFER_MAGIC 0xA5u +#define HSEND_BUFFER_INFO_SIZE 2u + +typedef struct HSendBufferInfo { + uint8_t magic; + uint8_t frontOffset; +} HSendBufferInfo; + +static HSendBufferInfo *GetInfo(const void *ptr) { + if (ptr == NULL) { + return NULL; + } + + return (HSendBufferInfo *)((uint8_t *)ptr - HSEND_BUFFER_INFO_SIZE); +} + +static uint8_t IsValidInfo(const HSendBufferInfo *info) { + if (info == NULL) { + return 0; + } + + return info->magic == HSEND_BUFFER_MAGIC; +} + +static uint8_t *GetRawPtr(const void *ptr) { + HSendBufferInfo *info = GetInfo(ptr); + if (!IsValidInfo(info)) { + return NULL; + } + + return (uint8_t *)ptr - info->frontOffset - HSEND_BUFFER_INFO_SIZE; +} + +static uint8_t *GetUserPtr(void *rawPtr, uint8_t frontOffset) { + if (rawPtr == NULL) { + return NULL; + } + + return (uint8_t *)rawPtr + HSEND_BUFFER_INFO_SIZE + frontOffset; +} + +static void SetInfo(void *ptr, uint8_t frontOffset) { + HSendBufferInfo *info = GetInfo(ptr); + info->magic = HSEND_BUFFER_MAGIC; + info->frontOffset = frontOffset; +} + +void *HSendBufferGet(size_t size) { + size_t totalSize = HSEND_BUFFER_INFO_SIZE + HSEND_BUFFER_FIRST_OFFSET + size; + uint8_t *rawPtr = HMemMalloc(totalSize); + uint8_t *userPtr; + + if (rawPtr == NULL) { + return NULL; + } + + userPtr = GetUserPtr(rawPtr, HSEND_BUFFER_FIRST_OFFSET); + SetInfo(userPtr, HSEND_BUFFER_FIRST_OFFSET); + + return userPtr; +} + +void *HSendBufferRealloc(void *ptr, size_t size) { + HSendBufferInfo *info; + uint8_t frontOffset; + uint8_t *rawPtr; + uint8_t *newRawPtr; + size_t totalSize; + + if (ptr == NULL) { + return HSendBufferGet(size); + } + + info = GetInfo(ptr); + if (!IsValidInfo(info)) { + return NULL; + } + + if (size == 0u) { + HSendBufferFree(ptr); + return NULL; + } + + frontOffset = info->frontOffset; + + rawPtr = GetRawPtr(ptr); + if (rawPtr == NULL) { + return NULL; + } + + totalSize = HSEND_BUFFER_INFO_SIZE + frontOffset + size; + newRawPtr = HMemRealloc(rawPtr, totalSize); + if (newRawPtr == NULL) { + return NULL; + } + + ptr = GetUserPtr(newRawPtr, frontOffset); + SetInfo(ptr, frontOffset); + + return ptr; +} + +void *HSendBufferAddHead(void *ptr, const void *data, uint8_t size) { + HSendBufferInfo *info; + uint8_t newFrontOffset; + uint8_t *newPtr; + + if (ptr == NULL) { + return NULL; + } + + info = GetInfo(ptr); + if (!IsValidInfo(info)) { + return NULL; + } + + if (size > info->frontOffset) { + return ptr; + } + + if (size == 0u) { + return ptr; + } + + newFrontOffset = (uint8_t)(info->frontOffset - size); + newPtr = (uint8_t *)ptr - size; + info->magic = 0u; + + if (data != NULL) { + memmove(newPtr, data, size); + } + + SetInfo(newPtr, newFrontOffset); + + return newPtr; +} + +void *HSendBufferAddRef(void *ptr) { + uint8_t *rawPtr = GetRawPtr(ptr); + + if (rawPtr == NULL) { + return NULL; + } + + if (HMemAddRef(rawPtr, 0) == NULL) { + return NULL; + } + + return ptr; +} + +uint8_t HSendBufferFree(void *ptr) { + uint8_t *rawPtr = GetRawPtr(ptr); + + if (rawPtr == NULL) { + return 0; + } + + return HMemFree(rawPtr); +} + +uint8_t HSendBufferIsValid(const void *ptr) { + return IsValidInfo(GetInfo(ptr)); +} + +uint8_t HSendBufferGetFrontOffset(const void *ptr) { + HSendBufferInfo *info = GetInfo(ptr); + + if (!IsValidInfo(info)) { + return 0; + } + + return info->frontOffset; +} + +uint8_t HSendBufferGetHeadRemainSize(const void *ptr) { + return HSendBufferGetFrontOffset(ptr); +}