Files
cKit/Foundation/c_LinkDQueue.c
T

154 lines
4.1 KiB
C
Raw Normal View History

2026-08-29 01:50:50 +08:00
#include <c_LinkDQueue.h>
#include <c_Memory.h>
#include <c_Alignment.h>
#include "c_Macros.h"
C_STATIC_FORCE_INLINE
c_LinkDQueueNode_t* create_node(int obj_size, void* obj) {
int size = sizeof(c_LinkDQueueNode_t) + obj_size;
size = C_ALIGN_UPB(size, C_ALIGN_SIZE);
c_LinkDQueueNode_t* new_node = (c_LinkDQueueNode_t*)C_ALLOC(size);
if (!new_node) return NULL;
new_node->data = new_node + 1;
memcpy(new_node->data, obj, obj_size);
new_node->prev = NULL;
new_node->next = NULL;
return new_node;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
c_err_t c_LinkDQueue_Init(c_LinkDQueue_t* self, int obj_size) {
if (!self || obj_size <= 0) return C_ERR_PARAM;
self->head = NULL;
self->tail = NULL;
self->obj_size = obj_size;
self->size = 0;
return C_ERR_OK;
}
void c_LinkDQueue_Destroy(c_LinkDQueue_t* self) {
if (!self) return;
c_LinkDQueueNode_t* current = self->head;
while (current != NULL) {
c_LinkDQueueNode_t* next = current->next;
C_FREE(current);
current = next;
}
self->head = NULL;
self->tail = NULL;
self->size = 0;
}
// 前端推入 O(1)
c_err_t c_LinkDQueue_PushHead(c_LinkDQueue_t* self, void* obj) {
if (!self || !obj) return C_ERR_PARAM;
c_LinkDQueueNode_t* new_node = create_node(self->obj_size, obj);
if (!new_node) return C_ERR_NOMEM;
if (self->size == 0) {
self->head = new_node;
self->tail = new_node;
} else {
new_node->next = self->head;
self->head->prev = new_node;
self->head = new_node;
}
self->size++;
return C_ERR_OK;
}
// 尾端推入 O(1)
c_err_t c_LinkDQueue_PushTail(c_LinkDQueue_t* self, void* obj) {
if (!self || !obj) return C_ERR_PARAM;
c_LinkDQueueNode_t* new_node = create_node(self->obj_size, obj);
if (!new_node) return C_ERR_NOMEM;
if (self->size == 0) {
self->head = new_node;
self->tail = new_node;
} else {
new_node->prev = self->tail;
self->tail->next = new_node;
self->tail = new_node;
}
self->size++;
return C_ERR_OK;
}
// 前端彈出 O(1)
c_err_t c_LinkDQueue_PopHead(c_LinkDQueue_t* self, void* obj) {
if (!self || !obj) return C_ERR_PARAM;
if (self->size == 0) return C_ERR_EMPTY;
c_LinkDQueueNode_t* to_delete = self->head;
memcpy(obj, to_delete->data, self->obj_size);
self->head = to_delete->next;
if (self->head == NULL) {
self->tail = NULL; // 變空佇列
} else {
self->head->prev = NULL;
}
C_FREE(to_delete);
self->size--;
return C_ERR_OK;
}
// 尾端彈出 O(1)
c_err_t c_LinkDQueue_PopTail(c_LinkDQueue_t* self, void* obj) {
if (!self || !obj) return C_ERR_PARAM;
if (self->size == 0) return C_ERR_EMPTY;
c_LinkDQueueNode_t* to_delete = self->tail;
memcpy(obj, to_delete->data, self->obj_size);
self->tail = to_delete->prev;
if (self->tail == NULL) {
self->head = NULL; // 變空佇列
} else {
self->tail->next = NULL;
}
C_FREE(to_delete);
self->size--;
return C_ERR_OK;
}
void* c_LinkDQueue_PeekHead(c_LinkDQueue_t* self) {
if (!self || self->size == 0) return NULL;
return self->head->data;
}
void* c_LinkDQueue_PeekTail(c_LinkDQueue_t* self) {
if (!self || self->size == 0) return NULL;
return self->tail->data;
}
// 迭代器安全刪除:利用雙向指標在 O(1) 修正前後驅關係並安全維護 head/tail
void c_LinkDQueueIter_Remove(c_LinkDQueueIter_t* self) {
if (!self || !self->dqueue || !self->node || !*(self->node)) return;
c_LinkDQueueNode_t* to_delete = *(self->node);
c_LinkDQueue_t* dq = self->dqueue;
// 1. 修正前驅節點的 next 或主結構的 head
*(self->node) = to_delete->next;
// 2. 修正後繼節點的 prev 或主結構的 tail
if (to_delete->next != NULL) {
to_delete->next->prev = to_delete->prev;
} else {
dq->tail = to_delete->prev; // 刪除的是尾端,更新 tail
}
// 3. 釋放資源與修正大小
C_FREE(to_delete);
dq->size--;
}