Skip to content

Commit

Permalink
Fix broken hash
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeRoggenbuck committed Aug 4, 2024
1 parent 0640b2a commit 3a45451
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 19 deletions.
48 changes: 32 additions & 16 deletions src/util/hashmap.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
#include "hashmap.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <testing/tassert.h>
#include <testing/test_utils.h>

unsigned fnva1(char *value) {
unsigned long long h = 14695981039346656037;
long int prime = 1099511628211;
unsigned long h = 16777619;
long int prime = 2166136261;

while (value) {
h ^= prime;
(*value)++;
while (*value != '\0') {
h ^= *value;
h *= prime;
++value;
}

return h;
}

unsigned equal_key(char *a, char *b) { return strcmp(a, b) == 0; }

struct Hashmap *create_hashmap(int capacity) {
struct Hashmap *h = malloc(sizeof(struct Hashmap));

Expand All @@ -26,6 +30,7 @@ struct Hashmap *create_hashmap(int capacity) {
h->cap = capacity;

h->hash = fnva1;
h->equals = equal_key;

return h;
}
Expand All @@ -35,7 +40,7 @@ void destroy_hashmap(struct Hashmap *h) {
free(h);
}

struct BucketNode *create_bucket(void *key, void *value) {
struct BucketNode *create_bucket(char *key, void *value) {
struct BucketNode *b = malloc(sizeof(struct BucketNode));

b->key = key;
Expand All @@ -45,40 +50,51 @@ struct BucketNode *create_bucket(void *key, void *value) {
return b;
}

struct BucketNode *hm_get(struct Hashmap *h, void *key) {
struct BucketNode *hm_get(struct Hashmap *h, char *key) {
unsigned a = h->hash(key) % h->cap;

struct BucketNode *b = h->buckets[a];
if (b != NULL) {

// Check if key is the same, because the hash might have collided
while (!h->equals(key, b->key)) {
b = b->next;
}
if (b == NULL) {
return NULL;
}

if (h->equals(b->key, key)) {
return b;
}

// check for linear probing

return NULL;
}

int hm_set(struct Hashmap *h, void *key, void *value) {
int hm_set(struct Hashmap *h, char *key, void *value) {
unsigned a = h->hash(key) % h->cap;

struct BucketNode *b = h->buckets[a];

if (b == NULL) {
if (h->size == h->cap) {
double_cap(h);
}

h->size++;

h->buckets[a] = malloc(sizeof(struct BucketNode *));
h->buckets[a]->key = key;
h->buckets[a]->value = value;
h->buckets[a]->next = NULL;

return 0;
} else {
// Handle chaining
// Handle linear probing
return -1;
}
}

void double_cap(struct Hashmap *h) {
// TODO: rehash all the old elements
// They will be in the wrong spot after this
h->buckets = realloc(h->buckets, h->cap * 2 * sizeof(struct BucketNode *));

h->size = 0;
Expand All @@ -100,9 +116,9 @@ int test_hash_init_and_store() {
tassert(h->size == 0);
tassert(h->cap == 100);

char name[100] = "jake";
char name[5] = "jake";

char key[10] = "test";
char key[5] = "test";
int ret = hm_set(h, key, name);
tassert(ret != -1);

Expand Down
6 changes: 3 additions & 3 deletions src/util/hashmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ struct Hashmap {
struct Hashmap *create_hashmap(int capacity);
void destroy_hashmap(struct Hashmap *h);

struct BucketNode *create_bucket(void *key, void *value);
struct BucketNode *create_bucket(char *key, void *value);

// Get a value with a key
struct BucketNode *hm_get(struct Hashmap *h, void *key);
struct BucketNode *hm_get(struct Hashmap *h, char *key);
// Set a value with a key
int hm_set(struct Hashmap *h, void *key, void *value);
int hm_set(struct Hashmap *h, char *key, void *value);
// Double the capacity of the hashmap (happens automatically when size >
// capacity)
void double_cap(struct Hashmap *h);
Expand Down

0 comments on commit 3a45451

Please sign in to comment.