2008-10-12 20:53:28 -04:00
|
|
|
#include <string.h>
|
|
|
|
#include "picoc.h"
|
2009-01-23 06:34:12 -05:00
|
|
|
|
|
|
|
/* hash function */
|
2008-10-12 20:53:28 -04:00
|
|
|
static unsigned int TableHash(const Str *Key)
|
|
|
|
{
|
2009-01-23 06:34:12 -05:00
|
|
|
if (Key->Len == 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return ((*Key->Str << 24) | (Key->Str[Key->Len-1] << 16) | (Key->Str[Key->Len >> 1] << 8)) ^ Key->Len;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2009-01-23 06:34:12 -05:00
|
|
|
/* initialise a table */
|
2008-12-21 21:29:19 -05:00
|
|
|
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, int Size)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
Tbl->Size = Size;
|
|
|
|
Tbl->HashTable = HashTable;
|
|
|
|
memset(HashTable, '\0', sizeof(struct TableEntry) * Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int TableCheckEntry(struct Table *Tbl, const Str *Key, int HashPos)
|
|
|
|
{
|
|
|
|
struct TableEntry *Entry = &Tbl->HashTable[HashPos];
|
|
|
|
|
|
|
|
if (Entry->Key.Len == 0)
|
|
|
|
return -1; /* empty */
|
|
|
|
|
|
|
|
else if (StrEqual(&Entry->Key, Key))
|
|
|
|
return HashPos; /* found */
|
|
|
|
|
|
|
|
else
|
|
|
|
return -2; /* wrong key */
|
|
|
|
}
|
|
|
|
|
2009-01-23 06:34:12 -05:00
|
|
|
/* search a table for an identifier. sets AddAt to where to add it at if not found */
|
2008-10-12 20:53:28 -04:00
|
|
|
static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
|
|
|
|
{
|
|
|
|
int HashValue;
|
|
|
|
int HashPos;
|
|
|
|
int Result;
|
|
|
|
|
|
|
|
HashValue = TableHash(Key) % Tbl->Size;
|
|
|
|
|
|
|
|
for (HashPos = HashValue; HashPos < Tbl->Size; HashPos++)
|
|
|
|
{
|
|
|
|
*AddAt = HashPos;
|
|
|
|
if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2)
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (HashPos = 0; HashPos < HashValue; HashPos++)
|
|
|
|
{
|
|
|
|
*AddAt = HashPos;
|
|
|
|
if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2)
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not found and table is full */
|
|
|
|
*AddAt = -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-01-23 06:34:12 -05:00
|
|
|
/* set an identifier to a value. returns FALSE if it already exists */
|
2008-12-20 22:13:25 -05:00
|
|
|
int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
int HashPos;
|
|
|
|
int AddAt;
|
|
|
|
|
|
|
|
HashPos = TableSearch(Tbl, Key, &AddAt);
|
|
|
|
|
2008-12-20 22:13:25 -05:00
|
|
|
if (HashPos == -1)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
if (AddAt == -1)
|
2008-12-21 21:29:19 -05:00
|
|
|
Fail("variable table is full\n");
|
2008-10-12 20:53:28 -04:00
|
|
|
|
|
|
|
else
|
|
|
|
{ /* add it to the table */
|
|
|
|
struct TableEntry *Entry = &Tbl->HashTable[AddAt];
|
|
|
|
Entry->Key = *Key;
|
2009-01-21 04:02:05 -05:00
|
|
|
Entry->Val = Val;
|
2009-01-23 06:34:12 -05:00
|
|
|
return TRUE;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
}
|
2009-01-23 06:34:12 -05:00
|
|
|
else
|
|
|
|
return FALSE;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2009-01-23 06:34:12 -05:00
|
|
|
/* find a value in a table. returns FALSE if not found */
|
2008-12-18 19:22:52 -05:00
|
|
|
int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
|
|
|
int HashPos;
|
|
|
|
int AddAt;
|
|
|
|
|
|
|
|
HashPos = TableSearch(Tbl, Key, &AddAt);
|
|
|
|
|
|
|
|
if (HashPos == -1)
|
2008-12-18 19:22:52 -05:00
|
|
|
return FALSE;
|
|
|
|
|
2009-01-21 04:02:05 -05:00
|
|
|
*Val = Tbl->HashTable[HashPos].Val;
|
2008-12-18 19:22:52 -05:00
|
|
|
return TRUE;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|