Skip to content
This repository was archived by the owner on Nov 16, 2022. It is now read-only.
84 changes: 84 additions & 0 deletions src/hash_functions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "hash_functions.h"
#include "memory.h"

size_t hash_map_default_hash_func(const void *key, size_t capacity, int len) {
return *((size_t *) key) % capacity;
}

size_t xPear16(const void *x_copy, size_t capacity, int len) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you grabbed this code, but I'd prefer it to conform to our naming conventions (lowercase, underscored).

int h, i, j;
unsigned char ch;
size_t hex;

// to store h values
struct {
int a;
} hh[8];

// 256 values 0-255 in any (random) order suffices
struct DAT {
int a;
}

T[256] = {
98, 6, 85, 150, 36, 23, 112, 164, 135, 207, 169, 5, 26, 64, 165, 219, // 1
61, 20, 68, 89, 130, 63, 52, 102, 24, 229, 132, 245, 80, 216, 195, 115, // 2
90, 168, 156, 203, 177, 120, 2, 190, 188, 7, 100, 185, 174, 243, 162, 10, // 3
237, 18, 253, 225, 8, 208, 172, 244, 255, 126, 101, 79, 145, 235, 228, 121, // 4
123, 251, 67, 250, 161, 0, 107, 97, 241, 111, 181, 82, 249, 33, 69, 55, // 5
59, 153, 29, 9, 213, 167, 84, 93, 30, 46, 94, 75, 151, 114, 73, 222, // 6
197, 96, 210, 45, 16, 227, 248, 202, 51, 152, 252, 125, 81, 206, 215, 186, // 7
39, 158, 178, 187, 131, 136, 1, 49, 50, 17, 141, 91, 47, 129, 60, 99, // 8
154, 35, 86, 171, 105, 34, 38, 200, 147, 58, 77, 118, 173, 246, 76, 254, // 9
133, 232, 196, 144, 198, 124, 53, 4, 108, 74, 223, 234, 134, 230, 157, 139, // 10
189, 205, 199, 128, 176, 19, 211, 236, 127, 192, 231, 70, 233, 88, 146, 44, // 11
183, 201, 22, 83, 13, 214, 116, 109, 159, 32, 95, 226, 140, 220, 57, 12, // 12
221, 31, 209, 182, 143, 92, 149, 184, 148, 62, 113, 65, 37, 27, 106, 166, // 13
3, 14, 204, 72, 21, 41, 56, 66, 28, 193, 40, 217, 25, 54, 179, 117, // 14
238, 87, 240, 155, 180, 170, 242, 212, 191, 163, 78, 218, 137, 194, 175, 110, // 15
43, 119, 224, 71, 122, 142, 42, 160, 104, 48, 247, 103, 15, 11, 138, 239 // 16
};

char *x = safe_malloc(len);
memcpy(x, x_copy, len);

int r;
ch = x[0]; // save first byte
for (j = 0 ; j < 8; j++) {
// standard Pearson hash (output is h)
h = 0;

for (i = 0; i < len; i++) {
r = abs(h ^ x[i]);
h = T[r].a;
}

hh[j].a = h; // store result
x[0] = x[0] + 1; // increment first data byte by 1
}

x[0] = ch; // restore first byte

safe_free(x);

// concatenate the 8 stored values of h
/*sprintf(hex,"%02X%02X%02X%02X%02X%02X%02X%02X",
hh[0].a, hh[1].a,
hh[2].a, hh[3].a,
hh[4].a, hh[5].a,
hh[6].a, hh[7].a);*/

// For now let me do it this way, but Liu doesn't think this is a good thing
for (int i = 0; i < 8; i++) {
hex = hex << 8;
hex = hex & hh[i].a;
}

return hex; // output 64-bit 16 hex bytes hash
}
27 changes: 27 additions & 0 deletions src/hash_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @file
* Implementation of different hash functions.
*/

#ifndef HASH_FUNCTIONS_H
#define HASH_FUNCTIONS_H

/**
* The default hash function. This is the function to be used if the user does not explicitly provide any hash function. It is a basic <EM> mod </EM> operator.
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
size_t hash_map_default_hash_func(const void *key, size_t capacity, int len);

/**
* The Pearson hash function. Both the explanation and code are derived from <A HREF="http://en.wikipedia.org/wiki/Pearson_hashing">Wikipedia</A>
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
size_t xPear16(const void *x, size_t capacity, int len);

#endif /*HASH_FUNCTIONS_H*/
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our current header files don't have the endif comment. I don't really see the need unless you have an exorbitant amount of endifs. Also, nobody does this for code! Which is where it'd be more useful. (Except CMake, which requires it... Oh my God...).

