重构
This commit is contained in:
+115
-54
@@ -1,82 +1,143 @@
|
||||
#include <c_LinkList.h>
|
||||
#include <c_Memory.h>
|
||||
#include <c_Alignment.h>
|
||||
#include "c_Macros.h"
|
||||
|
||||
c_err_t c_LinkList_Init(c_LinkList_t* self, c_size_t obj_size) {
|
||||
if (!self || obj_size == 0) return C_ERR_PARAM;
|
||||
self->head = NULL;
|
||||
self->obj_size = (int)obj_size;
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
// 辅助内联宏:通过节点指针直接获取其内部存储的用户数据区地址
|
||||
#define NODE_DATA(node) ((void*)((char*)(node) + sizeof(c_LinkNode_t)))
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
|
||||
// 原地初始化:建立哑哨兵头节点
|
||||
c_err_t c_LinkList_Init(c_LinkList_t* self, c_size_t item_size, 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;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
void c_LinkList_Destroy(c_LinkList_t* self) {
|
||||
if (!self) return;
|
||||
// 辅助函数:创建承载用户数据的值复制节点
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_LinkNode_t* c_LinkList_CreateNode(c_LinkList_t* self, const void* item) {
|
||||
c_size_t total_bytes = sizeof(c_LinkNode_t) + self->item_size;
|
||||
c_LinkNode_t* new_node = (c_LinkNode_t*)c_Allocator_Alloc(&self->allocator, total_bytes);
|
||||
if (!new_node) return NULL;
|
||||
|
||||
c_LinkListNode_t* current = self->head;
|
||||
while (current != NULL) {
|
||||
c_LinkListNode_t* next = current->next;
|
||||
// 由於 Add 時 data 與 node 是分開或合開,此處依據一體化配置釋放
|
||||
C_FREE(current);
|
||||
current = next;
|
||||
}
|
||||
self->head = NULL;
|
||||
self->size = 0;
|
||||
new_node->next = NULL;
|
||||
memcpy(NODE_DATA(new_node), item, self->item_size); // 泛型值深度复制
|
||||
return new_node;
|
||||
}
|
||||
|
||||
c_err_t c_LinkList_Add(c_LinkList_t* self, void* obj) {
|
||||
if (!self || !obj) return C_ERR_PARAM;
|
||||
// O(1) 头部高效插入
|
||||
c_err_t c_LinkList_AddHead(c_LinkList_t* self, const void* item) {
|
||||
if (!self || !self->head || !item) return C_ERR_PARAM;
|
||||
|
||||
int size = (int)sizeof(c_LinkListNode_t) + self->obj_size;
|
||||
size = C_ALIGN_UPB(size, C_ALIGN_SIZE);
|
||||
c_LinkListNode_t* new_node = (c_LinkListNode_t*)C_ALLOC(size);
|
||||
c_LinkNode_t* new_node = c_LinkList_CreateNode(self, item);
|
||||
if (!new_node) return C_ERR_NOMEM;
|
||||
new_node->data = new_node+1;
|
||||
|
||||
// 值複製 (Value Copy)
|
||||
memcpy(new_node->data, obj, self->obj_size);
|
||||
|
||||
// 頭插法鏈結
|
||||
new_node->next = self->head;
|
||||
self->head = new_node;
|
||||
|
||||
self->size++;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
// O(N) 尾部追加插入
|
||||
c_err_t c_LinkList_AddTail(c_LinkList_t* self, const void* item) {
|
||||
if (!self || !item) return C_ERR_PARAM;
|
||||
|
||||
// 二级指针直接指向控制头里的 head 指针变量本身地址
|
||||
c_LinkNode_t** pp = &(self->head);
|
||||
|
||||
// 一路滑移到单链表的尽头(即找到那个内部存储着 NULL 的坑位)
|
||||
while (*pp != NULL) {
|
||||
pp = &((*pp)->next);
|
||||
}
|
||||
|
||||
// 此时 *pp 必然是 NULL。不管链表原先是不是空,我们直接用这行代码注入新节点地址:
|
||||
*pp = c_LinkList_CreateNode(self, item);
|
||||
if (!*pp) return C_ERR_NOMEM;
|
||||
|
||||
self->size++;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
// 【二级指针艺术】:根据指定索引精准裁剪节点,并扣减计数
|
||||
c_err_t c_LinkList_RemoveAt(c_LinkList_t* self, c_size_t index, void* out_item) {
|
||||
if (!self || index >= self->size) return C_ERR_PARAM;
|
||||
|
||||
// 初始咬定核心变量 &self->head 坑位地址
|
||||
c_LinkNode_t** pp = &(self->head);
|
||||
|
||||
// 精准步进到要移除的索引位置
|
||||
for (c_size_t i = 0; i < index; i++) {
|
||||
pp = &((*pp)->next);
|
||||
}
|
||||
|
||||
// 此时 *pp 正好是“指向要被删除节点”的物理指针
|
||||
c_LinkNode_t* node_to_free = *pp;
|
||||
|
||||
if (out_item) {
|
||||
memcpy(out_item, NODE_DATA(node_to_free), self->item_size);
|
||||
}
|
||||
|
||||
// 核心裁剪:直接重写前驱的指针域。如果 index 为 0,这里等同于就地修改了 self->head 的值!
|
||||
// 一行代码,完美合并了“删除第一个节点”和“删除后续项”的两套高危处理流
|
||||
*pp = node_to_free->next;
|
||||
|
||||
// 回收资源并扣减账目
|
||||
c_Allocator_Free(&self->allocator, node_to_free);
|
||||
self->size--;
|
||||
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
c_err_t c_LinkList_Remove(c_LinkList_t* self, void* obj) {
|
||||
if (!self || !obj) return C_ERR_PARAM;
|
||||
// 安全的从链表中读取指定索引处的值拷贝
|
||||
c_err_t c_LinkList_Read(const c_LinkList_t* self, c_size_t index, void* out_item) {
|
||||
if (!self || !out_item || index >= self->size) return C_ERR_PARAM;
|
||||
|
||||
c_LinkListNode_t** curr = &self->head;
|
||||
while (*curr != NULL) {
|
||||
// 使用 memcmp 進行二進位值比對
|
||||
if (memcmp((*curr)->data, obj, self->obj_size) == 0) {
|
||||
c_LinkListNode_t* to_delete = *curr;
|
||||
*curr = to_delete->next;
|
||||
|
||||
C_FREE(to_delete);
|
||||
self->size--;
|
||||
return C_ERR_OK;
|
||||
}
|
||||
curr = &(*curr)->next;
|
||||
c_LinkNode_t* curr = self->head; // 从真实的 head 节点起步
|
||||
for (c_size_t i = 0; i < index; i++) {
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
return C_ERR_FAIL;
|
||||
memcpy(out_item, NODE_DATA(curr), self->item_size);
|
||||
return C_ERR_OK;
|
||||
}
|
||||
|
||||
void c_LinkListIter_Remove(c_LinkListIter_t* self) {
|
||||
if (!self || !self->list || !self->node || !*(self->node)) return;
|
||||
// 只读原位窥探指针(注意:不要在发生 Add/Remove 后持久持有它,防止发生野指针悬空)
|
||||
void* c_LinkList_Get(const c_LinkList_t* self, c_size_t index) {
|
||||
if (!self || index >= self->size) return NULL;
|
||||
|
||||
c_LinkListNode_t* to_delete = *(self->node);
|
||||
|
||||
// 讓上一個節點的 next 指向下一個節點,移除鏈結
|
||||
*(self->node) = to_delete->next;
|
||||
|
||||
// 釋放該節點的值與結構
|
||||
C_FREE(to_delete);
|
||||
|
||||
self->list->size--;
|
||||
c_LinkNode_t* curr = self->head;
|
||||
for (c_size_t i = 0; i < index; i++) {
|
||||
curr = curr->next;
|
||||
}
|
||||
return NODE_DATA(curr);
|
||||
}
|
||||
|
||||
// 快速清空链表
|
||||
void c_LinkList_Clear(c_LinkList_t* self) {
|
||||
if (!self) return;
|
||||
|
||||
c_LinkNode_t* curr = self->head;
|
||||
while (curr) {
|
||||
c_LinkNode_t* next_to_free = curr->next;
|
||||
c_Allocator_Free(&self->allocator, curr);
|
||||
curr = next_to_free;
|
||||
}
|
||||
self->head = NULL; // 还原到你 Init 指定的 0 状态
|
||||
self->size = 0;
|
||||
}
|
||||
|
||||
// 彻底解体
|
||||
void c_LinkList_Destroy(c_LinkList_t* self) {
|
||||
if (!self) return;
|
||||
c_LinkList_Clear(self);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user