#include #include #include #include #include /* ------------------------------------------------------------------------------------------------------------------ */ /* */ 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_err_t c_FastByteRingBuffer_Init(c_FastByteRingBuffer_t* self, c_size_t capacity) { if (!self || capacity == 0) return C_ERR_PARAM; // 自動向上對齊,確保符合 Power of Two self->capacity = round_up_to_pow2(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; }