Files
cKit/Foundation/c_LinkQueue.c
T

129 lines
3.6 KiB
C
Raw Normal View History

2026-08-29 01:50:50 +08:00
#include <c_LinkQueue.h>
#include <c_Memory.h>
#include "c_Alignment.h"
#include "c_Macros.h"
c_err_t c_LinkQueue_Init(c_LinkQueue_t* self, int obj_size) {
if (!self || obj_size == 0) return C_ERR_PARAM;
self->head = NULL;
self->tail = NULL;
self->obj_size = (int)obj_size;
self->size = 0;
return C_ERR_OK;
}
void c_LinkQueue_Destroy(c_LinkQueue_t* self) {
if (!self) return;
c_LinkQueueNode_t* current = self->head;
while (current != NULL) {
c_LinkQueueNode_t* next = current->next;
C_FREE(current);
current = next;
}
self->head = NULL;
self->tail = NULL;
self->size = 0;
}
c_err_t c_LinkQueue_Push(c_LinkQueue_t* self, void* obj) {
if (!self || !obj) return C_ERR_PARAM;
// 1. 配置新節點與資料空間
int size = (int)sizeof(c_LinkQueueNode_t) + self->obj_size;
size = C_ALIGN_UPB(size, C_ALIGN_SIZE);
c_LinkQueueNode_t* new_node = (c_LinkQueueNode_t*)C_ALLOC(size);
if (!new_node) return C_ERR_NOMEM;
new_node->data = new_node+1;
// 深複製資料內容
memcpy(new_node->data, obj, self->obj_size);
new_node->next = NULL;
// 2. 將新節點追加到串列尾端
if (self->tail == NULL) {
// 佇列原本為空
self->head = new_node;
self->tail = new_node;
} else {
// 佇列不為空,讓原本尾端的 next 指向新節點,並更新 tail
self->tail->next = new_node;
self->tail = new_node;
}
self->size++;
return C_ERR_OK;
}
c_err_t c_LinkQueue_Pop(c_LinkQueue_t* self, void* obj) {
if (!self ) return C_ERR_PARAM;
if (self->size == 0 || !self->head) return C_ERR_EMPTY;
c_LinkQueueNode_t* to_delete = self->head;
// 1. 複製資料到使用者緩衝區
if (obj) {
memcpy(obj, to_delete->data, self->obj_size);
}
// 2. 將 head 移至下一個節點
self->head = to_delete->next;
if (self->head == NULL) {
self->tail = NULL;
}
// 3. 釋放斷開的節點資源
C_FREE(to_delete);
self->size--;
return C_ERR_OK;
}
c_err_t c_LinkQueue_Peek(c_LinkQueue_t* self, void* obj) {
if (!self ) return C_ERR_PARAM;
if (self->size == 0 || !self->head) return C_ERR_EMPTY;
// 複製最前端的資料內容
if (obj) {
memcpy(obj, self->head->data, self->obj_size);
}
return C_ERR_OK;
}
void c_LinkQueueIter_Remove(c_LinkQueueIter_t* self) {
if (!self || !self->queue || !self->node || !*(self->node)) return;
c_LinkQueueNode_t* to_delete = *(self->node);
c_LinkQueue_t* q = self->queue;
// 檢查目前要刪除的是否為尾端節點
const c_bool_t is_tail = (to_delete == q->tail);
// 讓上一個節點的 next(或 head)直接指向下一個節點,將 to_delete 從串列中斷開
*(self->node) = to_delete->next;
// 如果刪除的是尾端節點,必須更新 tail 指標
if (is_tail) {
if (q->head == NULL) {
// 情況 A:刪除後佇列完全空了
q->tail = NULL;
} else {
// 情況 B:刪除的是尾巴,但前方還有元素。
// 沿著 head 重新走訪一遍,找出現在最尾端的節點(即 next 為 NULL 的節點)
c_LinkQueueNode_t* curr = q->head;
while (curr->next != NULL) {
curr = curr->next;
}
q->tail = curr; // 更新新的尾端
}
}
// 釋放記憶體資源
C_FREE(to_delete);
// 同步遞減佇列大小
q->size--;
// 此時 self->node 已自動留在原本的下一個節點上,呼叫端可直接繼續 Get() 或 Next()
}