static void gu_map_finalize(GuFinalizer* fin) { GuMap* map = gu_container(fin, GuMap, fin); gu_mem_buf_free(map->data.keys); if (map->value_size) { gu_mem_buf_free(map->data.values); } }
static void gu_buf_fini(GuFinalizer* fin) { GuBuf* buf = gu_container(fin, GuBuf, fin); gu_mem_buf_free(buf->data); }
static void gu_map_resize(GuMap* map) { GuMapData* data = &map->data; GuMapData old_data = *data; size_t req_entries = gu_twin_prime_sup(GU_MAX(11, map->data.n_occupied * 4 / 3 + 1)); size_t key_size = map->key_size; size_t key_alloc = 0; data->keys = gu_mem_buf_alloc(req_entries * key_size, &key_alloc); size_t value_size = map->value_size; size_t value_alloc = 0; if (value_size) { data->values = gu_mem_buf_alloc(req_entries * value_size, &value_alloc); memset(data->values, 0, value_alloc); } data->n_entries = gu_twin_prime_inf(value_size ? GU_MIN(key_alloc / key_size, value_alloc / value_size) : key_alloc / key_size); switch (map->kind) { case GU_MAP_GENERIC: case GU_MAP_WORD: memset(data->keys, 0, key_alloc); break; case GU_MAP_ADDR: for (size_t i = 0; i < data->n_entries; i++) { ((const void**)data->keys)[i] = NULL; } break; case GU_MAP_STRING: for (size_t i = 0; i < data->n_entries; i++) { ((GuString*)data->keys)[i] = NULL; } break; default: gu_impossible(); } gu_assert(data->n_entries > data->n_occupied); data->n_occupied = 0; data->zero_idx = SIZE_MAX; for (size_t i = 0; i < old_data.n_entries; i++) { if (gu_map_entry_is_free(map, &old_data, i)) { continue; } void* old_key = &old_data.keys[i * key_size]; if (map->kind == GU_MAP_ADDR) { old_key = *(void**)old_key; } else if (map->kind == GU_MAP_STRING) { old_key = (void*) *(GuString*)old_key; } void* old_value = &old_data.values[i * value_size]; memcpy(gu_map_insert(map, old_key), old_value, map->value_size); } gu_mem_buf_free(old_data.keys); if (value_size) { gu_mem_buf_free(old_data.values); } }