diff --git a/includes/hashtable.h b/includes/hashtable.h new file mode 100644 index 0000000..c4f4eec --- /dev/null +++ b/includes/hashtable.h @@ -0,0 +1,25 @@ +#ifndef HASTABLE_H +#define HASTABLE_H + +typedef struct { + char* Key; + char* Value; +} BucketKeyPair; + +typedef struct { + unsigned int Size; + unsigned int Capacity; + BucketKeyPair** KeyPairs; +} Bucket; + +typedef struct { + unsigned int Capacity; + Bucket** Values; +} HashTable; + +HashTable* CreateHashTable(void); +void AddItemToHashTable(char* key, char* item, HashTable* table); +char* GetHashTableItem(char* key, HashTable* table); +void PrintHashTable(HashTable* table); + +#endif \ No newline at end of file diff --git a/src/hashtable.c b/src/hashtable.c new file mode 100644 index 0000000..63103b2 --- /dev/null +++ b/src/hashtable.c @@ -0,0 +1,106 @@ +#include "../includes/hashtable.h" +#include +#include +#include + +//Reference https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash +//FNV = Fowler–Noll–Vo +#define FNV_OFFSET 0xcbf29ce484222325 //Or 14695981039346656037 in decimal +#define FNV_PRIME 0x100000001b3 //Or 1099511628211 in decimal +#define DEFAULTHASHTABLESIZE 64 + +Bucket* CreateBucket(); +void AddToBucket(char* key, char* text, Bucket* bucket); + +HashTable* CreateHashTable(void) { + HashTable* table = calloc(1, sizeof(HashTable)); + + table->Values = calloc(DEFAULTHASHTABLESIZE, sizeof(Bucket*)); + table->Capacity = DEFAULTHASHTABLESIZE; + + return table; +} + +void AddItemToHashTable(char* key, char* item, HashTable* table) { + //FNV-1a hash + unsigned long long hash = FNV_OFFSET; + + for(int i = 0; i < strlen(key); i ++) { + hash ^= key[i]; + hash *= FNV_PRIME; + } + + unsigned int index = hash % table->Capacity; + + Bucket* bucket = table->Values[index]; + + if (!bucket) table->Values[index] = CreateBucket(); + + AddToBucket(key, item, table->Values[index]); +} + +char* HashTableBucketLinearScan(char* key, Bucket* bucket) { + for(int i = 0; i < bucket->Size; i++) { + BucketKeyPair* pair = bucket->KeyPairs[i]; + + if (strcmp(key, pair->Key) == 0) return pair->Value; + } + + return NULL; +} + +char* GetHashTableItem(char* key, HashTable* table) { + unsigned long long hash = FNV_OFFSET; + + for(int i = 0; i < strlen(key); i ++) { + hash ^= key[i]; + hash *= FNV_PRIME; + } + + unsigned int index = hash % table->Capacity; + + Bucket* bucket = table->Values[index]; + + if (!bucket) return NULL; + + if (bucket->Size == 1) return bucket->KeyPairs[0]->Value; + + return HashTableBucketLinearScan(key, bucket); +} + +Bucket* CreateBucket() { + Bucket* bucket = calloc(1, sizeof(Bucket)); + + bucket->KeyPairs = calloc(16, sizeof(BucketKeyPair*)); + bucket->Capacity = 16; + + return bucket; +} + +void AddToBucket(char* key, char* text, Bucket* bucket) { + BucketKeyPair* keyPair = calloc(1, sizeof(BucketKeyPair)); + keyPair->Key = key; + keyPair->Value = text; + + bucket->KeyPairs[bucket->Size] = keyPair; + + bucket->Size++; +} + +void PrintHashTable(HashTable* table) { + printf("Capacity %d\nBuckets:\n", table->Capacity); + + for(int i = 0; i < table->Capacity; i++) { + Bucket* bucket = table->Values[i]; + + if (!bucket) continue; + + printf("Bucket %d: \n", i+1); + + for(int j = 0; j < bucket->Size; j++) { + printf("(%s) '%s'\n", bucket->KeyPairs[j]->Key, bucket->KeyPairs[j]->Value); + } + + printf("\n"); + } +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index 64395f2..59fe009 100644 --- a/src/main.c +++ b/src/main.c @@ -19,6 +19,7 @@ #include #include "../includes/font_cache.h" #include "../includes/list.h" +#include "../includes/hashtable.h" const int SCREEN_WIDTH = 1280; const int SCREEN_HEIGHT = 720; @@ -131,7 +132,13 @@ int main(int argc, char** argv){ AddStringToList("Hello World! 4 and a reallly long sting", list); ListFontSizeHasChanged(app.renderer, GetFont(app.DefaultFontSize, app.FontCache), list); + HashTable* table = CreateHashTable(); + AddItemToHashTable("TEST", "Hello, World!", table); + AddItemToHashTable("TEST2", "Hello, World", table); + AddItemToHashTable("No here", "Hello, 3", table); + PrintHashTable(table); + printf("Got %s with key %s\n", GetHashTableItem("TEST", table), "TEST"); // Uint64 start = 0; // Uint64 end = 0; // float frameCount = 0;