Files
2026-08-30 01:48:03 +08:00

124 lines
4.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <c_ArrayQueue.h>
#define DEFAULT_INIT_CAPACITY 4
c_err_t c_ArrayQueue_Init(c_ArrayQueue_t* self, c_size_t item_size, c_size_t capacity, c_Allocator_t* allocator) {
if (!self || item_size == 0) return C_ERR_PARAM;
self->allocator = (allocator != NULL) ? *allocator : c_DefaultAllocator;
self->item_size = item_size;
self->size = 0;
self->head = 0;
self->tail = 0;
self->capacity = (capacity > 0) ? capacity : DEFAULT_INIT_CAPACITY;
self->array = c_Allocator_Alloc(&self->allocator, self->capacity * item_size);
if (!self->array) return C_ERR_NOMEM;
return C_ERR_OK;
}
void c_ArrayQueue_Destroy(c_ArrayQueue_t* self) {
if (!self) return;
if (self->array) {
c_Allocator_Free(&self->allocator, self->array);
self->array = NULL;
}
self->size = 0;
self->capacity = 0;
self->head = 0;
self->tail = 0;
}
c_err_t c_ArrayQueue_Resize(c_ArrayQueue_t* self, c_size_t new_capacity) {
if (!self || new_capacity < self->size) return C_ERR_PARAM; // 不允许缩容到比当前已有元素还小
if (new_capacity == self->capacity) return C_ERR_OK;
const c_size_t new_bytes = new_capacity * self->item_size;
// 1. 先用 Alloc 申请一块干净、独立的全新目标缓冲区
void* new_array = c_Allocator_Alloc(&self->allocator, new_bytes);
if (!new_array) return C_ERR_NOMEM;
// 2. 此时旧缓冲区 self->array 100% 安全存活,可以放心读取并执行平整化导出
if (self->size > 0 && self->array) {
uint8_t* dst = (uint8_t*)new_array;
const uint8_t* src = (const uint8_t*)self->array;
if (self->head < self->tail) {
// 情况 A: 数据是连续的,没有发生回绕
memcpy(dst, src + (self->head * self->item_size), self->size * self->item_size);
} else {
// 情况 B: 数据发生了回绕,精准分两段导出到新阵列
const c_size_t first_part_len = self->capacity - self->head;
const c_size_t second_part_len = self->tail;
memcpy(dst, src + (self->head * self->item_size), first_part_len * self->item_size);
memcpy(dst + (first_part_len * self->item_size), src, second_part_len * self->item_size);
}
}
// 3. 数据安全倒腾完毕后,显式手工释放旧空间(因为我们第一步用的是 Alloc 而不是 Realloc
if (self->array) {
c_Allocator_Free(&self->allocator, self->array);
}
// 4. 更新队列控制头状态
self->array = new_array;
self->capacity = new_capacity;
self->head = 0;
self->tail = self->size; // 经过平整化铺平,新尾部直接等于已有大小
return C_ERR_OK;
}
// 内部自动扩容
C_STATIC_FORCE_INLINE
bool c_ArrayQueue_EnsureCapacity(c_ArrayQueue_t* self) {
if (self->size < self->capacity) return true;
c_size_t new_capacity = self->capacity * 2;
return c_ArrayQueue_Resize(self, new_capacity) == C_ERR_OK;
}
// 入队 (O(1) 性能,自动触发扩容)
c_err_t c_ArrayQueue_Enqueue(c_ArrayQueue_t* self, const void* item) {
if (!self || !item) return C_ERR_PARAM;
if (!c_ArrayQueue_EnsureCapacity(self)) return C_ERR_NOMEM;
// 计算尾部插入点并拷贝数据
uint8_t* target = (uint8_t*)self->array + (self->tail * self->item_size);
memcpy(target, item, self->item_size);
// 环形推进 tail 指针
self->tail = (self->tail + 1) % self->capacity;
self->size++;
return C_SUCCESS;
}
// 出队 (O(1) 性能,零内存移动开销)
c_err_t c_ArrayQueue_Dequeue(c_ArrayQueue_t* self, void* out_item) {
if (!self || self->size == 0) return C_ERR_PARAM;
// 找到队头数据源
uint8_t* source = (uint8_t*)self->array + (self->head * self->item_size);
if (out_item) {
memcpy(out_item, source, self->item_size);
}
// 环形推进 head 指针
self->head = (self->head + 1) % self->capacity;
self->size--;
return C_SUCCESS;
}
// 查看队头元素(不移除)
void* c_ArrayQueue_Peek(const c_ArrayQueue_t* self) {
if (!self || self->size == 0) return NULL;
return (uint8_t*)self->array + (self->head * self->item_size);
}