You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/kpdf/xpdf/goo/GHash.cpp

381 lines
5.9 KiB

//========================================================================
//
// GHash.cpp
//
// Copyright 2001-2003 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "gmem.h"
#include "GString.h"
#include "GHash.h"
//------------------------------------------------------------------------
struct GHashBucket {
GString *key;
union {
void *p;
int i;
} val;
GHashBucket *next;
};
struct GHashIter {
int h;
GHashBucket *p;
};
//------------------------------------------------------------------------
GHash::GHash(GBool deleteKeysA) {
int h;
deleteKeys = deleteKeysA;
size = 7;
tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
for (h = 0; h < size; ++h) {
tab[h] = NULL;
}
len = 0;
}
GHash::~GHash() {
GHashBucket *p;
int h;
for (h = 0; h < size; ++h) {
while (tab[h]) {
p = tab[h];
tab[h] = p->next;
if (deleteKeys) {
delete p->key;
}
delete p;
}
}
gfree(tab);
}
void GHash::add(GString *key, void *val) {
GHashBucket *p;
int h;
// expand the table if necessary
if (len >= size) {
expand();
}
// add the new symbol
p = new GHashBucket;
p->key = key;
p->val.p = val;
h = hash(key);
p->next = tab[h];
tab[h] = p;
++len;
}
void GHash::add(GString *key, int val) {
GHashBucket *p;
int h;
// expand the table if necessary
if (len >= size) {
expand();
}
// add the new symbol
p = new GHashBucket;
p->key = key;
p->val.i = val;
h = hash(key);
p->next = tab[h];
tab[h] = p;
++len;
}
void GHash::replace(GString *key, void *val) {
GHashBucket *p;
int h;
if ((p = find(key, &h))) {
p->val.p = val;
delete key;
} else {
add(key, val);
}
}
void GHash::replace(GString *key, int val) {
GHashBucket *p;
int h;
if ((p = find(key, &h))) {
p->val.i = val;
delete key;
} else {
add(key, val);
}
}
void *GHash::lookup(GString *key) {
GHashBucket *p;
int h;
if (!(p = find(key, &h))) {
return NULL;
}
return p->val.p;
}
int GHash::lookupInt(GString *key) {
GHashBucket *p;
int h;
if (!(p = find(key, &h))) {
return 0;
}
return p->val.i;
}
void *GHash::lookup(char *key) {
GHashBucket *p;
int h;
if (!(p = find(key, &h))) {
return NULL;
}
return p->val.p;
}
int GHash::lookupInt(char *key) {
GHashBucket *p;
int h;
if (!(p = find(key, &h))) {
return 0;
}
return p->val.i;
}
void *GHash::remove(GString *key) {
GHashBucket *p;
GHashBucket **q;
void *val;
int h;
if (!(p = find(key, &h))) {
return NULL;
}
q = &tab[h];
while (*q != p) {
q = &((*q)->next);
}
*q = p->next;
if (deleteKeys) {
delete p->key;
}
val = p->val.p;
delete p;
--len;
return val;
}
int GHash::removeInt(GString *key) {
GHashBucket *p;
GHashBucket **q;
int val;
int h;
if (!(p = find(key, &h))) {
return 0;
}
q = &tab[h];
while (*q != p) {
q = &((*q)->next);
}
*q = p->next;
if (deleteKeys) {
delete p->key;
}
val = p->val.i;
delete p;
--len;
return val;
}
void *GHash::remove(char *key) {
GHashBucket *p;
GHashBucket **q;
void *val;
int h;
if (!(p = find(key, &h))) {
return NULL;
}
q = &tab[h];
while (*q != p) {
q = &((*q)->next);
}
*q = p->next;
if (deleteKeys) {
delete p->key;
}
val = p->val.p;
delete p;
--len;
return val;
}
int GHash::removeInt(char *key) {
GHashBucket *p;
GHashBucket **q;
int val;
int h;
if (!(p = find(key, &h))) {
return 0;
}
q = &tab[h];
while (*q != p) {
q = &((*q)->next);
}
*q = p->next;
if (deleteKeys) {
delete p->key;
}
val = p->val.i;
delete p;
--len;
return val;
}
void GHash::startIter(GHashIter **iter) {
*iter = new GHashIter;
(*iter)->h = -1;
(*iter)->p = NULL;
}
GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
if (!*iter) {
return gFalse;
}
if ((*iter)->p) {
(*iter)->p = (*iter)->p->next;
}
while (!(*iter)->p) {
if (++(*iter)->h == size) {
delete *iter;
*iter = NULL;
return gFalse;
}
(*iter)->p = tab[(*iter)->h];
}
*key = (*iter)->p->key;
*val = (*iter)->p->val.p;
return gTrue;
}
GBool GHash::getNext(GHashIter **iter, GString **key, int *val) {
if (!*iter) {
return gFalse;
}
if ((*iter)->p) {
(*iter)->p = (*iter)->p->next;
}
while (!(*iter)->p) {
if (++(*iter)->h == size) {
delete *iter;
*iter = NULL;
return gFalse;
}
(*iter)->p = tab[(*iter)->h];
}
*key = (*iter)->p->key;
*val = (*iter)->p->val.i;
return gTrue;
}
void GHash::killIter(GHashIter **iter) {
delete *iter;
*iter = NULL;
}
void GHash::expand() {
GHashBucket **oldTab;
GHashBucket *p;
int oldSize, h, i;
oldSize = size;
oldTab = tab;
size = 2*size + 1;
tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
for (h = 0; h < size; ++h) {
tab[h] = NULL;
}
for (i = 0; i < oldSize; ++i) {
while (oldTab[i]) {
p = oldTab[i];
oldTab[i] = oldTab[i]->next;
h = hash(p->key);
p->next = tab[h];
tab[h] = p;
}
}
gfree(oldTab);
}
GHashBucket *GHash::find(GString *key, int *h) {
GHashBucket *p;
*h = hash(key);
for (p = tab[*h]; p; p = p->next) {
if (!p->key->cmp(key)) {
return p;
}
}
return NULL;
}
GHashBucket *GHash::find(char *key, int *h) {
GHashBucket *p;
*h = hash(key);
for (p = tab[*h]; p; p = p->next) {
if (!p->key->cmp(key)) {
return p;
}
}
return NULL;
}
int GHash::hash(GString *key) {
char *p;
unsigned int h;
int i;
h = 0;
for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
h = 17 * h + (int)(*p & 0xff);
}
return (int)(h % size);
}
int GHash::hash(char *key) {
char *p;
unsigned int h;
h = 0;
for (p = key; *p; ++p) {
h = 17 * h + (int)(*p & 0xff);
}
return (int)(h % size);
}