Minor refactoring and addition of comments

This commit is contained in:
XOR 2023-04-05 00:32:35 +02:00
parent 289de54e7e
commit b37272aa71

61
main.c
View file

@ -1,10 +1,10 @@
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <assert.h>
#define WORD 32
#define TRANSFORM_TABLE_MAX_RAND 4294967296
@ -46,13 +46,13 @@ typedef struct
int get_empty_hashtable_slot(shash_hashtable_t *hashtable)
{
assert(hashtable != NULL);
for (int i = 0; i < hashtable->table_size; i++)
for (unsigned int i = 0; i < hashtable->table_size; i++)
{
if (hashtable->hash_table[i].key == 0)
return i;
}
// Full
// The hashtable is full
return -1;
}
@ -61,23 +61,23 @@ int shash_init_hashtable(shash_hashtable_t *hashtable, unsigned int table_size)
// Initialize the RNG to a non-constant value, to make the output less pseudo random
srand(time(NULL));
// Create a random transformation table
unsigned int *table = malloc((CHAR_MAX - CHAR_MIN) * sizeof(int));
if(table == NULL)
// Create a transformation table
hashtable->transformation_table = malloc((CHAR_MAX - CHAR_MIN) * sizeof(int));
if (hashtable->transformation_table == NULL)
{
return EXIT_FAILURE;
return EXIT_FAILURE;
}
// assign random values to it
for (int i = 0; i < CHAR_MAX - CHAR_MIN; i++)
{
table[i] = TRANSFORM_TABLE_MAX_RAND * rand() / RAND_MAX;
hashtable->transformation_table[i] = TRANSFORM_TABLE_MAX_RAND * rand() / RAND_MAX;
}
hashtable->transformation_table = table;
// Create the hash_table
hashtable->hash_table = malloc(table_size * sizeof(shash_table_element_t));
if(hashtable->hash_table == NULL)
if (hashtable->hash_table == NULL)
{
return EXIT_FAILURE;
return EXIT_FAILURE;
}
memset(hashtable->hash_table, 0, table_size * sizeof(shash_table_element_t));
@ -88,17 +88,17 @@ int shash_init_hashtable(shash_hashtable_t *hashtable, unsigned int table_size)
unsigned int shash_hash(char *key, unsigned int len, shash_hashtable_t *hashtable)
{
assert(hashtable != NULL);
if (SIMULATE_COLLISIONS == 1)
{
return SIMULATED_COLLISION_HASH;
}
// Slight variation of cyclic polynomial hasing, as described in the Paper: "Recursive Hashing functions for n-Grams" by J. D. Cohen
unsigned int hash_word = 0;
for (int i = 0; i < len; i++)
for (unsigned int i = 0; i < len; i++)
{
hash_word = rot32_left(hash_word, 1);
hash_word = hash_word ^ hashtable->transformation_table[key[i]];
hash_word = hash_word ^ hashtable->transformation_table[(unsigned int)key[i]];
}
return hash_word % hashtable->table_size;
@ -109,7 +109,7 @@ int shash_set(char *key, unsigned int len, void *data, shash_hashtable_t *hashta
assert(key != NULL);
assert(data != NULL);
assert(hashtable != NULL);
unsigned int slot = shash_hash(key, len, hashtable);
// Loop to the end of the linked list
@ -122,12 +122,14 @@ int shash_set(char *key, unsigned int len, void *data, shash_hashtable_t *hashta
{
.key = strndup(key, len),
.data = data};
// If there is no element already in the slot, we can just use it
if (hashtable->hash_table[slot].key == 0)
{
hashtable->hash_table[slot] = table_element;
return 0;
return EXIT_SUCCESS;
}
// If not, we need to handle the collision
else
{
int empty_slot = get_empty_hashtable_slot(hashtable);
@ -136,20 +138,21 @@ int shash_set(char *key, unsigned int len, void *data, shash_hashtable_t *hashta
hashtable->hash_table[slot].encountered_collision = 1;
hashtable->hash_table[slot].next_key_location = empty_slot;
hashtable->hash_table[empty_slot] = table_element;
return 0;
return EXIT_SUCCESS;
}
}
// hashtable full
return -1;
return EXIT_FAILURE;
}
void *shash_get(char *key, unsigned int len, shash_hashtable_t *hashtable)
{
assert(key != NULL);
assert(hashtable != NULL);
unsigned int slot = shash_hash(key, len, hashtable);
// Itereate through the link list until we find the right element
while (strcmp(hashtable->hash_table[slot].key, key) != 0)
{
if (hashtable->hash_table[slot].encountered_collision == 1)
@ -170,13 +173,13 @@ void *shash_get(char *key, unsigned int len, shash_hashtable_t *hashtable)
void shash_destroy_hashtable(shash_hashtable_t *hashtable)
{
assert(hashtable != 0);
for(int i = 0; i < hashtable->table_size; i++)
for (unsigned int i = 0; i < hashtable->table_size; i++)
{
if(hashtable->hash_table[i].key != NULL)
{
free(hashtable->hash_table[i].key);
}
if (hashtable->hash_table[i].key != NULL)
{
free(hashtable->hash_table[i].key);
}
}
free(hashtable->transformation_table);
free(hashtable->hash_table);
@ -191,7 +194,7 @@ int main(void)
// Store some data
shash_set("FOO", 3, "Hello", &hashtable);
shash_set("BAR", 3, "World!", &hashtable);
// And retrieve it
char *retrieved_foo = shash_get("FOO", 3, &hashtable);
char *retrieved_bar = shash_get("BAR", 3, &hashtable);