159 lines
6.3 KiB
C
159 lines
6.3 KiB
C
#include <c_StringList.h>
|
|||
|
|
|
||
|
|
c_err_t c_StringList_Init(c_StringList* self, c_size_t capacity, c_Allocator_t* allocator) {
|
||
|
|
if (!self) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
self->allocator = (allocator != NULL) ? *allocator : c_DefaultAllocator;
|
||
|
|
self->size = 0;
|
||
|
|
self->capacity = (capacity > 0) ? capacity : 4; // 默认初始槽位预留 4 项
|
||
|
|
|
||
|
|
// 闭环通过内部绑定的多态分配器,开辟二级指针控制矩阵的大底座连续空间
|
||
|
|
self->strings = (char**)c_Allocator_Alloc(&self->allocator, self->capacity * sizeof(char*));
|
||
|
|
if (!self->strings) {
|
||
|
|
self->capacity = 0;
|
||
|
|
return C_ERR_NOMEM;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 严维抹零:确保内部所有裸指针槽位初始皆为安全的纯净 NULL 状态
|
||
|
|
memset((void*)self->strings, 0, self->capacity * sizeof(char*));
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
void c_StringList_Clear(c_StringList* self) {
|
||
|
|
if (!self || !self->strings) return;
|
||
|
|
|
||
|
|
// 【核心深清算】:必须先顺着槽位将当前持有的每一个独占字符串物理火化,退还给内置分配器
|
||
|
|
for (c_size_t i = 0; i < self->size; i++) {
|
||
|
|
if (self->strings[i]) {
|
||
|
|
c_Allocator_Free(&self->allocator, self->strings[i]);
|
||
|
|
self->strings[i] = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
self->size = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void c_StringList_Destroy(c_StringList* self) {
|
||
|
|
if (!self) return;
|
||
|
|
|
||
|
|
if (self->strings) {
|
||
|
|
c_StringList_Clear(self); // 先洗刷释放内部行字符串
|
||
|
|
c_Allocator_Free(&self->allocator, self->strings); // 再一并火化指针矩阵底座
|
||
|
|
self->strings = NULL;
|
||
|
|
}
|
||
|
|
self->capacity = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief 内部私有自动动态翻倍扩容算法
|
||
|
|
* @note 强异常安全性:若分配器因碎片满或爆仓返回 NULL,原有数据指针及老矩阵原样完整留存,绝不发生物理跑飞
|
||
|
|
*/
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
bool c_StringList_EnsureCapacity(c_StringList* self) {
|
||
|
|
if (self->size < self->capacity) return true;
|
||
|
|
|
||
|
|
c_size_t old_bytes = self->capacity * sizeof(char*);
|
||
|
|
c_size_t new_capacity = self->capacity * 2;
|
||
|
|
c_size_t new_bytes = new_capacity * sizeof(char*);
|
||
|
|
|
||
|
|
// 对接你最新的 Realloc 包装,闭环支持伙伴系统在同一阶数(Order)内的 O(1) 原地续约物理搬迁
|
||
|
|
void* new_matrix = c_Allocator_Realloc(&self->allocator, self->strings, old_bytes, new_bytes);
|
||
|
|
if (!new_matrix) return false;
|
||
|
|
|
||
|
|
self->strings = (char**)new_matrix;
|
||
|
|
self->capacity = new_capacity;
|
||
|
|
|
||
|
|
// 将新扩出来的后半段空白区指针槽位执行原位抹零
|
||
|
|
c_size_t gap_slots = self->capacity - self->size;
|
||
|
|
memset((void*)(self->strings + self->size), 0, gap_slots * sizeof(char*));
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 2. 核心深度值复制增删控制操作 API
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
c_err_t c_StringList_InsertAt(c_StringList* self, c_size_t index, const char* str) {
|
||
|
|
if (!self || !str || index > self->size) return C_ERR_PARAM;
|
||
|
|
if (!c_StringList_EnsureCapacity(self)) return C_ERR_NOMEM;
|
||
|
|
|
||
|
|
c_size_t str_bytes = (c_size_t)strlen(str) + 1; // 包含 \0 封底位
|
||
|
|
// 从自身绑定的多态分配器中,为当前新加入的项单独申领专属独立生存空间
|
||
|
|
char* owned_str = (char*)c_Allocator_Alloc(&self->allocator, str_bytes);
|
||
|
|
if (!owned_str) return C_ERR_NOMEM;
|
||
|
|
memcpy(owned_str, str, str_bytes); // 深度复制值复制,彻底与外部解耦
|
||
|
|
|
||
|
|
// 利用重叠安全的 memmove 将目标索引右侧的所有行指针整体右推滑移一格
|
||
|
|
if (index < self->size) {
|
||
|
|
memmove(self->strings + index + 1, self->strings + index, (self->size - index) * sizeof(char*));
|
||
|
|
}
|
||
|
|
|
||
|
|
self->strings[index] = owned_str;
|
||
|
|
self->size++;
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_StringList_Add(c_StringList* self, const char* str) {
|
||
|
|
return c_StringList_InsertAt(self, self->size, str); // 末尾追加
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_StringList_RemoveAt(c_StringList* self, c_size_t index) {
|
||
|
|
if (!self || index >= self->size || !self->strings) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
// ① 定点火化销毁当前槽位持有的独占堆字符串,归还空间
|
||
|
|
c_Allocator_Free(&self->allocator, self->strings[index]);
|
||
|
|
|
||
|
|
// ② 自左向右推进,将右侧后续有效项指针依序前移一格,完美重组填补空缺
|
||
|
|
if (index < self->size - 1) {
|
||
|
|
memmove(self->strings + index, self->strings + index + 1, (self->size - index - 1) * sizeof(char*));
|
||
|
|
}
|
||
|
|
|
||
|
|
// 将滑移后腾出来的最后一个残存指针坑位强制置空,杜绝野指针残存
|
||
|
|
self->strings[self->size - 1] = NULL;
|
||
|
|
self->size--;
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================================================================================================================
|
||
|
|
// 3. 高级功能:链表深克隆与高速去重
|
||
|
|
// ==================================================================================================================
|
||
|
|
|
||
|
|
c_err_t c_StringList_Clone(c_StringList* dest, const c_StringList* src) {
|
||
|
|
if (!dest || !src || dest == src || !src->strings) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
// 清算 dest 先前绑定的生命线
|
||
|
|
c_StringList_Clear(dest);
|
||
|
|
|
||
|
|
// 强制将 dest 的容量与 src 完全对齐齐平
|
||
|
|
if (dest->capacity < src->size) {
|
||
|
|
c_StringList_Destroy(dest);
|
||
|
|
c_err_t err = c_StringList_Init(dest, src->size, &dest->allocator);
|
||
|
|
if (err != C_ERR_OK) return err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 顺着槽位依次遍历执行行级专属大连续深拷贝
|
||
|
|
for (c_size_t i = 0; i < src->size; i++) {
|
||
|
|
c_err_t err = c_StringList_Add(dest, src->strings[i]);
|
||
|
|
if (err != C_ERR_OK) return err;
|
||
|
|
}
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_StringList_Deduplicate(c_StringList* self) {
|
||
|
|
if (!self || self->size <= 1 || !self->strings) return C_ERR_OK;
|
||
|
|
|
||
|
|
// O(N^2) 经典原位原地重排去重流
|
||
|
|
for (c_size_t i = 0; i < self->size; i++) {
|
||
|
|
for (c_size_t j = i + 1; j < self->size; ) {
|
||
|
|
if (strcmp(self->strings[i], self->strings[j]) == 0) {
|
||
|
|
// 撞特征重复!直接调用内部定点 RemoveAt 擦除拓扑,其内部会自动左移并 size--
|
||
|
|
c_StringList_RemoveAt(self, j);
|
||
|
|
// 此时后续槽位前移填补了坑位,j 不需要递增,原位继续二次判定
|
||
|
|
} else {
|
||
|
|
j++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return C_ERR_OK;
|
||
|
|
}
|