| /* | |
| ** C implementation of a hash table ADT | |
| */ | |
| typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode; | |
| typedef struct tagEntry | |
| { | |
| char* key; | |
| char* value; | |
| } Entry; | |
| typedef struct tagNode | |
| { | |
| Entry* entry; | |
| struct tagNode* next; | |
| } Node; | |
| typedef struct tagHash | |
| { | |
| unsigned int table_size; | |
| Node** heads; | |
| } Hash; | |
| static unsigned int hash_func(const char* str, unsigned int table_size) | |
| { | |
| unsigned int hash_value; | |
| unsigned int a = 127; | |
| for (hash_value = 0; *str != 0; ++str) | |
| hash_value = (a*hash_value + *str) % table_size; | |
| return hash_value; | |
| } | |
| ReturnCode HashCreate(Hash** hash, unsigned int table_size) | |
| { | |
| unsigned int i; | |
| if (table_size < 1) | |
| return FAIL; | |
| // | |
| // Allocate space for the Hash | |
| // | |
| if (((*hash) = malloc(sizeof(**hash))) == NULL) | |
| return FAIL; | |
| // | |
| // Allocate space for the array of list heads | |
| // | |
| if (((*hash)->heads = malloc(table_size*sizeof(*((*hash)->heads)))) == NULL) | |
| return FAIL; | |
| // | |
| // Initialize Hash info | |
| // | |
| for (i = 0; i < table_size; ++i) | |
| { | |
| (*hash)->heads[i] = NULL; | |
| } | |
| (*hash)->table_size = table_size; | |
| return SUCCESS; | |
| } | |
| ReturnCode HashInsert(Hash* hash, const Entry* entry) | |
| { | |
| unsigned int index = hash_func(entry->key, hash->table_size); | |
| Node* temp = hash->heads[index]; | |
| HashRemove(hash, entry->key); | |
| if ((hash->heads[index] = malloc(sizeof(Node))) == NULL) | |
| return FAIL; | |
| hash->heads[index]->entry = malloc(sizeof(Entry)); | |
| hash->heads[index]->entry->key = malloc(strlen(entry->key)+1); | |
| hash->heads[index]->entry->value = malloc(strlen(entry->value)+1); | |
| strcpy(hash->heads[index]->entry->key, entry->key); | |
| strcpy(hash->heads[index]->entry->value, entry->value); | |
| hash->heads[index]->next = temp; | |
| return SUCCESS; | |
| } | |
| const Entry* HashFind(const Hash* hash, const char* key) | |
| { | |
| unsigned int index = hash_func(key, hash->table_size); | |
| Node* temp = hash->heads[index]; | |
| while (temp != NULL) | |
| { | |
| if (!strcmp(key, temp->entry->key)) | |
| return temp->entry; | |
| temp = temp->next; | |
| } | |
| return NULL; | |
| } | |
| ReturnCode HashRemove(Hash* hash, const char* key) | |
| { | |
| unsigned int index = hash_func(key, hash->table_size); | |
| Node* temp1 = hash->heads[index]; | |
| Node* temp2 = temp1; | |
| while (temp1 != NULL) | |
| { | |
| if (!strcmp(key, temp1->entry->key)) | |
| { | |
| if (temp1 == hash->heads[index]) | |
| hash->heads[index] = hash->heads[index]->next; | |
| else | |
| temp2->next = temp1->next; | |
| free(temp1->entry->key); | |
| free(temp1->entry->value); | |
| free(temp1->entry); | |
| free(temp1); | |
| temp1 = NULL; | |
| return SUCCESS; | |
| } | |
| temp2 = temp1; | |
| temp1 = temp1->next; | |
| } | |
| return FAIL; | |
| } | |
| void HashPrint(Hash* hash, void (*PrintFunc)(char*, char*)) | |
| { | |
| unsigned int i; | |
| if (hash == NULL || hash->heads == NULL) | |
| return; | |
| for (i = 0; i < hash->table_size; ++i) | |
| { | |
| Node* temp = hash->heads[i]; | |
| while (temp != NULL) | |
| { | |
| PrintFunc(temp->entry->key, temp->entry->value); | |
| temp = temp->next; | |
| } | |
| } | |
| } | |
| void HashDestroy(Hash* hash) | |
| { | |
| unsigned int i; | |
| if (hash == NULL) | |
| return; | |
| for (i = 0; i < hash->table_size; ++i) | |
| { | |
| Node* temp = hash->heads[i]; | |
| while (temp != NULL) | |
| { | |
| Node* temp2 = temp; | |
| free(temp->entry->key); | |
| free(temp->entry->value); | |
| free(temp->entry); | |
| temp = temp->next; | |
| free(temp2); | |
| } | |
| } | |
| free(hash->heads); | |
| hash->heads = NULL; | |
| free(hash); | |
| } | |