#include /* ------------------------------------------------------------------------------------------------------------------ */ /* */ // 辅助内联宏:通过节点指针直接获取其内部存储的用户数据区地址 #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; } // 辅助函数:创建承载用户数据的值复制节点 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; new_node->next = NULL; memcpy(NODE_DATA(new_node), item, self->item_size); // 泛型值深度复制 return new_node; } // O(1) 头部高效插入 c_err_t c_LinkList_AddHead(c_LinkList_t* self, const void* item) { if (!self || !self->head || !item) return C_ERR_PARAM; c_LinkNode_t* new_node = c_LinkList_CreateNode(self, item); if (!new_node) return C_ERR_NOMEM; 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_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_LinkNode_t* curr = self->head; // 从真实的 head 节点起步 for (c_size_t i = 0; i < index; i++) { curr = curr->next; } memcpy(out_item, NODE_DATA(curr), self->item_size); return C_ERR_OK; } // 只读原位窥探指针(注意:不要在发生 Add/Remove 后持久持有它,防止发生野指针悬空) void* c_LinkList_Get(const c_LinkList_t* self, c_size_t index) { if (!self || index >= self->size) return NULL; 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); }