#include "ficl.h"
#define FICL_ASSERT_PHASH(hash, expression) FICL_ASSERT(NULL, expression)
void
ficlHashForget(ficlHash *hash, void *where)
{
ficlWord *pWord;
unsigned i;
FICL_ASSERT_PHASH(hash, hash);
FICL_ASSERT_PHASH(hash, where);
for (i = 0; i < hash->size; i++) {
pWord = hash->table[i];
while ((void *)pWord >= where) {
pWord = pWord->link;
}
hash->table[i] = pWord;
}
}
ficlUnsigned16
ficlHashCode(ficlString s)
{
ficlUnsigned8 *trace;
ficlUnsigned16 code = (ficlUnsigned16)s.length;
ficlUnsigned16 shift = 0;
if (s.length == 0)
return (0);
for (trace = (ficlUnsigned8 *)s.text;
s.length && *trace; trace++, s.length--) {
code = (ficlUnsigned16)((code << 4) + tolower(*trace));
shift = (ficlUnsigned16)(code & 0xf000);
if (shift) {
code ^= (ficlUnsigned16)(shift >> 8);
code ^= (ficlUnsigned16)shift;
}
}
return ((ficlUnsigned16)code);
}
void
ficlHashInsertWord(ficlHash *hash, ficlWord *word)
{
ficlWord **pList;
FICL_ASSERT_PHASH(hash, hash);
FICL_ASSERT_PHASH(hash, word);
if (hash->size == 1) {
pList = hash->table;
} else {
pList = hash->table + (word->hash % hash->size);
}
word->link = *pList;
*pList = word;
}
ficlWord *
ficlHashLookup(ficlHash *hash, ficlString name, ficlUnsigned16 hashCode)
{
ficlUnsigned nCmp = name.length;
ficlWord *word;
ficlUnsigned16 hashIdx;
if (nCmp > FICL_NAME_LENGTH)
nCmp = FICL_NAME_LENGTH;
for (; hash != NULL; hash = hash->link) {
if (hash->size > 1)
hashIdx = (ficlUnsigned16)(hashCode % hash->size);
else
hashIdx = 0;
for (word = hash->table[hashIdx]; word; word = word->link) {
if ((word->length == name.length) &&
(!ficlStrincmp(name.text, word->name, nCmp)))
return (word);
#if FICL_ROBUST
FICL_ASSERT_PHASH(hash, word != word->link);
#endif
}
}
return (NULL);
}
void
ficlHashReset(ficlHash *hash)
{
unsigned i;
FICL_ASSERT_PHASH(hash, hash);
for (i = 0; i < hash->size; i++) {
hash->table[i] = NULL;
}
hash->link = NULL;
hash->name = NULL;
}