Files

220 lines
4.7 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include <cstdlib>
#include <memory.h>
#include <cstring>
#include "globalincs/pstypes.h"
#include "localization/fhash.h"
// -----------------------------------------------------------------------------------------------
// HASH DEFINES/VARS
//
// hash node
typedef struct fhash_node {
char *str; // allocated dynamically
int id; // can be -1
fhash_node *next, *prev; // for chaining in an individual hash table entry (non-circular, doubly linked list)
} fhash_node;
// hash table itself (with chained nodes)
#define HASH_TABLE_SIZE 253 // works better when not a power of 2, and is prime
fhash_node *Hash_table_fred[HASH_TABLE_SIZE];
// if the hash table is active
int Fhash_active = 0;
// -----------------------------------------------------------------------------------------------
// HASH FORWARD DECLARATIONS
//
// hash a string. return an index into the hash table where it should be inserted
int fhash_get_hash_index(const char *str);
// insert a string into hash table index N, will take care of allocating/chaining everything
void fhash_insert(const char *str, int id, int n);
// -----------------------------------------------------------------------------------------------
// HASH FUNCTIONS
//
// initialize the hash table
void fhash_init()
{
memset(Hash_table_fred, 0, sizeof(fhash_node *) * HASH_TABLE_SIZE);
}
// set the hash table to be active for parsing
void fhash_activate()
{
Fhash_active = 1;
}
// set the hash table to be inactive for parsing
void fhash_deactivate()
{
Fhash_active = 0;
}
// if the hash table is active
int fhash_active()
{
return Fhash_active;
}
// flush out the hash table, freeing up everything
void fhash_flush()
{
int idx;
fhash_node *moveup, *backup;
// go through each element
for(idx=0; idx<HASH_TABLE_SIZE; idx++){
if(Hash_table_fred[idx] != NULL){
moveup = Hash_table_fred[idx];
while(moveup != NULL){
// next element
backup = moveup;
moveup = moveup->next;
// free up this element
if(backup->str != NULL){
vm_free(backup->str);
}
vm_free(backup);
}
// null this element
Hash_table_fred[idx] = NULL;
}
}
}
// add a string with the given id# to the hash table
void fhash_add_str(const char *str, int id)
{
int hash_index;
// if the hash table isn't active, don't bother
Assert(Fhash_active);
if(!Fhash_active){
return;
}
// determine where the string goes in the hash table
Assert(str != NULL);
if(str == NULL){
return;
}
hash_index = fhash_get_hash_index(str);
// insert into the hash table
fhash_insert(str, id, hash_index);
}
// determine if the passed string exists in the table
// returns : -2 if the string doesn't exit, or >= -1 as the string id # otherwise
int fhash_string_exists(const char *str)
{
int hash_index;
fhash_node *moveup;
Assert(str != NULL);
if(str == NULL){
return -2;
}
// get the hash index for this string
hash_index = fhash_get_hash_index(str);
// if there are no entries, it doesn't exist
if(Hash_table_fred[hash_index] == NULL){
return -2;
}
// otherwise compare against all strings in this code
moveup = Hash_table_fred[hash_index];
while(moveup != NULL){
// do a string compare on this item
Assert(moveup->str != NULL);
if(moveup->str != NULL){
if(!strcmp(moveup->str, str)){
return moveup->id;
}
}
// next item
moveup = moveup->next;
}
// didn't find it
return -2;
}
// -----------------------------------------------------------------------------------------------
// HASH FORWARD DEFINITIONS
//
// hash a string. return an index into the hash table where it should be inserted
int fhash_get_hash_index(const char *str)
{
int accum = 0;
size_t idx, str_len;
int ret;
// add up the string
str_len = strlen(str);
for(idx=0; idx<str_len; idx++){
accum += str[idx];
}
ret = abs(accum) % 253;
return ret;
}
// insert a string into hash table index N, will take care of allocating/chaining everything
void fhash_insert(const char *str, int id, int n)
{
fhash_node *new_node;
fhash_node *moveup;
// allocate the new node
new_node = (fhash_node*)vm_malloc(sizeof(fhash_node));
Assert(new_node);
if(new_node == NULL){
return;
}
// fill in the node
new_node->str = vm_strdup(str);
new_node->id = id;
new_node->next = NULL;
new_node->prev = NULL;
// if this hash index is NULL, just assign it
if(Hash_table_fred[n] == NULL){
Hash_table_fred[n] = new_node;
} else {
moveup = Hash_table_fred[n];
while(moveup->next != NULL){
moveup = moveup->next;
}
new_node->prev = moveup;
moveup->next = new_node;
}
}