diff --git a/hash.c b/hash.c index 0b5db47..da112fd 100644 --- a/hash.c +++ b/hash.c @@ -41,10 +41,13 @@ #include #include "gap.h" + +typedef void* hash_item; #include "hash.h" static const int h_keylen = 5; /* How many bits in the hash key? (hash is 2^h_keylen big) */ static const int hash_size = (1 << h_keylen); /* 8 => 256 */ +static const int keymask = hash_size - 1; /* 8 => 11111111 */ static void* const FREE = NULL; struct hash { @@ -59,6 +62,12 @@ struct hash { typedef struct hash hash; +static int hash_make_key(hash* h, hash_item item) +{ + return h->hash_make_key(item) & keymask; +} + + hash* hash_init(hash_make_key_fn make_key, hash_cmp_item_fn cmp_item) { hash* h = malloc(sizeof(*h)); @@ -83,10 +92,10 @@ static int hash_next_index(hash* h, int i) * item is an item object that must return the target wanted index and for * which comparison with the searched object will succeed. * */ -int hash_find_index(hash* h, hash_item item) +static int hash_find_index(hash* h, hash_item item) { hash_item cnx; - int index = h->hash_make_key(item); + int index = hash_make_key(h, item); int cnt = 0; if (index < h->floor) index = h->floor; @@ -111,6 +120,14 @@ int hash_find_index(hash* h, hash_item item) return index; } +hash_item hash_find(hash* h, hash_item item) +{ + int index = hash_find_index(h, item); + if (index == -1) return NULL; + hash_item out = gap_get(h->data, index); + return out; +} + /* says if we should swap the bubble (element that's going up) and the current * indexed element. * index: current insertion index @@ -141,7 +158,7 @@ static int i_should_swap(int index, int wanted_index, int bubble_index, int floo int hash_insert(hash* h, hash_item new) { - int bubble_wanted_index = h->hash_make_key(new); + int bubble_wanted_index = hash_make_key(h, new); int index = bubble_wanted_index; gap_array* hash = h->data; @@ -163,7 +180,7 @@ int hash_insert(hash* h, hash_item new) return 0; } - int curr_wanted_index = h->hash_make_key(curr_item); + int curr_wanted_index = hash_make_key(h, curr_item); if (i_should_swap(index, curr_wanted_index, bubble_wanted_index, orig_floor, wrapped)) { gap_set(h->data, index, new); @@ -184,13 +201,10 @@ int hash_insert(hash* h, hash_item new) return 0; } - - - static int next_in_right_place(hash* h, hash_item item, int index) { if (!item) return 0; - int wanted_index = h->hash_make_key(item); + int wanted_index = hash_make_key(h, item); return (wanted_index == index); } @@ -224,7 +238,7 @@ int hash_remove(hash* h, hash_item item) return 0; } - +#if HASH_TESTING #include #include #define STR_LENGTH 16 @@ -249,11 +263,12 @@ void hash_dump(hash* h, char* filename) memset(str, 0, STR_LENGTH); if (item) { - idx = h->hash_make_key(item); - memcpy(str, item->str, STR_LENGTH); + idx = hash_make_key(h, item); + memcpy(str, ((struct hash_item*)item)->str, STR_LENGTH); } fprintf(out, "\t%d:%d:%s\n", i, idx, str); } fprintf(out, "\n"); fclose(out); } +#endif diff --git a/hash.h b/hash.h index 49a747b..e774186 100644 --- a/hash.h +++ b/hash.h @@ -1,16 +1,28 @@ +#ifndef HASH_H +#define HASH_H +/* You will need to typedef a pointer type to hash_item before including this + * .h */ typedef struct hash hash; -typedef struct hash_item* hash_item; + +/* Function that returns a key (index) for a given item. The key must be always + * the same for an item. It doesn't need to be bounded (hash.c masks it for you) */ typedef int (*hash_make_key_fn)(hash_item item); /* Function that compares two items: returns 0 if they are the same */ typedef int (*hash_cmp_item_fn)(hash_item item1, hash_item item2); hash* hash_init(hash_make_key_fn make_key, hash_cmp_item_fn cmp_item); -int hash_find_index(hash* h, hash_item item); + int hash_insert(hash* h, hash_item new); int hash_remove(hash* h, hash_item item); +/* Returns the hash item that matches specification (meaning the + * comparison function returns true for cmp(x, item), or NULL if not found */ +hash_item hash_find(hash* h, hash_item item); + void hash_dump(hash* h, char* filename); /* For development only */ + +#endif diff --git a/hashtest/Makefile b/hashtest/Makefile index 49e961e..776b159 100644 --- a/hashtest/Makefile +++ b/hashtest/Makefile @@ -1,4 +1,5 @@ +CFLAGS=-DHASH_TESTING OBJ=../hash.o ../gap.o htest.o htest: $(OBJ) diff --git a/hashtest/htest.c b/hashtest/htest.c index a61da13..2c5e688 100644 --- a/hashtest/htest.c +++ b/hashtest/htest.c @@ -18,7 +18,6 @@ #include #include -#include "../hash.h" #define STR_LENGTH 16 @@ -27,6 +26,9 @@ struct hash_item { char str[STR_LENGTH]; }; +typedef struct hash_item* hash_item; + +#include "../hash.h" @@ -92,8 +94,8 @@ int main(int argc, char* argv[]) case 's': /* search */ fprintf(stderr, "searching\n"); - int i = hash_find_index(h, item); - fprintf(stderr, "searching %d[%s]: %d\n", item->wanted_index, item->str, i); + struct hash_item* found = hash_find(h, item); + fprintf(stderr, "searching %d[%s]: %p\n", item->wanted_index, item->str, found); break; case 'q': /* quit */