Files
scc/lib/utils/ds/hashtable.c
ZZY 05c637e594 refactor: 重构前端代码并添加日志功能
- 重命名和重构了多个文件,包括 lexer、parser 和 AST 相关代码
- 添加了日志功能,使用 LOG_* 宏替代原有的 error 和 warn 函数
- 优化了错误处理和内存分配方式
- 调整了代码结构,提高了模块化和可读性
2025-03-19 12:22:55 +08:00

142 lines
4.0 KiB
C

#include "hashtable.h"
#define LOAD_FACTOR 0.75f
// 素数表用于桶扩容(最后一个元素为最大允许容量)
static const int PRIME_CAPACITIES[] = {
11, 23, 47, 97, 193, 389, 769, 1543, 3079,
6151, 12289, 24593, 49157, 98317, 196613, 393241,
786433, 1572869, 3145739, 6291469, 12582917, 25165843
};
// 私有函数声明
static u32_t calc_hash(const char* str, int len);
static void rehash(hash_table_t* ht);
hash_table_t* new_hash_table(int init_size, int max_cap) {
hash_table_t* ht = salloc_alloc(sizeof(hash_table_t));
hash_table_init(ht, init_size, max_cap);
return ht;
}
static inline get_real_size(int size) {
// 查找第一个不小于size的素数容量
int cap_idx = 0;
if (size < 0) {
return PRIME_CAPACITIES[SMCC_ARRLEN(PRIME_CAPACITIES)-1];
}
while (PRIME_CAPACITIES[cap_idx] < size && cap_idx < SMCC_ARRLEN(PRIME_CAPACITIES)-1) {
cap_idx++;
}
return PRIME_CAPACITIES[cap_idx];
}
void hash_table_init(hash_table_t* ht, int init_size, int max_cap) {
// 限制最大容量索引
ht->max_cap = get_real_size(max_cap);
// 应用实际容量
ht->cap = get_real_size(init_size);
ht->size = 0;
ht->buckets = NULL;
ht->buckets = salloc_realloc(ht->buckets, sizeof(hash_node_t*) * ht->cap);
}
void hash_table_insert(hash_table_t* ht, const char* str, int len) {
// 自动扩容检查
if (ht->size >= ht->cap * LOAD_FACTOR && ht->cap < ht->max_cap) {
rehash(ht);
}
if (ht->size >= ht->cap) {
LOG_TRACE("Hash table size exceeds maximum capacity. Consider increasing max_capacity.");
}
// 计算哈希值
u32_t hash = calc_hash(str, len);
int bucket_idx = hash % ht->cap;
// 检查重复
hash_node_t* node = ht->buckets[bucket_idx];
while (node) {
if (node->hash == hash &&
node->len == len &&
memcmp(node->str, str, len) == 0) {
return; // 已存在
}
node = node->next;
}
// 创建新节点
hash_node_t* new_node = salloc_alloc(sizeof(hash_node_t));
new_node->str = str;
new_node->len = len;
new_node->hash = hash;
new_node->next = ht->buckets[bucket_idx];
ht->buckets[bucket_idx] = new_node;
ht->size++;
}
hash_node_t* hash_table_find(hash_table_t* ht, const char* str, int len) {
u32_t hash = calc_hash(str, len);
int bucket_idx = hash % ht->cap;
hash_node_t* node = ht->buckets[bucket_idx];
while (node) {
if (node->hash == hash &&
node->len == len &&
memcmp(node->str, str, len) == 0) {
return node;
}
node = node->next;
}
return NULL;
}
static void rehash(hash_table_t* ht) {
int old_cap = ht->cap;
hash_node_t** old_buckets = ht->buckets;
// 查找下一个素数容量
int new_cap_idx = 0;
while (PRIME_CAPACITIES[new_cap_idx] <= old_cap &&
new_cap_idx < ht->max_cap) {
new_cap_idx++;
}
ht->cap = PRIME_CAPACITIES[new_cap_idx];
// 分配新桶数组
ht->buckets = salloc_alloc(sizeof(hash_node_t*) * ht->cap);
memset(ht->buckets, 0, sizeof(hash_node_t*) * ht->cap);
// 重新哈希所有节点
for (int i = 0; i < old_cap; i++) {
hash_node_t* node = old_buckets[i];
while (node) {
hash_node_t* next = node->next;
int new_bucket = node->hash % ht->cap;
node->next = ht->buckets[new_bucket];
ht->buckets[new_bucket] = node;
node = next;
}
}
salloc_free(old_buckets);
}
static u32_t calc_hash(const char* str, int len) {
// 使用与HASH_FNV_1A宏一致的算法
rt_strhash(str);
}
void hash_table_destroy(hash_table_t* ht) {
for (int i = 0; i < ht->cap; i++) {
hash_node_t* node = ht->buckets[i];
while (node) {
hash_node_t* next = node->next;
salloc_free(node);
node = next;
}
}
salloc_free(ht->buckets);
ht->buckets = NULL;
ht->size = ht->cap = 0;
}