21 changes: 11 additions & 10 deletions src/hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>

#include "memory.h"
#include "linked_list.h"

#include "hash_map.h"
#include "hash_functions.h"

// when "-g" is used redefine inline to static or else the linker will try to link the function and fail (since it's inline)
#ifdef TEST
Expand All @@ -17,11 +19,7 @@ inline int hash_map_default_comparator(const void *l, const void *r) {
return *((unsigned long *) l) - *((unsigned long *) r);
}

inline size_t hash_map_default_hash_func(const void *key, size_t capacity) {
return *((size_t *) key) % capacity;
}

void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func) {
void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func, hash_map_key_size key_size) {
map->capacity = capacity;
map->size = 0;

Expand All @@ -40,6 +38,8 @@ void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparato
map->hash_func = hash_map_default_hash_func;
}

map->key_size = key_size;

map->keys = (linked_list *) safe_malloc(sizeof(linked_list));
// No free_data func here because keys will be free'd by linked_list_free for **table
linked_list_init(map->keys, NULL);
Expand All @@ -60,7 +60,7 @@ void hash_map_free(hash_map *map) {
}

void *hash_map_get(hash_map *map, void *key) {
linked_list *list = map->table[map->hash_func(key, map->capacity)];
linked_list *list = map->table[map->hash_func(key, map->capacity, map->key_size(key))];

if (!list) {
return NULL;
Expand All @@ -82,12 +82,13 @@ void *hash_map_get(hash_map *map, void *key) {
}

void hash_map_put(hash_map *map, void *key, void *value) {
linked_list *list = map->table[map->hash_func(key, map->capacity)];
linked_list *list = map->table[map->hash_func(key, map->capacity, map->key_size(key))];

if (!list) {
list = (linked_list *) safe_malloc(sizeof(linked_list));

linked_list_init(list, (linked_list_destructor) safe_free);
map->table[map->hash_func(key, map->capacity)] = list;
map->table[map->hash_func(key, map->capacity, map->key_size(key))] = list;
}

linked_list_node *head = linked_list_head(list);
Expand Down Expand Up @@ -118,7 +119,7 @@ void hash_map_put(hash_map *map, void *key, void *value) {
}

void hash_map_remove(hash_map *map, void *key) {
size_t offset = map->hash_func(key, map->capacity);
size_t offset = map->hash_func(key, map->capacity, map->key_size(key));
linked_list *list = map->table[offset];

if (!list) {
Expand Down Expand Up @@ -175,7 +176,7 @@ void hash_map_clear(hash_map *map) {
}

bool hash_map_contains_key(hash_map *map, void *key) {
linked_list *list = map->table[map->hash_func(key, map->capacity)];
linked_list *list = map->table[map->hash_func(key, map->capacity, map->key_size(key))];

if (!list) {
return false;
Expand Down
13 changes: 11 additions & 2 deletions src/hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ typedef int (*hash_map_comparator)(const void *l, const void *r);
* Hash function
* @param key key to hash
* @param capacity maximum size of the map
* @param len the size of the key passed as the first argument
* @return an offset within the range `[0, capacity)`
*/
typedef size_t (*hash_map_hash_func)(const void *key, size_t capacity);
typedef size_t (*hash_map_hash_func)(const void *key, size_t capacity, int len);

/**
* Size function to determine the size of each keys in the hash function
* @return the size of each key`
*/
typedef size_t (*hash_map_key_size)();

/**
* Hash map object
Expand All @@ -40,6 +47,8 @@ typedef struct {
hash_map_comparator comparator;
/** Key hash function */
hash_map_hash_func hash_func;
/** Key size function */
hash_map_key_size key_size;
/** Keys */
linked_list *keys;
} hash_map;
Expand All @@ -61,7 +70,7 @@ typedef struct {
* @param comparator key comparator function
* @param hash_func key hash function
*/
void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func);
void hash_map_init(hash_map *map, size_t capacity, hash_map_comparator comparator, hash_map_hash_func hash_func, hash_map_key_size);

/**
* Free the hash map.
Expand Down
1 change: 0 additions & 1 deletion src/memory.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "memory.h"

#include <stdio.h>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try not to include changes like this. I usually look at the diff before committing to make sure I don't have stuff like this.

#include <stdlib.h>

Expand Down
Loading