重构
This commit is contained in:
+91
-78
@@ -1,110 +1,123 @@
|
||||
#include <c_ArrayQueue.h>
|
||||
#include <c_Memory.h>
|
||||
|
||||
#define DEFAULT_INITIAL_CAPACITY 4
|
||||
#define MIN_SHRINK_CAPACITY 4
|
||||
#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;
|
||||
|
||||
c_err_t c_ArrayQueue_Init(c_ArrayQueue_t* self, int obj_size, c_size_t capacity) {
|
||||
if (!self || obj_size == 0) return C_ERR_PARAM;
|
||||
|
||||
self->obj_size = obj_size;
|
||||
self->capacity = (capacity > 0) ? capacity : DEFAULT_INITIAL_CAPACITY;
|
||||
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_ALLOC(self->capacity * self->obj_size);
|
||||
if (!self->array) {
|
||||
self->capacity = 0;
|
||||
return C_ERR_NOMEM;
|
||||
}
|
||||
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;
|
||||
|
||||
C_FREE(self->array);
|
||||
|
||||
self->capacity = 0;
|
||||
if (self->array) {
|
||||
c_Allocator_Free(&self->allocator, self->array);
|
||||
self->array = NULL;
|
||||
}
|
||||
self->size = 0;
|
||||
self->obj_size = 0;
|
||||
self->capacity = 0;
|
||||
self->head = 0;
|
||||
self->tail = 0;
|
||||
}
|
||||
|
||||
c_err_t c_ArrayQueue_Push(c_ArrayQueue_t* self, void* obj) {
|
||||
if (!self || !self->array || !obj) return C_ERR_PARAM;
|
||||
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 (self->size >= self->capacity) {
|
||||
const c_size_t new_capacity = self->capacity << 1;
|
||||
void* new_array = C_REALLOC(self->array, new_capacity * self->obj_size);
|
||||
if (!new_array) {
|
||||
return C_ERR_NOMEM;
|
||||
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);
|
||||
}
|
||||
self->array = new_array;
|
||||
self->capacity = new_capacity;
|
||||
}
|
||||
|
||||
char* target = (char*)self->array + (self->size * self->obj_size);
|
||||
memcpy(target, obj, self->obj_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_ERR_OK;
|
||||
return C_SUCCESS;
|
||||
}
|
||||
|
||||
c_err_t c_ArrayQueue_Pop(c_ArrayQueue_t* self, void* obj) {
|
||||
if (!self || !self->array ) return C_ERR_PARAM;
|
||||
if (self->size == 0) return C_ERR_EMPTY; // 佇列已空
|
||||
// 出队 (O(1) 性能,零内存移动开销)
|
||||
c_err_t c_ArrayQueue_Dequeue(c_ArrayQueue_t* self, void* out_item) {
|
||||
if (!self || self->size == 0) return C_ERR_PARAM;
|
||||
|
||||
char* pop_src = (char*)self->array; // 最前端索引 0 的地址
|
||||
|
||||
// 1. 直接值複製到呼叫端提供的記憶體中
|
||||
if (obj) {
|
||||
memcpy(obj, pop_src, self->obj_size);
|
||||
}
|
||||
|
||||
// 2. 如果佇列內還有其他元素,將它們向前平移一個單位
|
||||
if (self->size > 1) {
|
||||
char* dest = pop_src;
|
||||
const char* src = pop_src + self->obj_size;
|
||||
const c_size_t num_elements_to_move = self->size - 1;
|
||||
memmove(dest, src, num_elements_to_move * self->obj_size);
|
||||
// 找到队头数据源
|
||||
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--;
|
||||
|
||||
if (self->size > 0 && self->size <= (self->capacity >> 2)) {
|
||||
c_size_t new_capacity = self->capacity >> 1; // 容量减半
|
||||
|
||||
void* new_array = C_REALLOC(self->array, new_capacity * self->obj_size);
|
||||
if (new_array) { // 如果 realloc 失败不影响原有数据安全,这里采用安全赋值
|
||||
self->array = new_array;
|
||||
self->capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return C_ERR_OK;
|
||||
return C_SUCCESS;
|
||||
}
|
||||
|
||||
c_err_t c_ArrayQueue_Remove(c_ArrayQueue_t* self, c_size_t index) {
|
||||
if (!self || !self->array) return C_ERR_PARAM;
|
||||
if (index >= self->size) return C_ERR_OUTOFBOUND;
|
||||
|
||||
if (index < self->size - 1) {
|
||||
char* dest = (char*)self->array + (index * self->obj_size);
|
||||
const char* src = dest + self->obj_size;
|
||||
const c_size_t num_elements_to_move = self->size - index - 1;
|
||||
memmove(dest, src, num_elements_to_move * self->obj_size);
|
||||
}
|
||||
|
||||
self->size--;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
void* c_ArrayQueue_Peek(c_ArrayQueue_t* self) {
|
||||
if (!self || !self->array || self->size == 0) return NULL;
|
||||
return self->array; // 最前端索引 0 的起始地址即是 array 本身
|
||||
// 查看队头元素(不移除)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user