OpenFPGA/vpr7_x2p/vpr/SRC/util/hash.c

201 lines
5.0 KiB
C
Raw Normal View History

2018-07-26 12:28:21 -05:00
#include <stdlib.h>
#include <string.h>
#include "hash.h"
#include "util.h"
struct s_hash **
alloc_hash_table(void) {
/* Creates a hash table with HASHSIZE different locations (hash values). */
struct s_hash **hash_table;
hash_table = (struct s_hash **) my_calloc(sizeof(struct s_hash *),
HASHSIZE);
return (hash_table);
}
void free_hash_table(struct s_hash **hash_table) {
/* Frees all the storage associated with a hash table. */
int i;
struct s_hash *h_ptr, *temp_ptr;
for (i = 0; i < HASHSIZE; i++) {
h_ptr = hash_table[i];
while (h_ptr != NULL) {
free(h_ptr->name);
temp_ptr = h_ptr->next;
free(h_ptr);
h_ptr = temp_ptr;
}
}
free(hash_table);
}
struct s_hash_iterator start_hash_table_iterator(void) {
/* Call this routine before you start going through all the elements in *
* a hash table. It sets the internal indices to the start of the table. */
struct s_hash_iterator hash_iterator;
hash_iterator.i = -1;
hash_iterator.h_ptr = NULL;
return (hash_iterator);
}
struct s_hash *
get_next_hash(struct s_hash **hash_table, struct s_hash_iterator *hash_iterator) {
/* Returns the next occupied hash entry, and moves the iterator structure *
* forward so the next call gets the next entry. */
int i;
struct s_hash *h_ptr;
i = hash_iterator->i;
h_ptr = hash_iterator->h_ptr;
while (h_ptr == NULL) {
i++;
if (i >= HASHSIZE)
return (NULL); /* End of table */
h_ptr = hash_table[i];
}
hash_iterator->h_ptr = h_ptr->next;
hash_iterator->i = i;
return (h_ptr);
}
struct s_hash *
insert_in_hash_table(struct s_hash **hash_table, char *name,
int next_free_index) {
/* Adds the string pointed to by name to the hash table, and returns the *
* hash structure created or updated. If name is already in the hash table *
* the count member of that hash element is incremented. Otherwise a new *
* hash entry with a count of zero and an index of next_free_index is *
* created. */
int i;
struct s_hash *h_ptr, *prev_ptr;
i = hash_value(name);
prev_ptr = NULL;
h_ptr = hash_table[i];
while (h_ptr != NULL) {
if (strcmp(h_ptr->name, name) == 0) {
h_ptr->count++;
return (h_ptr);
}
prev_ptr = h_ptr;
h_ptr = h_ptr->next;
}
/* Name string wasn't in the hash table. Add it. */
h_ptr = (struct s_hash *) my_malloc(sizeof(struct s_hash));
if (prev_ptr == NULL) {
hash_table[i] = h_ptr;
} else {
prev_ptr->next = h_ptr;
}
h_ptr->next = NULL;
h_ptr->index = next_free_index;
h_ptr->count = 1;
h_ptr->name = (char *) my_malloc((strlen(name) + 1) * sizeof(char));
strcpy(h_ptr->name, name);
return (h_ptr);
}
struct s_hash *
get_hash_entry(struct s_hash **hash_table, char *name) {
/* Returns the hash entry with this name, or NULL if there is no *
* corresponding entry. */
int i;
struct s_hash *h_ptr;
i = hash_value(name);
h_ptr = hash_table[i];
while (h_ptr != NULL) {
if (strcmp(h_ptr->name, name) == 0)
return (h_ptr);
h_ptr = h_ptr->next;
}
return (NULL);
}
int hash_value(char *name) {
/* Creates a hash key from a character string. The absolute value is taken *
* for the final val to compensate for long strlen that cause val to *
* overflow. */
int i;
int val = 0, mult = 1;
i = strlen(name);
for (i = strlen(name) - 1; i >= 0; i--) {
val += mult * ((int) name[i]);
mult *= 7;
}
val += (int) name[0];
val %= HASHSIZE;
val = abs(val);
return (val);
}
void get_hash_stats(struct s_hash **hash_table, char *hash_table_name){
/* Checks to see how well elements are distributed within the hash table. *
* Will traverse through the hash_table and count the length of the linked *
* list. Will output the hash number, the number of array elements that are *
* NULL, the average number of linked lists and the maximum length of linked *
* lists. */
int num_NULL = 0, total_elements = 0, max_num = 0, curr_num;
double avg_num = 0;
int i;
struct s_hash *h_ptr;
for (i = 0; i<HASHSIZE; i++){
h_ptr = hash_table[i];
curr_num = 0;
if (h_ptr == NULL)
num_NULL++;
else{
while (h_ptr != NULL){
curr_num ++;
h_ptr = h_ptr->next;
}
}
if (curr_num > max_num)
max_num = curr_num;
total_elements = total_elements + curr_num;
}
avg_num = (float) total_elements / ((float)HASHSIZE - (float)num_NULL);
vpr_printf(TIO_MESSAGE_INFO, "\n");
vpr_printf(TIO_MESSAGE_INFO, "The hash table '%s' is of size %d.\n",
hash_table_name, HASHSIZE);
vpr_printf(TIO_MESSAGE_INFO, "It has: %d keys that are never used; total of %d elements; an average linked-list length of %.1f; and a maximum linked-list length of %d.\n",
num_NULL, total_elements, avg_num, max_num);
vpr_printf(TIO_MESSAGE_INFO, "\n");
}