Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

GHash.cc

Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // GHash.cc
00004 //
00005 // Copyright 2001 Derek B. Noonburg
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   // expand the table if necessary
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   // add the new symbol
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 }

Generated on Sat Nov 5 16:18:11 2005 for OPIE by  doxygen 1.4.2