434 lines
16 KiB
C
434 lines
16 KiB
C
#include <ctype.h>
|
|||
|
|
#include <c_ByteRingBuffer.h>
|
||
|
|
#include <limits.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
uint8_t c_ByteRingBuffer_GetAtRelativeInternal(const c_ByteRingBuffer_t* self, c_size_t relative_offset) {
|
||
|
|
c_size_t absolute_index = (self->head + relative_offset) % self->capacity;
|
||
|
|
return self->buffer[absolute_index];
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
|
||
|
|
c_err_t c_ByteRingBuffer_Init(c_ByteRingBuffer_t* self, c_size_t capacity, c_Allocator_t* allocator) {
|
||
|
|
if (!self || capacity == 0) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
self->allocator = (allocator != NULL) ? *allocator : c_DefaultAllocator;
|
||
|
|
self->capacity = capacity;
|
||
|
|
self->head = 0;
|
||
|
|
self->tail = 0;
|
||
|
|
self->is_full = C_FALSE;
|
||
|
|
|
||
|
|
self->buffer = (uint8_t*)c_Allocator_Alloc(&self->allocator, self->capacity);
|
||
|
|
if (!self->buffer) return C_ERR_NOMEM;
|
||
|
|
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
void c_ByteRingBuffer_Destroy(c_ByteRingBuffer_t* self) {
|
||
|
|
if (!self) return;
|
||
|
|
if (self->buffer) {
|
||
|
|
c_Allocator_Free(&self->allocator, self->buffer);
|
||
|
|
self->buffer = NULL;
|
||
|
|
}
|
||
|
|
self->capacity = 0;
|
||
|
|
self->head = 0;
|
||
|
|
self->tail = 0;
|
||
|
|
self->is_full = C_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t c_ByteRingBuffer_GetSize(const c_ByteRingBuffer_t* self) {
|
||
|
|
if (!self) return 0;
|
||
|
|
if (self->is_full) return self->capacity;
|
||
|
|
if (self->tail >= self->head) {
|
||
|
|
return self->tail - self->head;
|
||
|
|
}
|
||
|
|
return self->capacity + self->tail - self->head;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_bool_t c_ByteRingBuffer_IsEmpty(const c_ByteRingBuffer_t* self) {
|
||
|
|
if (!self) return C_TRUE;
|
||
|
|
return (self->head == self->tail && !self->is_full) ? C_TRUE : C_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_bool_t c_ByteRingBuffer_IsFull(const c_ByteRingBuffer_t* self) {
|
||
|
|
if (!self) return C_FALSE;
|
||
|
|
return self->is_full;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 单字节单块基础读写
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
c_err_t c_ByteRingBuffer_WriteByte(c_ByteRingBuffer_t* self, uint8_t byte) {
|
||
|
|
if (!self) return C_ERR_PARAM;
|
||
|
|
if (self->is_full) return C_ERR_OUTOFBOUND;
|
||
|
|
|
||
|
|
self->buffer[self->tail] = byte;
|
||
|
|
self->tail = (self->tail + 1) % self->capacity;
|
||
|
|
|
||
|
|
if (self->tail == self->head) {
|
||
|
|
self->is_full = C_TRUE;
|
||
|
|
}
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_ByteRingBuffer_ReadByte(c_ByteRingBuffer_t* self, uint8_t* out_byte) {
|
||
|
|
if (!self || !out_byte) return C_ERR_PARAM;
|
||
|
|
if (c_ByteRingBuffer_IsEmpty(self)) return C_ERR_OUTOFBOUND;
|
||
|
|
|
||
|
|
*out_byte = self->buffer[self->head];
|
||
|
|
self->head = (self->head + 1) % self->capacity;
|
||
|
|
self->is_full = C_FALSE; // 读取一个字节后,必然不再满
|
||
|
|
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 连续缓冲区块合并搬运 (分段 memcpy 核心提速)
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
c_size_t c_ByteRingBuffer_WriteBuffer(c_ByteRingBuffer_t* self, const uint8_t* src, c_size_t len) {
|
||
|
|
if (!self || !src || len == 0 || self->is_full) return 0;
|
||
|
|
|
||
|
|
c_size_t current_size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
c_size_t free_space = self->capacity - current_size;
|
||
|
|
if (len > free_space) {
|
||
|
|
len = free_space; // 裁剪可写长度
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t first_part = self->capacity - self->tail;
|
||
|
|
if (len <= first_part) {
|
||
|
|
memcpy(self->buffer + self->tail, src, len);
|
||
|
|
self->tail = (self->tail + len) % self->capacity;
|
||
|
|
} else {
|
||
|
|
memcpy(self->buffer + self->tail, src, first_part);
|
||
|
|
memcpy(self->buffer, src + first_part, len - first_part);
|
||
|
|
self->tail = len - first_part;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (self->tail == self->head && len > 0) {
|
||
|
|
self->is_full = C_TRUE;
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t c_ByteRingBuffer_ReadBuffer(c_ByteRingBuffer_t* self, uint8_t* dest, c_size_t len) {
|
||
|
|
if (!self || !dest || len == 0 || c_ByteRingBuffer_IsEmpty(self)) return 0;
|
||
|
|
|
||
|
|
c_size_t current_size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
if (len > current_size) {
|
||
|
|
len = current_size; // 裁剪可读长度
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t first_part = self->capacity - self->head;
|
||
|
|
if (len <= first_part) {
|
||
|
|
memcpy(dest, self->buffer + self->head, len);
|
||
|
|
self->head = (self->head + len) % self->capacity;
|
||
|
|
} else {
|
||
|
|
memcpy(dest, self->buffer + self->head, first_part);
|
||
|
|
memcpy(dest + first_part, self->buffer, len - first_part);
|
||
|
|
self->head = len - first_part;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (len > 0) {
|
||
|
|
self->is_full = C_FALSE;
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 强制覆盖写高级流控制 (无死锁流核心控制)
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
void c_ByteRingBuffer_WriteByteOverwrite(c_ByteRingBuffer_t* self, uint8_t byte) {
|
||
|
|
if (!self) return;
|
||
|
|
if (self->is_full) {
|
||
|
|
// 如果满了,强行把最老的队头数据向后赶一格,腾出空间
|
||
|
|
self->head = (self->head + 1) % self->capacity;
|
||
|
|
}
|
||
|
|
self->buffer[self->tail] = byte;
|
||
|
|
self->tail = (self->tail + 1) % self->capacity;
|
||
|
|
|
||
|
|
if (self->tail == self->head) {
|
||
|
|
self->is_full = C_TRUE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t c_ByteRingBuffer_WriteBufferOverwrite(c_ByteRingBuffer_t* self, const uint8_t* src, c_size_t len) {
|
||
|
|
if (!self || !src || len == 0) return 0;
|
||
|
|
|
||
|
|
// 如果单次写入量直接超过了总容量,数据彻底发生覆盖,只需保留最后填满的内容
|
||
|
|
if (len >= self->capacity) {
|
||
|
|
c_size_t offset = len - self->capacity;
|
||
|
|
memcpy(self->buffer, src + offset, self->capacity);
|
||
|
|
self->head = 0;
|
||
|
|
self->tail = 0;
|
||
|
|
self->is_full = C_TRUE;
|
||
|
|
return self->capacity;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t current_size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
c_size_t free_space = self->capacity - current_size;
|
||
|
|
|
||
|
|
// 如果装不下,需要强行丢弃最前端对应的溢出老数据块
|
||
|
|
if (len > free_space) {
|
||
|
|
c_size_t overflow = len - free_space;
|
||
|
|
self->head = (self->head + overflow) % self->capacity;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t first_part = self->capacity - self->tail;
|
||
|
|
if (len <= first_part) {
|
||
|
|
memcpy(self->buffer + self->tail, src, len);
|
||
|
|
self->tail = (self->tail + len) % self->capacity;
|
||
|
|
} else {
|
||
|
|
memcpy(self->buffer + self->tail, src, first_part);
|
||
|
|
memcpy(self->buffer, src + first_part, len - first_part);
|
||
|
|
self->tail = len - first_part;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (self->tail == self->head) {
|
||
|
|
self->is_full = C_TRUE;
|
||
|
|
} else {
|
||
|
|
self->is_full = C_FALSE; // 可能因丢弃老数据后正好填满,或仍未满
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 只读窥探与静默丢弃 (零拷贝解析首选)
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
c_err_t c_ByteRingBuffer_PeekByte(const c_ByteRingBuffer_t* self, uint8_t* out_byte) {
|
||
|
|
if (!self || !out_byte) return C_ERR_PARAM;
|
||
|
|
if (c_ByteRingBuffer_IsEmpty(self)) return C_ERR_OUTOFBOUND;
|
||
|
|
|
||
|
|
*out_byte = self->buffer[self->head];
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t c_ByteRingBuffer_PeekBuffer(const c_ByteRingBuffer_t* self, uint8_t* dest, c_size_t len) {
|
||
|
|
if (!self || !dest || len == 0 || c_ByteRingBuffer_IsEmpty(self)) return 0;
|
||
|
|
|
||
|
|
c_size_t current_size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
if (len > current_size) len = current_size;
|
||
|
|
|
||
|
|
c_size_t first_part = self->capacity - self->head;
|
||
|
|
if (len <= first_part) {
|
||
|
|
memcpy(dest, self->buffer + self->head, len);
|
||
|
|
} else {
|
||
|
|
memcpy(dest, self->buffer + self->head, first_part);
|
||
|
|
memcpy(dest + first_part, self->buffer, len - first_part);
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t c_ByteRingBuffer_Discard(c_ByteRingBuffer_t* self, c_size_t len) {
|
||
|
|
if (!self || len == 0 || c_ByteRingBuffer_IsEmpty(self)) return 0;
|
||
|
|
|
||
|
|
c_size_t current_size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
if (len > current_size) len = current_size;
|
||
|
|
|
||
|
|
self->head = (self->head + len) % self->capacity;
|
||
|
|
if (len > 0) {
|
||
|
|
self->is_full = C_FALSE; // 只要丢弃了数据,必定不为满
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 物理地址直通映射 (DMA / 零拷贝内核直通核心)
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
const uint8_t* c_ByteRingBuffer_GetReadPtr(const c_ByteRingBuffer_t* self, c_size_t* out_contiguous_len) {
|
||
|
|
if (!self || !out_contiguous_len || c_ByteRingBuffer_IsEmpty(self)) {
|
||
|
|
if (out_contiguous_len) *out_contiguous_len = 0;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (self->tail > self->head) {
|
||
|
|
*out_contiguous_len = self->tail - self->head;
|
||
|
|
} else {
|
||
|
|
*out_contiguous_len = self->capacity - self->head; // 截止到物理终点的连续长
|
||
|
|
}
|
||
|
|
return self->buffer + self->head;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint8_t* c_ByteRingBuffer_GetWritePtr(const c_ByteRingBuffer_t* self, c_size_t* out_contiguous_len) {
|
||
|
|
if (!self || !out_contiguous_len || self->is_full) {
|
||
|
|
if (out_contiguous_len) *out_contiguous_len = 0;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (self->tail >= self->head) {
|
||
|
|
*out_contiguous_len = self->capacity - self->tail; // 直到物理数组末尾
|
||
|
|
} else {
|
||
|
|
*out_contiguous_len = self->head - self->tail; // 追赶到队头前的连续空闲
|
||
|
|
}
|
||
|
|
return self->buffer + self->tail;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 相对偏移数据自检索与逻辑匹配
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
c_err_t c_ByteRingBuffer_GetAtRelative(const c_ByteRingBuffer_t* self, c_size_t relative_offset, uint8_t* out_byte) {
|
||
|
|
if (!self || !out_byte) return C_ERR_PARAM;
|
||
|
|
c_size_t size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
if (relative_offset >= size) return C_ERR_OUTOFBOUND;
|
||
|
|
|
||
|
|
c_size_t physical_idx = (self->head + relative_offset) % self->capacity;
|
||
|
|
*out_byte = self->buffer[physical_idx];
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_bool_t c_ByteRingBuffer_Is(const c_ByteRingBuffer_t* self, c_index_t offset, uint8_t value) {
|
||
|
|
// 1. 防御参数为空以及相对索引为负的高危情况
|
||
|
|
if (!self || offset < 0) {
|
||
|
|
return C_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. 联动实时大小,防止相对索引发生正向越界
|
||
|
|
c_size_t size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
if ((c_size_t)offset >= size) {
|
||
|
|
return C_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. 精准计算物理环形映射索引并实施判定
|
||
|
|
c_size_t physical_idx = (self->head + (c_size_t)offset) % self->capacity;
|
||
|
|
return (self->buffer[physical_idx] == value) ? C_TRUE : C_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief 将环形缓冲区内的分段虚拟连续流与外部扁平内存块进行词典序比对
|
||
|
|
* @return 0 完美匹配; <0 环形区较小; >0 环形区较大。
|
||
|
|
* 若发生范围越界或无效参数违规,严格返回特定错误码 C_ERR_OUTOFBOUND 或 C_ERR_PARAM。
|
||
|
|
*/
|
||
|
|
int c_ByteRingBuffer_Memcmp(const c_ByteRingBuffer_t* self, c_size_t offset, const uint8_t* buffer, c_size_t len) {
|
||
|
|
if (!self || !buffer) {
|
||
|
|
return C_ERR_PARAM; // 严格返回参数错误
|
||
|
|
}
|
||
|
|
|
||
|
|
c_size_t size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
|
||
|
|
// 【溢出防御】:防御式检查 offset + len 是否发生加法整型回绕
|
||
|
|
if (offset > size || len > (size - offset)) {
|
||
|
|
return C_ERR_OUTOFBOUND; // 严格返回范围违规错误码
|
||
|
|
}
|
||
|
|
|
||
|
|
// 逐字节进行环形映射解包比对
|
||
|
|
for (c_size_t i = 0; i < len; i++) {
|
||
|
|
c_size_t physical_idx = (self->head + offset + i) % self->capacity;
|
||
|
|
if (self->buffer[physical_idx] != buffer[i]) {
|
||
|
|
// 标准词典序符号返回:不能直接用减法防止 uint8_t 减法下溢回绕引发符号颠倒
|
||
|
|
return (self->buffer[physical_idx] < buffer[i]) ? -1 : 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief 高级文本数字符号有限状态机解析器 (Strtoul 工业级原状重塑)
|
||
|
|
* @note 强御级加固:完全依靠 c_ByteRingBuffer_GetAtRelative 在环形虚拟长度内做边界锁死,
|
||
|
|
* 支持多进制智能嗅探(0x/0)与防符号下溢的 ULONG_MAX 饱和截断。
|
||
|
|
*/
|
||
|
|
c_err_t c_ByteRingBuffer_Strtoul(const c_ByteRingBuffer_t* self, c_size_t offset, int base, unsigned long* out_value, c_size_t* out_end_offset) {
|
||
|
|
if (!self || !self->buffer || !out_value) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
c_size_t total_size = c_ByteRingBuffer_GetSize(self);
|
||
|
|
if (offset >= total_size) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
// 1. Skip leading whitespace using the internal helper function
|
||
|
|
c_size_t scan_idx = offset;
|
||
|
|
while (scan_idx < total_size) {
|
||
|
|
uint8_t byte = c_ByteRingBuffer_GetAtRelativeInternal(self, scan_idx);
|
||
|
|
if (!isspace(byte)) break;
|
||
|
|
scan_idx++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (scan_idx == total_size) return C_ERR_PARAM; // Buffer contains only whitespace
|
||
|
|
|
||
|
|
// 2. Measure the exact alphanumeric chunk layout width boundary
|
||
|
|
c_size_t start_numeric_offset = scan_idx;
|
||
|
|
c_size_t numeric_len = 0;
|
||
|
|
while (scan_idx < total_size) {
|
||
|
|
uint8_t byte = c_ByteRingBuffer_GetAtRelativeInternal(self, scan_idx);
|
||
|
|
// Track hex modifiers (x, X), signs, and alphanumeric digits
|
||
|
|
if (!isalnum(byte) && byte != '+' && byte != '-') {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
numeric_len++;
|
||
|
|
scan_idx++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (numeric_len == 0) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
// 3. Compute absolute pointers and optimize memory operations based on wrap layouts
|
||
|
|
c_size_t absolute_start = (self->head + start_numeric_offset) % self->capacity;
|
||
|
|
c_size_t bytes_to_end = self->capacity - absolute_start;
|
||
|
|
|
||
|
|
unsigned long result = 0;
|
||
|
|
char* parse_end = NULL;
|
||
|
|
int current_errno = errno;
|
||
|
|
errno = 0;
|
||
|
|
|
||
|
|
if (numeric_len <= bytes_to_end) {
|
||
|
|
// Linear path optimization: Parse directly out of the contiguous array space
|
||
|
|
const char* flat_ptr = (const char*)(self->buffer + absolute_start);
|
||
|
|
result = strtoul(flat_ptr, &parse_end, base);
|
||
|
|
|
||
|
|
c_size_t parsed_bytes = (c_size_t)(parse_end - flat_ptr);
|
||
|
|
if (parsed_bytes == 0 || parse_end == flat_ptr) {
|
||
|
|
errno = current_errno;
|
||
|
|
return C_ERR_PARAM;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (errno == ERANGE) {
|
||
|
|
*out_value = result;
|
||
|
|
if (out_end_offset) {
|
||
|
|
*out_end_offset = start_numeric_offset + parsed_bytes;
|
||
|
|
}
|
||
|
|
return C_ERR_OUTOFBOUND;
|
||
|
|
}
|
||
|
|
|
||
|
|
*out_value = result;
|
||
|
|
if (out_end_offset) {
|
||
|
|
*out_end_offset = start_numeric_offset + parsed_bytes;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// Fragmented Wrap handling path: Copy across loop slices onto a small stack array
|
||
|
|
if (numeric_len >= 64) return C_ERR_OUTOFBOUND; // Enforce safe parsing limits
|
||
|
|
|
||
|
|
char stack_scratch[64];
|
||
|
|
for (c_size_t i = 0; i < numeric_len; i++) {
|
||
|
|
stack_scratch[i] = (char)c_ByteRingBuffer_GetAtRelativeInternal(self, start_numeric_offset + i);
|
||
|
|
}
|
||
|
|
stack_scratch[numeric_len] = '\0'; // Guarantee safe string boundary termination
|
||
|
|
|
||
|
|
result = strtoul(stack_scratch, &parse_end, base);
|
||
|
|
c_size_t parsed_bytes = (c_size_t)(parse_end - stack_scratch);
|
||
|
|
|
||
|
|
if (parsed_bytes == 0 || parse_end == stack_scratch) {
|
||
|
|
errno = current_errno;
|
||
|
|
return C_ERR_PARAM;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (errno == ERANGE) return C_ERR_OUTOFBOUND;
|
||
|
|
|
||
|
|
*out_value = result;
|
||
|
|
if (out_end_offset) {
|
||
|
|
*out_end_offset = start_numeric_offset + parsed_bytes;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
errno = current_errno; // Restore system state integrity flags cleanly
|
||
|
|
return C_SUCCESS;
|
||
|
|
}
|