Use the hashtab to implement the string pool hash table.
git-svn-id: svn://svn.cc65.org/cc65/trunk@5239 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -47,12 +47,33 @@
|
|||||||
/* common */
|
/* common */
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
#include "hashfunc.h"
|
#include "hashfunc.h"
|
||||||
|
#include "hashtab.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "strpool.h"
|
#include "strpool.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Forwards */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned HT_GenHash (const void* Key);
|
||||||
|
/* Generate the hash over a key. */
|
||||||
|
|
||||||
|
static const void* HT_GetKey (const void* Entry);
|
||||||
|
/* Given a pointer to the user entry data, return a pointer to the key */
|
||||||
|
|
||||||
|
static int HT_Compare (const void* Key1, const void* Key2);
|
||||||
|
/* Compare two keys. The function must return a value less than zero if
|
||||||
|
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||||
|
* than zero if Key1 is greater then Key2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -61,12 +82,25 @@
|
|||||||
|
|
||||||
/* A string pool entry */
|
/* A string pool entry */
|
||||||
struct StringPoolEntry {
|
struct StringPoolEntry {
|
||||||
StringPoolEntry* Next; /* Pointer to next entry in hash chain */
|
HashNode Node; /* Node for the hash table */
|
||||||
unsigned Hash; /* Full hash value */
|
|
||||||
unsigned Id; /* The numeric string id */
|
unsigned Id; /* The numeric string id */
|
||||||
StrBuf Buf; /* The string itself */
|
StrBuf Buf; /* The string itself */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A string pool */
|
||||||
|
struct StringPool {
|
||||||
|
Collection Entries; /* Entries sorted by number */
|
||||||
|
unsigned TotalSize; /* Total size of all string data */
|
||||||
|
HashTable Tab; /* Hash table */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hash table functions */
|
||||||
|
static const HashFunctions HashFunc = {
|
||||||
|
HT_GenHash,
|
||||||
|
HT_GetKey,
|
||||||
|
HT_Compare
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -75,15 +109,14 @@ struct StringPoolEntry {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static StringPoolEntry* NewStringPoolEntry (const StrBuf* S, unsigned Hash, unsigned Id)
|
static StringPoolEntry* NewStringPoolEntry (const StrBuf* S, unsigned Id)
|
||||||
/* Create a new string pool entry and return it. */
|
/* Create a new string pool entry and return it. */
|
||||||
{
|
{
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry));
|
StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
E->Next = 0;
|
InitHashNode (&E->Node);
|
||||||
E->Hash = Hash;
|
|
||||||
E->Id = Id;
|
E->Id = Id;
|
||||||
SB_Init (&E->Buf);
|
SB_Init (&E->Buf);
|
||||||
SB_Copy (&E->Buf, S);
|
SB_Copy (&E->Buf, S);
|
||||||
@@ -97,32 +130,64 @@ static StringPoolEntry* NewStringPoolEntry (const StrBuf* S, unsigned Hash, unsi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Hash table functions */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned HT_GenHash (const void* Key)
|
||||||
|
/* Generate the hash over a key. */
|
||||||
|
{
|
||||||
|
return HashBuf (Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const void* HT_GetKey (const void* Entry)
|
||||||
|
/* Given a pointer to the user entry data, return a pointer to the index */
|
||||||
|
{
|
||||||
|
return &((const StringPoolEntry*) Entry)->Buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int HT_Compare (const void* Key1, const void* Key2)
|
||||||
|
/* Compare two keys. The function must return a value less than zero if
|
||||||
|
* Key1 is smaller than Key2, zero if both are equal, and a value greater
|
||||||
|
* than zero if Key1 is greater then Key2.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return SB_Compare (Key1, Key2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StringPool* InitStringPool (StringPool* P)
|
StringPool* NewStringPool (unsigned HashSlots)
|
||||||
/* Initialize a string pool */
|
/* Allocate, initialize and return a new string pool */
|
||||||
{
|
{
|
||||||
unsigned I;
|
/* Allocate memory */
|
||||||
|
StringPool* P = xmalloc (sizeof (*P));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
for (I = 0; I < sizeof (P->Tab) / sizeof (P->Tab[0]); ++I) {
|
P->Entries = EmptyCollection;
|
||||||
P->Tab[I] = 0;
|
|
||||||
}
|
|
||||||
P->Entries = EmptyCollection;
|
|
||||||
P->TotalSize = 0;
|
P->TotalSize = 0;
|
||||||
|
InitHashTable (&P->Tab, HashSlots, &HashFunc);
|
||||||
|
|
||||||
/* Return a pointer to the initialized pool */
|
/* Return a pointer to the new pool */
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DoneStringPool (StringPool* P)
|
void FreeStringPool (StringPool* P)
|
||||||
/* Free the data of a string pool (but not the data itself) */
|
/* Free a string pool */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
@@ -140,31 +205,8 @@ void DoneStringPool (StringPool* P)
|
|||||||
}
|
}
|
||||||
CollDeleteAll (&P->Entries);
|
CollDeleteAll (&P->Entries);
|
||||||
|
|
||||||
/* Clear the hash table */
|
/* Free the hash table */
|
||||||
for (I = 0; I < sizeof (P->Tab) / sizeof (P->Tab[0]); ++I) {
|
DoneHashTable (&P->Tab);
|
||||||
P->Tab[I] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset the size */
|
|
||||||
P->TotalSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StringPool* NewStringPool (void)
|
|
||||||
/* Allocate, initialize and return a new string pool */
|
|
||||||
{
|
|
||||||
/* Allocate memory, initialize and return it */
|
|
||||||
return InitStringPool (xmalloc (sizeof (StringPool)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FreeStringPool (StringPool* P)
|
|
||||||
/* Free a string pool */
|
|
||||||
{
|
|
||||||
/* Free all entries */
|
|
||||||
DoneStringPool (P);
|
|
||||||
|
|
||||||
/* Free the string pool itself */
|
/* Free the string pool itself */
|
||||||
xfree (P);
|
xfree (P);
|
||||||
@@ -190,35 +232,25 @@ unsigned SP_Add (StringPool* P, const StrBuf* S)
|
|||||||
* existing string.
|
* existing string.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Calculate the string hash */
|
/* Search for a matching entry in the hash table */
|
||||||
unsigned Hash = HashBuf (S);
|
StringPoolEntry* E = HT_FindEntry (&P->Tab, S);
|
||||||
|
|
||||||
/* Calculate the reduced string hash */
|
/* Did we find it? */
|
||||||
unsigned RHash = Hash % (sizeof (P->Tab)/sizeof (P->Tab[0]));
|
if (E != 0) {
|
||||||
|
|
||||||
/* Search for an existing entry */
|
/* We didn't find the entry, so create a new one */
|
||||||
StringPoolEntry* E = P->Tab[RHash];
|
E = NewStringPoolEntry (S, CollCount (&P->Entries));
|
||||||
while (E) {
|
|
||||||
if (E->Hash == Hash && SB_Compare (&E->Buf, S) == 0) {
|
/* Insert the new entry into the entries collection */
|
||||||
/* Found, return the id of the existing string */
|
CollAppend (&P->Entries, E);
|
||||||
return E->Id;
|
|
||||||
}
|
/* Insert the new entry into the hash table */
|
||||||
E = E->Next;
|
HT_InsertEntry (&P->Tab, E);
|
||||||
|
|
||||||
|
/* Add up the string size */
|
||||||
|
P->TotalSize += SB_GetLen (&E->Buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We didn't find the entry, so create a new one */
|
|
||||||
E = NewStringPoolEntry (S, Hash, CollCount (&P->Entries));
|
|
||||||
|
|
||||||
/* Insert the new entry into the entry collection */
|
|
||||||
CollAppend (&P->Entries, E);
|
|
||||||
|
|
||||||
/* Insert the new entry into the hash table */
|
|
||||||
E->Next = P->Tab[RHash];
|
|
||||||
P->Tab[RHash] = E;
|
|
||||||
|
|
||||||
/* Add up the string size */
|
|
||||||
P->TotalSize += SB_GetLen (&E->Buf);
|
|
||||||
|
|
||||||
/* Return the id of the entry */
|
/* Return the id of the entry */
|
||||||
return E->Id;
|
return E->Id;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "attrib.h"
|
#include "hashtab.h"
|
||||||
#include "coll.h"
|
|
||||||
#include "inline.h"
|
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -66,20 +64,6 @@ typedef struct StringPoolEntry StringPoolEntry;
|
|||||||
|
|
||||||
/* A string pool */
|
/* A string pool */
|
||||||
typedef struct StringPool StringPool;
|
typedef struct StringPool StringPool;
|
||||||
struct StringPool {
|
|
||||||
Collection Entries; /* Entries sorted by number */
|
|
||||||
unsigned TotalSize; /* Total size of all string data */
|
|
||||||
StringPoolEntry* Tab[4177]; /* Entry hash table */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* A string pool initializer. We do only initialize the first field, all
|
|
||||||
* others will get zeroed out by the compiler.
|
|
||||||
*/
|
|
||||||
#define STATIC_STRINGPOOL_INITIALIZER { \
|
|
||||||
STATIC_COLLECTION_INITIALIZER, \
|
|
||||||
0, \
|
|
||||||
{ 0 } \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -89,13 +73,7 @@ struct StringPool {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
StringPool* InitStringPool (StringPool* P);
|
StringPool* NewStringPool (unsigned HashSlots);
|
||||||
/* Initialize a string pool */
|
|
||||||
|
|
||||||
void DoneStringPool (StringPool* P);
|
|
||||||
/* Free the data of a string pool (but not the data itself) */
|
|
||||||
|
|
||||||
StringPool* NewStringPool (void);
|
|
||||||
/* Allocate, initialize and return a new string pool */
|
/* Allocate, initialize and return a new string pool */
|
||||||
|
|
||||||
void FreeStringPool (StringPool* P);
|
void FreeStringPool (StringPool* P);
|
||||||
@@ -115,15 +93,8 @@ unsigned SP_AddStr (StringPool* P, const char* S);
|
|||||||
* exist in the pool, SP_Add will just return the index of the existing string.
|
* exist in the pool, SP_Add will just return the index of the existing string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
unsigned SP_GetCount (const StringPool* P);
|
||||||
INLINE unsigned SP_GetCount (const StringPool* P)
|
|
||||||
/* Return the number of strings in the pool */
|
/* Return the number of strings in the pool */
|
||||||
{
|
|
||||||
return CollCount (&P->Entries);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define SP_GetCount(P) CollCount (&(P)->Entries)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user