00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #ifndef GLMAP_INCLUDED
00070 #define GLMAP_INCLUDED
00071
00072 #pragma warning( disable : 4530 )
00073 #pragma warning( disable : 4786 )
00074 #include <string>
00075 #include <ctype.h>
00076 #include "glutil.h"
00077 #include "gldebug.h"
00078 #include "glprime.h"
00079 #include "gltypes.h"
00080
00081
00082 class GlHash
00083 {
00084 public:
00085 U32 HashValue() { return val; }
00086 protected:
00087 U32 val;
00088 };
00089
00090 class GlStringHash : public GlHash
00091 {
00092 public:
00093 GlStringHash( const std::string& str )
00094 {
00095 val = 0;
00096 for ( unsigned i=0; i<str.length() && i < 32; ++i )
00097 {
00098 val <<= 1;
00099 val |= str[i];
00100 }
00101 }
00102 };
00103
00104 template < class T >
00105 class GlNumberHash : public GlHash
00106 {
00107 public:
00108 GlNumberHash( T num ) { val = (T) num; }
00109 };
00110
00111
00112
00113
00114
00115
00116 template < class KEY, class VALUE, class HASH >
00117 class GlMap
00118 {
00119 public:
00120 GlMap( U32 startSize = 64, U32 grow = 60 );
00121 ~GlMap();
00122
00123
00124 bool Add( const KEY& key, const VALUE& value );
00125
00126
00127 bool Remove( const KEY& key );
00128
00129
00130
00131 bool Find( const KEY& key, VALUE* value );
00132
00133
00134 enum {
00135 EXPAND = 4
00136 };
00137
00138 struct Item
00139 {
00140 KEY key;
00141 VALUE value;
00142 Item* next;
00143 };
00144
00145
00146 void Grow( unsigned newsize );
00147
00148 U32 numBuckets;
00149 Item** buckets;
00150 U32 grow;
00151 U32 numItems;
00152 };
00153
00154
00155
00156
00157 template < class KEY, class VALUE, class HASH >
00158 inline GlMap< KEY, VALUE, HASH>::GlMap( U32 startSize, U32 _grow )
00159 {
00160 numBuckets = GlPrime( startSize, 1 );
00161 buckets = new Item*[ numBuckets ];
00162 memset( buckets, 0, sizeof( Item* ) * numBuckets );
00163 grow = _grow;
00164 numItems = 0;
00165
00166 #ifdef DEBUG
00167
00168 #endif
00169 };
00170
00171
00172 template < class KEY, class VALUE, class HASH >
00173 inline GlMap< KEY, VALUE, HASH>::~GlMap()
00174 {
00175 for( U32 i=0; i<numBuckets; ++i )
00176 {
00177 while ( buckets[i] )
00178 {
00179 Item* next = buckets[i]->next;
00180 delete buckets[i];
00181 buckets[i] = next;
00182 }
00183 }
00184
00185
00186 delete [] buckets;
00187 };
00188
00189
00190 template < class KEY, class VALUE, class HASH >
00191 inline void GlMap< KEY, VALUE, HASH>::Grow( unsigned newsize )
00192 {
00193 #ifdef DEBUG
00194 int itemcount = 0;
00195 #endif
00196
00197
00198 Item *root = 0;
00199 for( U32 i=0; i<numBuckets; ++i )
00200 {
00201 while ( buckets[i] )
00202 {
00203 Item* next = buckets[i]->next;
00204
00205 buckets[i]->next = root;
00206 root = buckets[i];
00207
00208 buckets[i] = next;
00209
00210 #ifdef DEBUG
00211 ++itemcount;
00212 #endif
00213 }
00214 }
00215 #ifdef DEBUG
00216 int comparecount = 0;
00217 for( Item* it = root; it; it = it->next )
00218 ++comparecount;
00219 GLASSERT( comparecount == itemcount );
00220 #endif
00221
00222
00223 delete [] buckets;
00224 buckets = 0;
00225
00226 #ifdef DEBUG
00227
00228 #endif
00229
00230 numBuckets = GlPrime( newsize, 1 );
00231 #ifdef DEBUG
00232
00233 #endif
00234
00235 buckets = new Item*[ numBuckets ];
00236 memset( buckets, 0, sizeof( Item* ) * numBuckets );
00237
00238 while ( root )
00239 {
00240 Item* next = root->next;
00241
00242 HASH hash( root->key );
00243 U32 which = hash.HashValue() % numBuckets;
00244
00245 root->next = buckets[ which ];
00246 buckets[ which ] = root;
00247
00248 root = next;
00249 }
00250 }
00251
00252
00253 template < class KEY, class VALUE, class HASH >
00254 inline bool GlMap< KEY, VALUE, HASH>::Add( const KEY& key, const VALUE& value )
00255 {
00256 VALUE dummy;
00257 if ( Find( key, &dummy ) )
00258 return false;
00259
00260
00261 if ( ( ( numItems + 1 ) * 100 / numBuckets ) > grow )
00262 {
00263 Grow( GlMax( numItems * EXPAND, numBuckets * EXPAND ) );
00264 }
00265
00266
00267 HASH hash( key );
00268 U32 which = hash.HashValue() % numBuckets;
00269
00270 Item* item = new Item;
00271 item->key = key;
00272 item->value = value;
00273 item->next = buckets[ which ];
00274
00275 buckets[ which ] = item;
00276 ++numItems;
00277 return true;
00278 }
00279
00280
00281 template < class KEY, class VALUE, class HASH >
00282 inline bool GlMap< KEY, VALUE, HASH>::Find( const KEY& key, VALUE* value )
00283 {
00284 HASH hash( key );
00285 U32 which = hash.HashValue() % numBuckets;
00286
00287 Item* item = buckets[which];
00288
00289 while( item )
00290 {
00291 if ( item->key == key )
00292 {
00293 *value = item->value;
00294 return true;
00295 }
00296 item = item->next;
00297 }
00298 return false;
00299 }
00300
00301
00302 template < class KEY, class VALUE, class HASH >
00303 inline bool GlMap< KEY, VALUE, HASH>::Remove( const KEY& key )
00304 {
00305 HASH hash( key );
00306 U32 which = hash.HashValue() % numBuckets;
00307
00308 Item* item = buckets[which];
00309 Item* prev = 0;
00310
00311 while( item )
00312 {
00313 if ( item->key == key )
00314 {
00315 if ( prev )
00316 prev->next = item->next;
00317 else
00318 buckets[ which ] = item->next;
00319
00320 delete item;
00321 --numItems;
00322 return true;
00323 }
00324 prev = item;
00325 item = item->next;
00326 }
00327 return false;
00328 }
00329
00330
00331 template < class KEY, class VALUE, class HASH >
00332 class GlMapIterator
00333 {
00334 public:
00335 GlMapIterator( GlMap< KEY, VALUE, HASH >& _map ) { map = &_map; bucket=0; item=0; }
00336
00337 void Begin() { bucket=0; item=map->buckets[0]; FindValid(); }
00338 void Next() { item=item->next; FindValid(); }
00339 bool Done() { return ( bucket < 0 ); }
00340
00341 void Current( KEY* key, VALUE* value )
00342 {
00343 if ( item )
00344 {
00345 *key = item->key;
00346 *value = item->value;
00347 }
00348 }
00349
00350 private:
00351 GlMap< KEY, VALUE, HASH >* map;
00352 int bucket;
00353 typename GlMap< KEY, VALUE, HASH >::Item* item;
00354
00355 void FindValid()
00356 {
00357 if ( bucket < 0
00358 || ( item && bucket >=0 ))
00359 {
00360 return;
00361 }
00362 GLASSERT( item == 0 );
00363 for ( ++bucket; bucket < map->numBuckets; ++bucket )
00364 {
00365 if ( map->buckets[bucket] )
00366 {
00367 item = map->buckets[ bucket ];
00368 return;
00369 }
00370 }
00371 bucket = -1;
00372 item = 0;
00373 }
00374 };
00375
00376
00377 #endif
00378