Files
cAI/cKit/Foundation/c_FastByteRingBuffer.c
T
2026-08-10 12:05:34 +08:00

545 lines
18 KiB
C

#include <c_FastByteRingBuffer.h>
#include <c_Memory.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
C_STATIC_FORCE_INLINE
c_size_t round_up_to_pow2(c_size_t v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
#if (defined(__WORDSIZE) && __WORDSIZE == 64) || defined(_WIN64) || defined(__x86_64__) || defined(__aarch64__)
v |= v >> 32;
#endif
v++;
return v;
}
C_STATIC_FORCE_INLINE
c_bool_t c_FastByteRingBuffer_IsPow2(c_size_t capacity) {
// A power of 2 must be greater than zero.
// The bitwise trick (capacity & (capacity - 1)) works because a power of 2
// has exactly one bit set (e.g., 01000). Subtracting 1 flips all bits up to
// that set bit (e.g., 00111). Performing a bitwise AND yields exactly 0.
if (capacity == 0) {
return C_FALSE;
}
return ((capacity & (capacity - 1)) == 0) ? C_TRUE : C_FALSE;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
c_err_t c_FastByteRingBuffer_Init(c_FastByteRingBuffer_t* self, c_size_t capacity) {
if (!self || capacity == 0) return C_ERR_PARAM;
if (!c_FastByteRingBuffer_IsPow2(capacity)) {
return C_ERR_PARAM;
}
// 自動向上對齊,確保符合 Power of Two
self->capacity = capacity;
self->mask = self->capacity - 1; // 建立遮罩
self->head = 0;
self->tail = 0;
self->is_full = C_FALSE;
self->buffer = (uint8_t*)malloc(self->capacity);
if (!self->buffer) {
self->capacity = 0;
self->mask = 0;
return C_ERR_NOMEM;
}
return C_ERR_SUCCESS;
}
void c_FastByteRingBuffer_Destroy(c_FastByteRingBuffer_t* self) {
if (!self) return;
C_FREE(self->buffer);
self->capacity = 0;
self->mask = 0;
self->head = 0;
self->tail = 0;
self->is_full = C_FALSE;
}
// 寫入單一單元組 (極速 O(1))
c_err_t c_FastByteRingBuffer_WriteByte(c_FastByteRingBuffer_t* self, uint8_t byte) {
if (!self || !self->buffer) return C_ERR_PARAM;
if (self->is_full) return C_ERR_FULL;
self->buffer[self->tail] = byte;
// 使用高速位元與運算取代模除 %
self->tail = (self->tail + 1) & self->mask;
if (self->tail == self->head) {
self->is_full = C_TRUE;
}
return C_ERR_SUCCESS;
}
// 讀取單一單元組 (極速 O(1))
c_err_t c_FastByteRingBuffer_ReadByte(c_FastByteRingBuffer_t* self, uint8_t* out_byte) {
if (!self || !self->buffer || !out_byte) return C_ERR_PARAM;
if (c_FastByteRingBuffer_IsEmpty(self)) return C_ERR_EMPTY;
*out_byte = self->buffer[self->head];
// 使用高速位元與運算取代模除 %
self->head = (self->head + 1) & self->mask;
self->is_full = C_FALSE;
return C_ERR_SUCCESS;
}
c_size_t c_FastByteRingBuffer_WriteBuffer(c_FastByteRingBuffer_t* self, const uint8_t* src, c_size_t len) {
if (!self || !self->buffer || !src || len == 0) return 0;
if (self->is_full) return 0;
// Calculate free space directly using fast size validation tracking
c_size_t current_size = c_FastByteRingBuffer_GetSize(self);
c_size_t free_space = self->capacity - current_size;
// Clamp write operations to avoid overrunning existing readable elements
if (len > free_space) {
len = free_space;
}
if (len == 0) return 0;
// Segment 1: Write from tail index up to the physical end boundary of the backing array
c_size_t space_to_end = self->capacity - self->tail;
c_size_t first_chunk = (len < space_to_end) ? len : space_to_end;
memcpy(self->buffer + self->tail, src, first_chunk);
// Segment 2: Wrap around to index 0 using bitwise optimizations if a split block configuration is required
c_size_t second_chunk = len - first_chunk;
if (second_chunk > 0) {
memcpy(self->buffer, src + first_chunk, second_chunk);
self->tail = second_chunk; // The wrapped tail calculation reduces cleanly to second_chunk
} else {
// Fast tail stepping path utilizing the mask constant
self->tail = (self->tail + first_chunk) & self->mask;
}
// Set the full status flag if the cursors perfectly intersect
if (self->tail == self->head) {
self->is_full = C_TRUE;
}
return len;
}
// 區塊讀取
c_size_t c_FastByteRingBuffer_ReadBuffer(c_FastByteRingBuffer_t* self, uint8_t* dest, c_size_t len) {
if (!self || !self->buffer || !dest || len == 0) return 0;
c_size_t bytes_read = 0;
while (bytes_read < len && !c_FastByteRingBuffer_IsEmpty(self)) {
dest[bytes_read] = self->buffer[self->head];
self->head = (self->head + 1) & self->mask;
self->is_full = C_FALSE;
bytes_read++;
}
return bytes_read;
}
c_size_t c_FastByteRingBuffer_GetSize(const c_FastByteRingBuffer_t* self) {
if (!self || !self->buffer) return 0;
if (self->is_full) return self->capacity;
if (self->tail >= self->head) {
return self->tail - self->head;
} else {
return self->capacity + self->tail - self->head;
}
}
c_bool_t c_FastByteRingBuffer_IsEmpty(const c_FastByteRingBuffer_t* self) {
if (!self) return C_TRUE;
return (self->head == self->tail) && !self->is_full;
}
c_bool_t c_FastByteRingBuffer_IsFull(const c_FastByteRingBuffer_t* self) {
if (!self) return C_FALSE;
return self->is_full;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
C_STATIC_FORCE_INLINE
uint8_t c_FastByteRingBuffer_GetAtRelativeInternal(const c_FastByteRingBuffer_t* self, c_size_t relative_offset) {
c_size_t absolute_index = (self->head + relative_offset) & self->mask;
return self->buffer[absolute_index];
}
/* ------------------------------------------------------------------------------------------------------------------ */
void c_FastByteRingBuffer_WriteByteOverwrite(c_FastByteRingBuffer_t* self, uint8_t byte) {
if (!self || !self->buffer) return;
if (self->is_full) {
// 環形陣列已滿時,強制將讀取指標向前推一格,拋棄最舊數據
self->head = (self->head + 1) & self->mask;
}
self->buffer[self->tail] = byte;
self->tail = (self->tail + 1) & self->mask;
if (self->tail == self->head) {
self->is_full = C_TRUE;
}
}
c_size_t c_FastByteRingBuffer_WriteBufferOverwrite(c_FastByteRingBuffer_t* self, const uint8_t* src, c_size_t len) {
if (!self || !self->buffer || !src || len == 0) return 0;
// 邊界極端優化:如果寫入長度超過總容量,只有最後符合容量大小的數據能存活
if (len >= self->capacity) {
src += (len - self->capacity);
len = self->capacity;
memcpy(self->buffer, src, len);
self->head = 0;
self->tail = 0;
self->is_full = C_TRUE;
return len;
}
c_size_t size = c_FastByteRingBuffer_GetSize(self);
c_size_t free_space = self->capacity - size;
// 若寫入長度大於剩餘空間,計算溢出量並自動同步前推 head 指標
if (len > free_space) {
c_size_t overwrite_count = len - free_space;
self->head = (self->head + overwrite_count) & self->mask;
}
// 分段一:從 tail 寫入到物理內存陣列末尾
c_size_t space_to_end = self->capacity - self->tail;
c_size_t first_chunk = (len < space_to_end) ? len : space_to_end;
memcpy(self->buffer + self->tail, src, first_chunk);
// 分段二:折返到內存陣列開頭寫入剩餘數據
c_size_t second_chunk = len - first_chunk;
if (second_chunk > 0) {
memcpy(self->buffer, src + first_chunk, second_chunk);
self->tail = second_chunk;
} else {
self->tail = (self->tail + first_chunk) & self->mask;
}
if (self->tail == self->head) {
self->is_full = C_TRUE;
} else {
self->is_full = C_FALSE;
}
return len;
}
c_err_t c_FastByteRingBuffer_PeekByte(const c_FastByteRingBuffer_t* self, uint8_t* out_byte) {
if (!self || !self->buffer || !out_byte) return C_ERR_INVALID_PARAM;
if (c_FastByteRingBuffer_IsEmpty(self)) return C_ERR_OUT_OF_BOUNDS;
*out_byte = self->buffer[self->head];
return C_SUCCESS;
}
c_size_t c_FastByteRingBuffer_PeekBuffer(const c_FastByteRingBuffer_t* self, uint8_t* dest, c_size_t len) {
if (!self || !self->buffer || !dest || len == 0) return 0;
c_size_t available_bytes = c_FastByteRingBuffer_GetSize(self);
if (len > available_bytes) {
len = available_bytes;
}
if (len == 0) return 0;
// 複製標準讀取邏輯,但完全不變動真實核心 head 指標狀態
c_size_t bytes_to_end = self->capacity - self->head;
c_size_t first_chunk = (len < bytes_to_end) ? len : bytes_to_end;
memcpy(dest, self->buffer + self->head, first_chunk);
c_size_t second_chunk = len - first_chunk;
if (second_chunk > 0) {
memcpy(dest + first_chunk, self->buffer, second_chunk);
}
return len;
}
c_size_t c_FastByteRingBuffer_Discard(c_FastByteRingBuffer_t* self, c_size_t len) {
if (!self || !self->buffer || len == 0) return 0;
c_size_t available_bytes = c_FastByteRingBuffer_GetSize(self);
if (len > available_bytes) {
len = available_bytes;
}
if (len == 0) return 0;
self->head = (self->head + len) & self->mask;
self->is_full = C_FALSE;
return len;
}
const uint8_t* c_FastByteRingBuffer_GetReadPtr(const c_FastByteRingBuffer_t* self, c_size_t* out_contiguous_len) {
if (!self || !self->buffer || !out_contiguous_len) return NULL;
*out_contiguous_len = 0;
if (c_FastByteRingBuffer_IsEmpty(self)) 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_FastByteRingBuffer_GetWritePtr(const c_FastByteRingBuffer_t* self, c_size_t* out_contiguous_len) {
if (!self || !self->buffer || !out_contiguous_len) return NULL;
*out_contiguous_len = 0;
if (self->is_full) 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_index_t c_FastByteRingBuffer_IndexOfByte(const c_FastByteRingBuffer_t* self, uint8_t target) {
if (!self || !self->buffer) return C_ERR_NOT_FOUND;
c_size_t total_size = c_FastByteRingBuffer_GetSize(self);
for (c_size_t offset = 0; offset < total_size; offset++) {
if (c_FastByteRingBuffer_GetAtRelativeInternal(self, offset) == target) {
return (c_index_t)offset;
}
}
return C_ERR_NOT_FOUND;
}
c_index_t c_FastByteRingBuffer_IndexOfBuffer(const c_FastByteRingBuffer_t* self, const uint8_t* pattern, c_size_t pattern_len) {
if (!self || !self->buffer || !pattern || pattern_len == 0) return C_ERR_NOT_FOUND;
c_size_t total_size = c_FastByteRingBuffer_GetSize(self);
if (pattern_len > total_size) return C_ERR_NOT_FOUND;
c_size_t max_search_offset = total_size - pattern_len;
for (c_size_t offset = 0; offset <= max_search_offset; offset++) {
c_bool_t match_found = C_TRUE;
for (c_size_t p_idx = 0; p_idx < pattern_len; p_idx++) {
if (c_FastByteRingBuffer_GetAtRelativeInternal(self, offset + p_idx) != pattern[p_idx]) {
match_found = C_FALSE;
break;
}
}
if (match_found) {
return (c_index_t)offset;
}
}
return C_ERR_NOT_FOUND;
}
c_index_t c_FastByteRingBuffer_LastIndexOfBuffer(const c_FastByteRingBuffer_t* self, const uint8_t* pattern, c_size_t pattern_len) {
if (!self || !self->buffer || !pattern || pattern_len == 0) return C_ERR_NOT_FOUND;
c_size_t total_size = c_FastByteRingBuffer_GetSize(self);
if (pattern_len > total_size) return C_ERR_NOT_FOUND;
c_size_t max_search_offset = total_size - pattern_len;
for (c_size_t offset = max_search_offset; ; offset--) {
c_bool_t match_found = C_TRUE;
for (c_size_t p_idx = 0; p_idx < pattern_len; p_idx++) {
if (c_FastByteRingBuffer_GetAtRelativeInternal(self, offset + p_idx) != pattern[p_idx]) {
match_found = C_FALSE;
break;
}
}
if (match_found) {
return (c_index_t)offset;
}
if (offset == 0) break;
}
return C_ERR_NOT_FOUND;
}
c_size_t c_FastByteRingBuffer_ReadUntilToken(c_FastByteRingBuffer_t* self, const uint8_t* token, c_size_t token_len, uint8_t* dest, c_size_t dest_max_len) {
if (!self || !self->buffer || !token || token_len == 0 || !dest || dest_max_len == 0) return 0;
c_index_t match_offset = c_FastByteRingBuffer_IndexOfBuffer(self, token, token_len);
if (match_offset == C_ERR_NOT_FOUND) {
return 0;
}
c_size_t aggregate_bytes = (c_size_t)match_offset + token_len;
if (aggregate_bytes > dest_max_len) {
return 0; // 避免目標緩衝區溢出
}
return c_FastByteRingBuffer_ReadBuffer(self, dest, aggregate_bytes);
}
c_err_t c_FastByteRingBuffer_GetAtRelative(const c_FastByteRingBuffer_t* self, c_size_t relative_offset, uint8_t* out_byte) {
if (!self || !self->buffer || !out_byte) return C_ERR_INVALID_PARAM;
c_size_t active_size = c_FastByteRingBuffer_GetSize(self);
if (relative_offset >= active_size) {
return C_ERR_OUT_OF_BOUNDS;
}
*out_byte = c_FastByteRingBuffer_GetAtRelativeInternal(self, relative_offset);
return C_SUCCESS;
}
c_bool_t c_FastByteRingBuffer_Is(const c_FastByteRingBuffer_t* self, c_index_t offset, uint8_t value) {
if (!self || !self->buffer || offset < 0) return C_FALSE;
c_size_t active_size = c_FastByteRingBuffer_GetSize(self);
if ((c_size_t)offset >= active_size) return C_FALSE;
return (c_FastByteRingBuffer_GetAtRelativeInternal(self, (c_size_t)offset) == value) ? C_TRUE : C_FALSE;
}
int c_FastByteRingBuffer_Memcmp(const c_FastByteRingBuffer_t* self, c_size_t offset, const uint8_t* buffer, c_size_t len) {
if (!self || !self->buffer || !buffer) return C_ERR_INVALID_PARAM;
if (len == 0) return 0;
c_size_t active_size = c_FastByteRingBuffer_GetSize(self);
if (offset >= active_size || (offset + len) > active_size) {
return C_ERR_OUT_OF_BOUNDS;
}
c_size_t absolute_start = (self->head + offset) & self->mask;
c_size_t bytes_to_end = self->capacity - absolute_start;
if (len <= bytes_to_end) {
return memcmp(self->buffer + absolute_start, buffer, len);
} else {
int first_segment_match = memcmp(self->buffer + absolute_start, buffer, bytes_to_end);
if (first_segment_match != 0) {
return first_segment_match;
}
return memcmp(self->buffer, buffer + bytes_to_end, len - bytes_to_end);
}
}
c_err_t c_FastByteRingBuffer_Strtoul(const c_FastByteRingBuffer_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_INVALID_PARAM;
c_size_t total_size = c_FastByteRingBuffer_GetSize(self);
if (offset >= total_size) return C_ERR_OUT_OF_BOUNDS;
// 1. Skip leading spaces safely using fast inline relative scans
c_size_t scan_idx = offset;
while (scan_idx < total_size) {
uint8_t byte = c_FastByteRingBuffer_GetAtRelativeInternal(self, scan_idx);
if (!isspace(byte)) break;
scan_idx++;
}
if (scan_idx == total_size) return C_ERR_INVALID_PARAM; // Contains only whitespace
// 2. Locate trailing delimiters to calculate numeric chunk span width
c_size_t start_numeric_offset = scan_idx;
c_size_t numeric_len = 0;
while (scan_idx < total_size) {
uint8_t byte = c_FastByteRingBuffer_GetAtRelativeInternal(self, scan_idx);
// Include numerical modifiers (+, -), hex identifiers (x, X) and alphanumeric bases
if (!isalnum(byte) && byte != '+' && byte != '-') {
break;
}
numeric_len++;
scan_idx++;
}
if (numeric_len == 0) return C_ERR_INVALID_PARAM;
// 3. Resolve the starting index using bitwise mask instead of slow % operators
c_size_t absolute_start = (self->head + start_numeric_offset) & self->mask;
c_size_t bytes_to_end = self->capacity - absolute_start;
unsigned long result = 0;
char* parse_end = NULL;
int current_errno = errno;
errno = 0;
// Fast-path: Segment runs contiguous without wrapping lines
if (numeric_len <= bytes_to_end) {
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_INVALID_PARAM;
}
if (errno == ERANGE) return C_ERR_OUT_OF_BOUNDS;
*out_value = result;
if (out_end_offset) {
*out_end_offset = start_numeric_offset + parsed_bytes;
}
} else {
// Slow-path: Structural wrap configuration requires localized stack flattening
if (numeric_len >= 64) return C_ERR_OUT_OF_BOUNDS;
char stack_scratch[64];
for (c_size_t i = 0; i < numeric_len; i++) {
stack_scratch[i] = (char)c_FastByteRingBuffer_GetAtRelativeInternal(self, start_numeric_offset + i);
}
stack_scratch[numeric_len] = '\0'; // Guarantee absolute zero string 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_INVALID_PARAM;
}
if (errno == ERANGE) return C_ERR_OUT_OF_BOUNDS;
*out_value = result;
if (out_end_offset) {
*out_end_offset = start_numeric_offset + parsed_bytes;
}
}
errno = current_errno; // Preserve runtime environment variables smoothly
return C_SUCCESS;
}