home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
src
/
common
/
strtbl.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-12-12
|
5KB
|
217 lines
/*
* The functions in this file maintain a hash table of strings and manage
* string buffers.
*/
#include "../h/gsupport.h"
/*
* Prototype for static function.
*/
static int streq (int len, char *s1, char *s2);
/*
* Entry in string table.
*/
struct str_entry {
char *s; /* string */
int length; /* length of string */
struct str_entry *next;
};
#define SBufSize 1024 /* initial size of a string buffer */
#define StrTblSz 149 /* size of string hash table */
static struct str_entry **str_tbl = NULL; /* string hash table */
/*
* init_str - initialize string hash table.
*/
void init_str()
{
int h;
if (str_tbl == NULL) {
str_tbl = alloc(StrTblSz * sizeof(struct str_entry *));
for (h = 0; h < StrTblSz; ++h)
str_tbl[h] = NULL;
}
}
/*
* free_stbl - free string table.
*/
void free_stbl()
{
struct str_entry *se, *se1;
int h;
for (h = 0; h < StrTblSz; ++h)
for (se = str_tbl[h]; se != NULL; se = se1) {
se1 = se->next;
free((char *)se);
}
free((char *)str_tbl);
str_tbl = NULL;
}
/*
* init_sbuf - initialize a new sbuf struct, allocating an initial buffer.
*/
void init_sbuf(sbuf)
struct str_buf *sbuf;
{
sbuf->size = SBufSize;
sbuf->frag_lst = alloc(sizeof(struct str_buf_frag) + (SBufSize - 1));
sbuf->frag_lst->next = NULL;
sbuf->strtimage = sbuf->frag_lst->s;
sbuf->endimage = sbuf->strtimage;
sbuf->end = sbuf->strtimage + SBufSize;
}
/*
* clear_sbuf - free string buffer storage.
*/
void clear_sbuf(sbuf)
struct str_buf *sbuf;
{
struct str_buf_frag *sbf, *sbf1;
for (sbf = sbuf->frag_lst; sbf != NULL; sbf = sbf1) {
sbf1 = sbf->next;
free((char *)sbf);
}
sbuf->frag_lst = NULL;
sbuf->strtimage = NULL;
sbuf->endimage = NULL;
sbuf->end = NULL;
}
/*
* new_sbuf - allocate a new buffer for a sbuf struct, copying the partially
* created string from the end of full buffer to the new one.
*/
void new_sbuf(sbuf)
struct str_buf *sbuf;
{
struct str_buf_frag *sbf;
char *s1, *s2;
/*
* The new buffer is larger than the old one to insure that any
* size string can be buffered.
*/
#if IntBits == 16
unsigned int oldsize = sbuf->size;
sbuf->size += (sbuf->size/2);
if (sbuf->size < oldsize) { /* check for overflow */
sbuf->size = MaxBlock;
}
#else /* IntBits == 16 */
sbuf->size *= 2;
#endif /* IntBits == 16 */
s1 = sbuf->strtimage;
sbf = alloc(sizeof(struct str_buf_frag) + (sbuf->size - 1));
sbf->next = sbuf->frag_lst;
sbuf->frag_lst = sbf;
sbuf->strtimage = sbf->s;
s2 = sbuf->strtimage;
while (s1 < sbuf->endimage)
*s2++ = *s1++;
sbuf->endimage = s2;
sbuf->end = sbuf->strtimage + sbuf->size;
}
/*
* spec_str - install a special string (null terminated) in the string table.
*/
char *spec_str(s)
char *s;
{
struct str_entry *se;
register char *s1;
register int l;
register int h;
h = 0;
l = 1;
for (s1 = s; *s1 != '\0'; ++s1) {
h += *s1 & 0377;
++l;
}
h %= StrTblSz;
for (se = str_tbl[h]; se != NULL; se = se->next)
if (l == se->length && streq(l, s, se->s))
return se->s;
se = NewStruct(str_entry);
se->s = s;
se->length = l;
se->next = str_tbl[h];
str_tbl[h] = se;
return s;
}
/*
* str_install - find out if the string at the end of the buffer is in
* the string table. If not, put it there. Return a pointer to the
* string in the table.
*/
char *str_install(sbuf)
struct str_buf *sbuf;
{
int h;
struct str_entry *se;
register char *s;
register char *e;
int l;
AppChar(*sbuf, '\0'); /* null terminate the buffered copy of the string */
s = sbuf->strtimage;
e = sbuf->endimage;
/*
* Compute hash value.
*/
h = 0;
while (s < e)
h += *s++ & 0377;
h %= StrTblSz;
s = sbuf->strtimage;
l = e - s;
for (se = str_tbl[h]; se != NULL; se = se->next)
if (l == se->length && streq(l, s, se->s)) {
/*
* A copy of the string is already in the table. Delete the copy
* in the buffer.
*/
sbuf->endimage = s;
return se->s;
}
/*
* The string is not in the table. Add the copy from the buffer to the
* table.
*/
se = NewStruct(str_entry);
se->s = s;
se->length = l;
sbuf->strtimage = e;
se->next = str_tbl[h];
str_tbl[h] = se;
return se->s;
}
/*
* streq - compare s1 with s2 for len bytes, and return 1 for equal,
* 0 for not equal.
*/
static int streq(len, s1, s2)
register int len;
register char *s1, *s2;
{
while (len--)
if (*s1++ != *s2++)
return 0;
return 1;
}