#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "XpmI.h"
LFUNC(AtomMake, xpmHashAtom, (char *name, void *data));
LFUNC(HashTableGrows, int, (xpmHashTable * table));
static xpmHashAtom
AtomMake(name, data)
char *name;
void *data;
{
xpmHashAtom object = (xpmHashAtom) XpmMalloc(sizeof(struct _xpmHashAtom));
if (object) {
object->name = name;
object->data = data;
}
return object;
}
#define HASH_FUNCTION hash = (hash << 5) - hash + *hp++;
#define INITIAL_HASH_SIZE 256
#define HASH_TABLE_GROWS size = size * 2;
#ifdef notdef
#define HASH_FUNCTION hash <<= 4; hash += *hp++; \
if(hash2 = hash & 0xf0000000) hash ^= (hash2 >> 24) ^ hash2;
#define INITIAL_HASH_SIZE 4095
#define HASH_TABLE_GROWS size = size << 1 + 1;
#endif
xpmHashAtom *
xpmHashSlot(table, s)
xpmHashTable *table;
char *s;
{
xpmHashAtom *atomTable = table->atomTable;
unsigned int hash;
xpmHashAtom *p;
char *hp = s;
char *ns;
hash = 0;
while (*hp) {
HASH_FUNCTION
}
p = atomTable + hash % table->size;
while (*p) {
ns = (*p)->name;
if (ns[0] == s[0] && strcmp(ns, s) == 0)
break;
p--;
if (p < atomTable)
p = atomTable + table->size - 1;
}
return p;
}
static int
HashTableGrows(table)
xpmHashTable *table;
{
xpmHashAtom *atomTable = table->atomTable;
unsigned int size = table->size;
xpmHashAtom *t, *p;
int i;
unsigned int oldSize = size;
t = atomTable;
HASH_TABLE_GROWS
table->size = size;
table->limit = size / 3;
if (size >= UINT_MAX / sizeof(*atomTable))
return (XpmNoMemory);
atomTable = (xpmHashAtom *) XpmMalloc(size * sizeof(*atomTable));
if (!atomTable)
return (XpmNoMemory);
table->atomTable = atomTable;
for (p = atomTable + size; p > atomTable;)
*--p = NULL;
for (i = 0, p = t; i < oldSize; i++, p++)
if (*p) {
xpmHashAtom *ps = xpmHashSlot(table, (*p)->name);
*ps = *p;
}
XpmFree(t);
return (XpmSuccess);
}
int
xpmHashIntern(table, tag, data)
xpmHashTable *table;
char *tag;
void *data;
{
xpmHashAtom *slot;
if (!*(slot = xpmHashSlot(table, tag))) {
if (!(*slot = AtomMake(tag, data)))
return (XpmNoMemory);
if (table->used >= table->limit) {
int ErrorStatus;
if ((ErrorStatus = HashTableGrows(table)) != XpmSuccess)
return (ErrorStatus);
table->used++;
return (XpmSuccess);
}
table->used++;
}
return (XpmSuccess);
}
int
xpmHashTableInit(table)
xpmHashTable *table;
{
xpmHashAtom *p;
xpmHashAtom *atomTable;
table->size = INITIAL_HASH_SIZE;
table->limit = table->size / 3;
table->used = 0;
table->atomTable = NULL;
if (table->size >= UINT_MAX / sizeof(*atomTable))
return (XpmNoMemory);
atomTable = (xpmHashAtom *) XpmMalloc(table->size * sizeof(*atomTable));
if (!atomTable)
return (XpmNoMemory);
for (p = atomTable + table->size; p > atomTable;)
*--p = NULL;
table->atomTable = atomTable;
return (XpmSuccess);
}
void
xpmHashTableFree(table)
xpmHashTable *table;
{
xpmHashAtom *p;
xpmHashAtom *atomTable = table->atomTable;
if (!atomTable)
return;
for (p = atomTable + table->size; p > atomTable;)
if (*--p)
XpmFree(*p);
XpmFree(atomTable);
table->atomTable = NULL;
}