diff --git a/Include/Fledasty/Core/HashTable.h b/Include/Fledasty/Core/HashTable.h index ab26d1e..5c1ceaa 100644 --- a/Include/Fledasty/Core/HashTable.h +++ b/Include/Fledasty/Core/HashTable.h @@ -51,8 +51,9 @@ void *fledasty_hash_table_get(const FledastyHashTable *current_hash_table, void FledastyError fledasty_hash_table_remove(FledastyHashTable *current_hash_table, void *key); FledastyError fledasty_hash_table_clear(FledastyHashTable *current_hash_table); +FledastyError fledasty_hash_table_shrink_to_fit(FledastyHashTable *current_hash_table); bool fledasty_hash_table_has_key(const FledastyHashTable *current_hash_table, void *key); static inline bool fledasty_hash_table_is_empty(const FledastyHashTable *current_hash_table) { return current_hash_table == NULL || current_hash_table->size == 0; } -#endif \ No newline at end of file +#endif diff --git a/Src/Core/HashTable.c b/Src/Core/HashTable.c index 19a5b5b..d0e813b 100644 --- a/Src/Core/HashTable.c +++ b/Src/Core/HashTable.c @@ -71,7 +71,6 @@ FledastyError fledasty_hash_table_insert(FledastyHashTable *current_hash_table, return FLEDASTY_ERROR_INVALID_POINTER; } - current_hash_table->size += 1; if (current_hash_table->size >= (current_hash_table->capacity * FLEDASTY_HASH_TABLE_SIZE_THRESHOLD) / 100) { const size_t old_capacity = current_hash_table->capacity; FledastyDynamicArray *previous_table = current_hash_table->Table; @@ -129,8 +128,9 @@ FledastyError fledasty_hash_table_insert(FledastyHashTable *current_hash_table, } hallocy_copy_memory(pair.value, value, current_hash_table->value_byte_size); - fledasty_dynamic_array_append(¤t_hash_table->Table[index], &pair); + + current_hash_table->size += 1; return FLEDASTY_ERROR_NONE; } @@ -138,7 +138,7 @@ void *fledasty_hash_table_get(const FledastyHashTable *current_hash_table, void if (current_hash_table == NULL || key == NULL) { return NULL; } - + const size_t index = current_hash_table->hash_function(key) % current_hash_table->capacity; if (current_hash_table->Table[index].buffer == NULL) { return NULL; @@ -208,6 +208,49 @@ FledastyError fledasty_hash_table_clear(FledastyHashTable *current_hash_table) { return FLEDASTY_ERROR_NONE; } +FledastyError fledasty_hash_table_shrink_to_fit(FledastyHashTable *current_hash_table) { + if (current_hash_table == NULL) { + return FLEDASTY_ERROR_INVALID_POINTER; + } + + const size_t old_capacity = current_hash_table->capacity; + FledastyDynamicArray *previous_table = current_hash_table->Table; + + current_hash_table->capacity = (current_hash_table->size * 100) / FLEDASTY_HASH_TABLE_SIZE_THRESHOLD; + if (current_hash_table->capacity == 0) { + current_hash_table->capacity = 1024; + } + + current_hash_table->Table = (FledastyDynamicArray*)hallocy_calloc(sizeof(FledastyDynamicArray), current_hash_table->capacity); + if (current_hash_table->Table == NULL) { + return FLEDASTY_ERROR_FAILED_ALLOCATION; + } + + for (size_t index = 0; index < old_capacity; index += 1) { + FledastyDynamicArray *current_dynamic_array = previous_table + index; + if (current_dynamic_array->buffer != NULL) { + for (size_t list_index = 0; list_index < current_dynamic_array->size; list_index += 1) { + FledastyHashTablePair *pair = (FledastyHashTablePair*)fledasty_dynamic_array_get(current_dynamic_array, list_index); + + const size_t key_index = current_hash_table->hash_function(pair->key) % current_hash_table->capacity; + if (current_hash_table->Table[key_index].buffer == NULL) { + FledastyError result = fledasty_dynamic_array_initialize(current_hash_table->Table + key_index, NULL, 0, sizeof(FledastyHashTablePair)); + if (result != FLEDASTY_ERROR_NONE) { + return result; + } + } + + fledasty_dynamic_array_append(current_hash_table->Table + key_index, pair); + } + + fledasty_dynamic_array_destroy(current_dynamic_array); + } + } + + hallocy_free(previous_table); + return FLEDASTY_ERROR_NONE; +} + bool fledasty_hash_table_has_key(const FledastyHashTable *current_hash_table, void *key) { if (current_hash_table == NULL || key == NULL) { return false; diff --git a/Tests/Main.c b/Tests/Main.c index 4ce0f77..fab8be1 100644 --- a/Tests/Main.c +++ b/Tests/Main.c @@ -29,7 +29,7 @@ #include #include -static inline size_t integer_hash_function(const void *key) { return *(size_t*)key; } +static inline size_t integer_hash_function(const void *key) { return *(int*)key; } int main() { FledastyQueue test_queue; @@ -207,6 +207,8 @@ int main() { fledasty_hash_table_insert(&test_hash_table, &pow_value, &i); } + fledasty_hash_table_shrink_to_fit(&test_hash_table); + int hash_table_value = 5; int hash_table_remove = 2; fledasty_hash_table_insert(&test_hash_table, &hash_table_remove, &hash_table_value);