2008-10-12 20:53:28 -04:00
|
|
|
#include <string.h>
|
|
|
|
#include "picoc.h"
|
2009-01-23 06:34:12 -05:00
|
|
|
|
2009-01-29 17:26:04 -05:00
|
|
|
/* quick hash function */
|
2009-02-01 06:31:18 -05:00
|
|
|
static unsigned int TableHash(const char *Key, int KeyLen)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
2009-02-01 06:31:18 -05:00
|
|
|
if (KeyLen == 0)
|
2009-01-23 06:34:12 -05:00
|
|
|
return 0;
|
|
|
|
else
|
2009-02-01 06:31:18 -05:00
|
|
|
return ((*Key << 24) | (Key[KeyLen-1] << 16) | (Key[KeyLen >> 1] << 8)) ^ KeyLen;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2009-01-23 06:34:12 -05:00
|
|
|
/* initialise a table */
|
2009-01-29 17:26:04 -05:00
|
|
|
void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
Tbl->Size = Size;
|
2009-01-29 17:26:04 -05:00
|
|
|
Tbl->OnHeap = OnHeap;
|
2008-10-12 20:53:28 -04:00
|
|
|
Tbl->HashTable = HashTable;
|
2009-01-29 17:26:04 -05:00
|
|
|
memset(HashTable, '\0', sizeof(struct TableEntry *) * Size);
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2009-01-29 17:26:04 -05:00
|
|
|
/* check a hash table entry for a key */
|
2009-02-01 22:25:15 -05:00
|
|
|
static int TableSearch(struct Table *Tbl, const char *Key, int *AddAt)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
2009-01-29 17:26:04 -05:00
|
|
|
struct TableEntry *Entry;
|
2009-02-01 22:25:15 -05:00
|
|
|
int HashValue = ((unsigned long)Key) % Tbl->Size;
|
2008-10-12 20:53:28 -04:00
|
|
|
|
2009-01-29 17:26:04 -05:00
|
|
|
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
2009-02-01 22:25:15 -05:00
|
|
|
if (Entry->p.v.Key == Key)
|
2009-01-29 17:26:04 -05:00
|
|
|
return HashValue; /* found */
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2009-01-29 17:26:04 -05:00
|
|
|
*AddAt = HashValue; /* didn't find it in the chain */
|
2008-10-12 20:53:28 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-02-01 22:25:15 -05:00
|
|
|
/* set an identifier to a value. returns FALSE if it already exists.
|
|
|
|
* Key must be a shared string from StrRegister() */
|
2009-02-01 06:31:18 -05:00
|
|
|
int TableSet(struct Table *Tbl, const char *Key, struct Value *Val)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
int AddAt;
|
2009-02-01 22:25:15 -05:00
|
|
|
int HashPos = TableSearch(Tbl, Key, &AddAt);
|
2008-10-12 20:53:28 -04:00
|
|
|
|
2008-12-20 22:13:25 -05:00
|
|
|
if (HashPos == -1)
|
2009-01-29 17:26:04 -05:00
|
|
|
{ /* add it to the table */
|
|
|
|
struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap);
|
2009-02-01 22:25:15 -05:00
|
|
|
NewEntry->p.v.Key = Key;
|
|
|
|
NewEntry->p.v.Val = Val;
|
2009-01-29 17:26:04 -05:00
|
|
|
NewEntry->Next = Tbl->HashTable[AddAt];
|
|
|
|
Tbl->HashTable[AddAt] = NewEntry;
|
|
|
|
return TRUE;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
2009-01-26 03:57:32 -05:00
|
|
|
|
|
|
|
return FALSE;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2009-02-01 22:25:15 -05:00
|
|
|
/* find a value in a table. returns FALSE if not found.
|
|
|
|
* Key must be a shared string from StrRegister() */
|
2009-02-01 06:31:18 -05:00
|
|
|
int TableGet(struct Table *Tbl, const char *Key, struct Value **Val)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
int AddAt;
|
2009-02-01 22:25:15 -05:00
|
|
|
int HashPos = TableSearch(Tbl, Key, &AddAt);
|
2008-10-12 20:53:28 -04:00
|
|
|
if (HashPos == -1)
|
2008-12-18 19:22:52 -05:00
|
|
|
return FALSE;
|
|
|
|
|
2009-02-01 22:25:15 -05:00
|
|
|
*Val = Tbl->HashTable[HashPos]->p.v.Val;
|
2008-12-18 19:22:52 -05:00
|
|
|
return TRUE;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
2009-02-01 06:31:18 -05:00
|
|
|
|
2009-02-01 22:25:15 -05:00
|
|
|
/* check a hash table entry for an identifier */
|
|
|
|
static int TableSearchIdentifier(struct Table *Tbl, const char *Key, int Len, int *AddAt)
|
|
|
|
{
|
|
|
|
struct TableEntry *Entry;
|
|
|
|
int HashValue = TableHash(Key, Len) % Tbl->Size;
|
|
|
|
|
|
|
|
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
|
|
|
|
{
|
2009-02-02 17:33:51 -05:00
|
|
|
if (strncmp(&Entry->p.Key[0], Key, Len) == 0 && Entry->p.Key[Len] == '\0')
|
2009-02-01 22:25:15 -05:00
|
|
|
return HashValue; /* found */
|
|
|
|
}
|
|
|
|
|
|
|
|
*AddAt = HashValue; /* didn't find it in the chain */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
/* set an identifier and return the identifier. share if possible */
|
2009-02-01 22:25:15 -05:00
|
|
|
const char *TableSetIdentifier(struct Table *Tbl, const char *Ident, int IdentLen)
|
2009-02-01 06:31:18 -05:00
|
|
|
{
|
|
|
|
int AddAt;
|
2009-02-01 22:25:15 -05:00
|
|
|
int HashPos = TableSearchIdentifier(Tbl, Ident, IdentLen, &AddAt);
|
2009-02-01 06:31:18 -05:00
|
|
|
|
|
|
|
if (HashPos != -1)
|
2009-02-02 17:33:51 -05:00
|
|
|
return &Tbl->HashTable[HashPos]->p.Key[0];
|
2009-02-01 06:31:18 -05:00
|
|
|
else
|
2009-02-01 22:25:15 -05:00
|
|
|
{ /* add it to the table - we economise by not allocating the whole structure here */
|
|
|
|
struct TableEntry *NewEntry = HeapAlloc(sizeof(struct TableEntry *) + IdentLen + 1);
|
2009-02-02 17:33:51 -05:00
|
|
|
strncpy((char *)&NewEntry->p.Key[0], Ident, IdentLen);
|
2009-02-01 06:31:18 -05:00
|
|
|
NewEntry->Next = Tbl->HashTable[AddAt];
|
|
|
|
Tbl->HashTable[AddAt] = NewEntry;
|
2009-02-02 17:33:51 -05:00
|
|
|
return &NewEntry->p.Key[0];
|
2009-02-01 06:31:18 -05:00
|
|
|
}
|
|
|
|
}
|