Code:
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
typedef struct H HashTable;
HashTable * createHashTable(unsigned int capacity);
void addItem(HashTable * table, int item, int value);
int containsItem(HashTable * table, int item);
void destroyHashTable(HashTable * table);
struct Node;
typedef struct Node Link;
struct Node {
int item;
int value;
unsigned int next;
};
struct H {
unsigned int bytes;
unsigned int capacity;
unsigned int * data;
};
/*
* Allocates a new node to hold the given initial values, and
* returns a pointer to that node. Returns NULL if the node
* could not be allocated.
*/
unsigned int newNode(int item, int value, unsigned int next, HashTable * table) {
void * tmp_pointer = realloc(table, table->bytes + sizeof(struct Node));
if (tmp_pointer == NULL) {
printf("Realloc failed, out of Contiguous memory, cannot continue\n");
free(table);
return NULL;
} else {
table = tmp_pointer;
}
long unsigned int rel_address = table->bytes;
Link * result = (void *)table + rel_address; //calloc(1, sizeof(struct Node));
table->bytes = rel_address + sizeof(struct Node);
result->item = item;
result->value = value;
result->next = next;
return rel_address;
}
/*
* Creates a hashtable with the given capacity and hash function.
* Returns a pointer to the newly created table, or NULL if the
* table could not be created.
*/
HashTable * createHashTable(unsigned int capacity) {
HashTable * table = malloc(sizeof(struct H));
if (table == NULL) {
return NULL;
}
/* Move Bytes along */
table->bytes = sizeof(struct H);
int empty_space = sizeof(unsigned int) * capacity;
void * tmp_pointer = realloc(table, table->bytes + empty_space);
if (tmp_pointer == NULL) {
printf("Realloc failed, out of Contiguous memory, cannot continue\n");
free(table);
return NULL;
} else {
table = tmp_pointer;
}
table->data = table->bytes;
bzero((unsigned int)table + (unsigned int)table->data, empty_space);
table->bytes = table->bytes + empty_space;
table->capacity = capacity;
return table;
}
/*
* Adds the given item to the table, unless the item is already in
* the table, in which case it does nothing.
*/
void addItem(HashTable * table, int item, int value) {
unsigned int * data = (unsigned int)table->data + (unsigned int)table;
/* Which bucket does the item hash to? */
int index = item % table->capacity;
/* Search the linked list - if already there, bail! */
long unsigned int rel_address = data[index];
Link * p = (void *)table + rel_address;
long unsigned int pnexta = rel_address;
while (pnexta != NULL) {
p = pnexta + (void *)table;
if (p->item == item) {
printf("Already in index\n");
return;
}
pnexta = p->next;
}
/* Didn't find it in the list - add it! */
data[index] = newNode(item, value, data[index], table);
}
/*
* Returns 1 (true) if item is in table, otherwise returns 0 (false).
*/
int containsItem(HashTable * table, int item) {
/* Which bucket does the item hash to? */
unsigned int index = item % table->capacity;
unsigned int * data = (unsigned int)table->data + (unsigned int)table;
int rel_address = data[index];
int address = table;
Link * p = address + rel_address;
/* Search the linked list */
unsigned int pnexta = rel_address;
while (pnexta != NULL) {
p = pnexta + address;
if (p->item == item) {
return p->value;
}
pnexta = p->next;
}
/* Didn't find it in the list */
return 0;
}
/*
* Cleans up any memory allocated when we created the hashtable.
*/
void destroyHashTable(HashTable * table) {
free(table);
}
int main () {
HashTable * table = createHashTable(10);
addItem(table, 8493, 60);
addItem(table, 6876, 12);
FILE * stream = NULL;
if ((stream = fopen("./test", "wb+")) == NULL) {
printf("Could not open file for writing\n");
exit(1);
} else {
fwrite(table, table->bytes, 1, stream);
fclose(stream);
}
destroyHashTable(table);
/* Test reading it back */
stream = NULL;
if ((stream = fopen("./test", "rb+")) == NULL) {
printf("Could not open file for reading\n");
exit(1);
} else {
HashTable * new_table = malloc(sizeof(struct H));
fread(new_table, sizeof(struct H), 1, stream);
new_table = realloc(new_table, new_table->bytes);
fread((void *)new_table + sizeof(struct H), new_table->bytes - sizeof(struct H), 1, stream);
/*test search */
int value = 0;
if ((value = containsItem(new_table, 8493)) != NULL) {
printf("%d found\n", value);
} else {
printf("not found\n");
}
fclose(stream);
}
}