#include #include #include #include #include bool fzl_consts_equal(fzl_const_t a, fzl_const_t b) { if (a.type != b.type) return false; switch (a.type) { case FZL_CONSTTYPE_STRING: { if (a.as.string.length != b.as.string.length) return false; return memcmp(a.as.string.chars, b.as.string.chars, a.as.string.length) == 0; } } return false; } uint32_t fzl_hash_const(fzl_const_t c) { uint32_t hash = 2166136261u; const uint8_t *data = NULL; size_t size = 0; switch (c.type) { case FZL_CONSTTYPE_STRING: data = (const uint8_t *)c.as.string.chars; size = c.as.string.length; break; } for (size_t i = 0; i < size; i++) { hash ^= data[i]; hash *= 16777619u; } return hash; } fzl_const_hash_pool_t *fzl_mkconstpool() { fzl_const_hash_pool_t *pool = malloc(sizeof(fzl_const_hash_pool_t)); pool->size = 0; pool->capacity = 8; pool->array = malloc(pool->capacity * sizeof(fzl_const_t)); pool->slots_count = 0; pool->slots_capacity = 16; pool->slots = malloc(pool->slots_capacity * sizeof(fzl_const_hash_slot_t)); for (size_t i = 0; i < pool->slots_capacity; i++) pool->slots[i].pool_index = -1; return pool; } void fzl_consts_pool_resize_hash(fzl_const_hash_pool_t *pool) { int old_capacity = pool->slots_capacity; fzl_const_hash_slot_t *old_slots = pool->slots; pool->slots_capacity = old_capacity * 2; pool->slots = malloc(pool->slots_capacity * sizeof(fzl_const_hash_slot_t)); for (size_t i = 0; i < pool->slots_capacity; i++) pool->slots[i].pool_index = -1; pool->slots_count = 0; for (int i = 0; i < old_capacity; i++) { if (old_slots[i].pool_index == -1) continue; int index_in_pool = old_slots[i].pool_index; fzl_const_t c = pool->array[index_in_pool]; uint32_t hash = fzl_hash_const(c); uint32_t bucket = hash & (pool->slots_capacity - 1); while (pool->slots[bucket].pool_index != -1) bucket = (bucket + 1) & (pool->slots_capacity - 1); pool->slots[bucket].pool_index = index_in_pool; pool->slots_count++; } free(old_slots); } size_t fzl_consts_pool_add(fzl_const_hash_pool_t *pool, fzl_const_t c) { if (pool->slots_count * 4 >= pool->slots_capacity * 3) fzl_consts_pool_resize_hash(pool); uint32_t hash = fzl_hash_const(c); uint32_t bucket = hash & (pool->slots_capacity - 1); while (pool->slots[bucket].pool_index != -1) { size_t existing_index = pool->slots[bucket].pool_index; if (fzl_consts_equal(pool->array[existing_index], c)) return existing_index; bucket = (bucket + 1) & (pool->slots_capacity - 1); } if (pool->size >= pool->capacity) { pool->capacity *= 2; pool->array = (fzl_const_t *)realloc(pool->array, pool->capacity * sizeof(fzl_const_t)); } size_t new_index = pool->size; pool->array[new_index] = c; pool->size++; pool->slots[bucket].pool_index = new_index; pool->slots_count++; return new_index; } void fzl_consts_pool_free(fzl_const_hash_pool_t *pool) { if (!pool) return; free(pool->array); free(pool->slots); free(pool); }