00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef __GNUC__
00010 #pragma implementation
00011 #endif
00012
00013 #include <aconf.h>
00014 #include "gmem.h"
00015 #include "GString.h"
00016 #include "GHash.h"
00017
00018
00019
00020 struct GHashBucket {
00021 GString *key;
00022 void *val;
00023 GHashBucket *next;
00024 };
00025
00026 struct GHashIter {
00027 int h;
00028 GHashBucket *p;
00029 };
00030
00031
00032
00033 GHash::GHash(GBool deleteKeysA) {
00034 int h;
00035
00036 deleteKeys = deleteKeysA;
00037 size = 7;
00038 tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
00039 for (h = 0; h < size; ++h) {
00040 tab[h] = NULL;
00041 }
00042 len = 0;
00043 }
00044
00045 GHash::~GHash() {
00046 GHashBucket *p;
00047 int h;
00048
00049 for (h = 0; h < size; ++h) {
00050 while (tab[h]) {
00051 p = tab[h];
00052 tab[h] = p->next;
00053 if (deleteKeys) {
00054 delete p->key;
00055 }
00056 delete p;
00057 }
00058 }
00059 gfree(tab);
00060 }
00061
00062 void GHash::add(GString *key, void *val) {
00063 GHashBucket **oldTab;
00064 GHashBucket *p;
00065 int oldSize, i, h;
00066
00067
00068 if (len >= size) {
00069 oldSize = size;
00070 oldTab = tab;
00071 size = 2*size + 1;
00072 tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
00073 for (h = 0; h < size; ++h) {
00074 tab[h] = NULL;
00075 }
00076 for (i = 0; i < oldSize; ++i) {
00077 while (oldTab[i]) {
00078 p = oldTab[i];
00079 oldTab[i] = oldTab[i]->next;
00080 h = hash(p->key);
00081 p->next = tab[h];
00082 tab[h] = p;
00083 }
00084 }
00085 gfree(oldTab);
00086 }
00087
00088
00089 p = new GHashBucket;
00090 p->key = key;
00091 p->val = val;
00092 h = hash(key);
00093 p->next = tab[h];
00094 tab[h] = p;
00095 ++len;
00096 }
00097
00098 void *GHash::lookup(GString *key) {
00099 GHashBucket *p;
00100 int h;
00101
00102 if (!(p = find(key, &h))) {
00103 return NULL;
00104 }
00105 return p->val;
00106 }
00107
00108 void *GHash::lookup(char *key) {
00109 GHashBucket *p;
00110 int h;
00111
00112 if (!(p = find(key, &h))) {
00113 return NULL;
00114 }
00115 return p->val;
00116 }
00117
00118 void *GHash::remove(GString *key) {
00119 GHashBucket *p;
00120 GHashBucket **q;
00121 void *val;
00122 int h;
00123
00124 if (!(p = find(key, &h))) {
00125 return NULL;
00126 }
00127 q = &tab[h];
00128 while (*q != p) {
00129 q = &((*q)->next);
00130 }
00131 *q = p->next;
00132 if (deleteKeys) {
00133 delete p->key;
00134 }
00135 val = p->val;
00136 delete p;
00137 --len;
00138 return val;
00139 }
00140
00141 void *GHash::remove(char *key) {
00142 GHashBucket *p;
00143 GHashBucket **q;
00144 void *val;
00145 int h;
00146
00147 if (!(p = find(key, &h))) {
00148 return NULL;
00149 }
00150 q = &tab[h];
00151 while (*q != p) {
00152 q = &((*q)->next);
00153 }
00154 *q = p->next;
00155 if (deleteKeys) {
00156 delete p->key;
00157 }
00158 val = p->val;
00159 delete p;
00160 --len;
00161 return val;
00162 }
00163
00164 void GHash::startIter(GHashIter **iter) {
00165 *iter = new GHashIter;
00166 (*iter)->h = -1;
00167 (*iter)->p = NULL;
00168 }
00169
00170 GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
00171 if (!*iter) {
00172 return gFalse;
00173 }
00174 if ((*iter)->p) {
00175 (*iter)->p = (*iter)->p->next;
00176 }
00177 while (!(*iter)->p) {
00178 if (++(*iter)->h == size) {
00179 delete *iter;
00180 *iter = NULL;
00181 return gFalse;
00182 }
00183 (*iter)->p = tab[(*iter)->h];
00184 }
00185 *key = (*iter)->p->key;
00186 *val = (*iter)->p->val;
00187 return gTrue;
00188 }
00189
00190 void GHash::killIter(GHashIter **iter) {
00191 delete *iter;
00192 *iter = NULL;
00193 }
00194
00195 GHashBucket *GHash::find(GString *key, int *h) {
00196 GHashBucket *p;
00197
00198 *h = hash(key);
00199 for (p = tab[*h]; p; p = p->next) {
00200 if (!p->key->cmp(key)) {
00201 return p;
00202 }
00203 }
00204 return NULL;
00205 }
00206
00207 GHashBucket *GHash::find(char *key, int *h) {
00208 GHashBucket *p;
00209
00210 *h = hash(key);
00211 for (p = tab[*h]; p; p = p->next) {
00212 if (!p->key->cmp(key)) {
00213 return p;
00214 }
00215 }
00216 return NULL;
00217 }
00218
00219 int GHash::hash(GString *key) {
00220 char *p;
00221 unsigned int h;
00222 int i;
00223
00224 h = 0;
00225 for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
00226 h = 17 * h + (int)(*p & 0xff);
00227 }
00228 return (int)(h % size);
00229 }
00230
00231 int GHash::hash(char *key) {
00232 char *p;
00233 unsigned int h;
00234
00235 h = 0;
00236 for (p = key; *p; ++p) {
00237 h = 17 * h + (int)(*p & 0xff);
00238 }
00239 return (int)(h % size);
00240 }