blob: 9646d3f77209a9a7f7f954ea2d5ea80e1c72a911 [file] [log] [blame]
// Not PJs code, but very useful and used everywhere */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vtr_util.h"
#include "vtr_memory.h"
#include "string_cache.h"
unsigned long
string_hash(STRING_CACHE * sc,
const char *string);
void
generate_sc_hash(STRING_CACHE * sc);
unsigned long
string_hash(STRING_CACHE * sc,
const char *string)
{
long a, i, mod, mul;
a = 0;
mod = sc->mod;
mul = sc->mul;
for(i = 0; string[i]; i++)
a = (a * mul + (unsigned char)string[i]) % mod;
return a;
}
void
generate_sc_hash(STRING_CACHE * sc)
{
long i;
long hash;
if(sc->string_hash != NULL)
vtr::free(sc->string_hash);
if(sc->next_string != NULL)
vtr::free(sc->next_string);
sc->string_hash_size = sc->size * 2 + 11;
sc->string_hash = (long *)sc_do_alloc(sc->string_hash_size, sizeof(long));
sc->next_string = (long *)sc_do_alloc(sc->size, sizeof(long));
memset(sc->string_hash, 0xff, sc->string_hash_size * sizeof(long));
memset(sc->next_string, 0xff, sc->size * sizeof(long));
for(i = 0; i < sc->free; i++)
{
hash = string_hash(sc, sc->string[i]) % sc->string_hash_size;
sc->next_string[i] = sc->string_hash[hash];
sc->string_hash[hash] = i;
}
}
STRING_CACHE *
sc_new_string_cache(void)
{
STRING_CACHE *sc;
sc = (STRING_CACHE *)sc_do_alloc(1, sizeof(STRING_CACHE));
sc->size = 100;
sc->string_hash_size = 0;
sc->string_hash = NULL;
sc->next_string = NULL;
sc->free = 0;
sc->string = (char **)sc_do_alloc(sc->size, sizeof(char *));
sc->data = (void **)sc_do_alloc(sc->size, sizeof(void *));
sc->mod = 834535547;
sc->mul = 247999;
generate_sc_hash(sc);
return sc;
}
long
sc_lookup_string(STRING_CACHE * sc,
const char *string)
{
long i, hash;
if(sc == NULL) {
return -1;
}
else {
hash = string_hash(sc, string) % sc->string_hash_size;
i = sc->string_hash[hash];
while(i >= 0)
{
if(!strcmp(sc->string[i], string))
return i;
i = sc->next_string[i];
}
return -1;
}
}
bool
sc_remove_string(STRING_CACHE * sc,
const char *string)
{
long i, hash;
if(sc != NULL) {
hash = string_hash(sc, string) % sc->string_hash_size;
i = sc->string_hash[hash];
while(i >= 0)
{
if(!strcmp(sc->string[i], string))
{
vtr::free(sc->string[i]);
if(sc->data[i] != NULL)
{
vtr::free(sc->data[i]);
sc->data = NULL;
}
sc->string[i] = vtr::strdup("REMOVED_NAME_FROM_SC_CACHE");
return true;
}
i = sc->next_string[i];
}
}
return false;
}
long
sc_add_string(STRING_CACHE * sc,
const char *string)
{
long i;
long hash;
void *a;
i = sc_lookup_string(sc, string);
if(i >= 0)
return i;
if(sc->free >= sc->size)
{
sc->size = sc->size * 2 + 10;
a = sc_do_alloc(sc->size, sizeof(char *));
if(sc->free > 0)
memcpy(a, sc->string, sc->free * sizeof(char *));
vtr::free(sc->string);
sc->string = (char **)a;
a = sc_do_alloc(sc->size, sizeof(void *));
if(sc->free > 0)
memcpy(a, sc->data, sc->free * sizeof(void *));
vtr::free(sc->data);
sc->data = (void **)a;
generate_sc_hash(sc);
}
i = sc->free;
sc->free++;
sc->string[i] = vtr::strdup(string);
sc->data[i] = NULL;
hash = string_hash(sc, string) % sc->string_hash_size;
sc->next_string[i] = sc->string_hash[hash];
sc->string_hash[hash] = i;
return i;
}
int
sc_valid_id(STRING_CACHE * sc,
long string_id)
{
if(string_id < 0)
return 0;
if(string_id >= sc->free)
return 0;
return 1;
}
void *
sc_do_alloc(long a,
long b)
{
void *r;
if(a < 1)
a = 1;
if(b < 1)
b = 1;
r = vtr::calloc(a, b);
while(r == NULL)
{
fprintf(stderr,
"Failed to allocated %ld chunks of %ld bytes (%ld bytes total)\n",
a, b, a * b);
r = vtr::calloc(a, b);
}
return r;
}
STRING_CACHE * sc_free_string_cache(STRING_CACHE * sc)
{
if(sc != NULL)
{
if (sc->string != NULL)
{
for(long i = 0; i < sc->free; i++)
{
if (sc->string[i] != NULL)
{
vtr::free(sc->string[i]);
}
sc->string[i] = NULL;
}
vtr::free(sc->string);
}
sc->string = NULL;
if(sc->data != NULL)
{
vtr::free(sc->data);
}
sc->data = NULL;
if(sc->string_hash != NULL)
{
vtr::free(sc->string_hash);
}
sc->string_hash = NULL;
if(sc->next_string != NULL)
{
vtr::free(sc->next_string);
}
sc->next_string = NULL;
vtr::free(sc);
}
sc = NULL;
return sc;
}
void sc_merge_string_cache(STRING_CACHE **source_ref, STRING_CACHE *destination)
{
STRING_CACHE *source = (*source_ref);
for(int source_spot = 0; source_spot < source->free; source_spot++)
{
long destination_spot = sc_add_string(destination, source->string[source_spot]);
destination->data[destination_spot] = source->data[source_spot];
source->data[source_spot] = NULL;
}
/* now cleanup */
sc_free_string_cache(source);
(*source_ref) = NULL;
}