Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
cxx_hash.h
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 //-*-c++-*-
00037 // ====================================================================
00038 // ====================================================================
00039 //
00040 //
00041 // Revision history:
00042 //  07-Dec-95 - Merged USER_HASH_TABLE support.
00043 //
00044 // Description:
00045 //
00046 // This file contains templates for open hash tables.
00047 //
00048 // ====================================================================
00049 //
00050 // (template...) class HASH_TABLE
00051 //
00052 // The first implementation maps SIG_TYPE keys into DATA_TYPE *data.
00053 // A typical instantiation would be INT for SIG_TYPE and void * for
00054 // DATA_TYPE.  This implementation has the following key attributes:
00055 //
00056 //  1)  The size of the hash table is determined at constructor time.
00057 //
00058 //  2)  The hash table elements are lists of objects.
00059 //
00060 //  3)  The objects in the table's lists are pairs consisting of a
00061 //      signature (key) and a data element to which the key is mapped.
00062 //
00063 //  4)  The hash function is a built in function of the signature.
00064 //      Therefore, for example, it will be the pointer value for
00065 //      a string key, and will produce different entries for distinct
00066 //      pointers to the same character string.
00067 //
00068 // template <class SIG_TYPE, class DATA_TYPE> class HASH_TABLE
00069 // 
00070 //              An open hash table.  This table maps SIG_TYPE signatures
00071 //              into DATA_TYPE data.
00072 //
00073 //          HASH_TABLE(const UINT num_elements, MEM_POOL *pool)
00074 //
00075 //              Create a new hash table with num_elements elements.
00076 //              Store the table in pool.
00077 //
00078 //          void Enter(SIG_TYPE signature, DATA_TYPE data)
00079 //
00080 //              Enter into the table the pair (signature, data)
00081 //              This routine does not check for duplicates.
00082 //
00083 //          void Enter_If_Unique(SIG_TYPE signature, DATA_TYPE data)
00084 //
00085 //              Enter the pair into the table if signature is not
00086 //              already in the table
00087 //
00088 //          DATA_TYPE Find(SIG_TYPE signature) const
00089 //
00090 //              Return the data if it is in the table, NULL otherwise.
00091 //
00092 //           void Remove(SIG_TYPE signature)
00093 //
00094 //              If it's in the table, remove it
00095 //
00096 //      UINT Num_Entries() const
00097 //          Return the number of entries in the table.
00098 //          This is different from Num_Elements.
00099 //
00100 //          ~HASH_TABLE() 
00101 //
00102 //  template <class SIG_TYPE, class DATA_TYPE> HASH_TABLE_ITER
00103 //
00104 //          HASH_TABLE_ITER(const HASH_TABLE*)
00105 //          BOOL Step(SIG_TYPE*, DATA_TYPE*)
00106 //
00107 //              Usage:
00108 //                  HASH_TABLE_ITER it(hashtable);
00109 //                  while (it.Step(&sig, &data))
00110 //                      ...
00111 //
00112 // ====================================================================
00113 //
00114 // (template...) class USER_HASH_TABLE
00115 //
00116 // The second implementation maps KEY_TYPE keys into DATA_TYPE *data.
00117 // It is very similar to HASH_TABLE, but allows the user to supply a
00118 // hash function and a key equality function.
00119 //
00120 // A typical instantiation would be char * for KEY_TYPE and void * for
00121 // DATA_TYPE.  This implementation has the following key attributes:
00122 //
00123 //  1)  The size of the hash table is determined at constructor time.
00124 //
00125 //  2)  The hash table elements are lists of objects.
00126 //
00127 //  3)  The objects in the table's lists are pairs consisting of a
00128 //      signature (key) and a data element to which the key is mapped.
00129 //
00130 //  4)  The hash function is provided by the user as a function object
00131 //      HASH_FUNC on the KEY_TYPE, and equivalence between keys is
00132 //      also provided by a user function object KEY_EQ.  We supply
00133 //      reasonable hash and equality functions for character strings
00134 //      below.
00135 //
00136 // typedef ... HASH;
00137 //      This type must be the result type of the user hash function.
00138 //
00139 // template < class KEY_TYPE, class DATA_TYPE,
00140 //            class HASH_FUNC, class KEY_EQ >
00141 // class USER_HASH_TABLE
00142 // 
00143 //              An open hash table.  This table maps KEY_TYPE
00144 //              keys into DATA_TYPE data.  HASH_FUNC must map
00145 //              KEY_TYPE objects into an HASH hash value, and KEY_EQ
00146 //              must compare two KEY_TYPE objects for equality and
00147 //              return a BOOL result.
00148 //
00149 //          USER_HASH_TABLE ( const UINT32 num_elements, MEM_POOL *pool )
00150 //
00151 //              Create a new hash table with num_elements elements.
00152 //              Store the table in pool.  It may later be resized.
00153 //
00154 //          void Enter ( KEY_TYPE key, DATA_TYPE data )
00155 //
00156 //              Enter into the table the pair (key, data)
00157 //              This routine does not check for duplicates.
00158 //
00159 //          void Enter_If_Unique ( KEY_TYPE key, DATA_TYPE data )
00160 //
00161 //              Enter the pair into the table if key is not
00162 //              already in the table
00163 //
00164 //          DATA_TYPE Find ( KEY_TYPE key ) const
00165 //
00166 //              Return the data if it is in the table, NULL otherwise.
00167 //
00168 //      UINT Num_Entries() const
00169 //          Return the number of entries in the table.
00170 //          This is different from Num_Elements.
00171 //
00172 //          ~HASH_TABLE() 
00173 //
00174 // template < class KEY_TYPE, class DATA_TYPE,
00175 //            class HASH_FUNC, class KEY_EQ >
00176 // USER_HASH_TABLE_ITER
00177 //
00178 //          USER_HASH_TABLE_ITER ( const USER_HASH_TABLE* )
00179 //          BOOL Step ( KEY_TYPE*, DATA_TYPE* )
00180 //
00181 //              Usage:
00182 //                  USER_HASH_TABLE_ITER it(hashtable);
00183 //                  while (it.Step(&key, &data))
00184 //                      ...
00185 //
00186 // ====================================================================
00187 //
00188 // HASH String_Hash ( const char *k );
00189 //      This function object may be used as the HASH_FUNC parameter
00190 //      for USER_HASH_TABLE instances with string keys.
00191 //
00192 // BOOL String_Compare ( const char *s, const char *t );
00193 //      This function object may be used as the KEY_EQ parameter for
00194 //      USER_HASH_TABLE instances with string keys.
00195 //
00196 // ====================================================================
00197 //
00198 // NOTE:  The bodies for the definitions in this file are split between
00199 // cxx_hash.cxx (template bodies) and cxx_hash_util.cxx (non-template
00200 // bodies).
00201 //
00202 // ====================================================================
00203 // ====================================================================
00204 
00205 #ifndef cxx_hash_INCLUDED
00206 #define cxx_hash_INCLUDED "cxx_hash.h"
00207 
00208 #ifdef _KEEP_RCS_ID
00209 #endif /* _KEEP_RCS_ID */
00210 
00211 #ifndef CXX_MEMORY_INCLUDED
00212 #include "cxx_memory.h"
00213 #endif
00214 #include "erglob.h"
00215 
00216 // ====================================================================
00217 // ====================================================================
00218 //
00219 // HASH_ELEMENT
00220 //
00221 // For both hash map implementations, the main hash table contains
00222 // lists of these objects.
00223 //
00224 // This is public, but no one should touch this except HASH_TABLE,
00225 // HASH_TABLE_ITER, USER_HASH_TABLE, and USER_HASH_TABLE_ITER.
00226 // I would use friend functions, but they don't seem to work with
00227 // templates.
00228 //
00229 // ====================================================================
00230 // ====================================================================
00231 
00232 template <class SIG_TYPE, class DATA_TYPE>
00233 class HASH_ELEMENT
00234 {
00235 public:
00236   DATA_TYPE     _data;
00237   SIG_TYPE      _signature;
00238   HASH_ELEMENT  *_next;
00239 
00240   // create a new element
00241   HASH_ELEMENT(const SIG_TYPE& signature, const DATA_TYPE& data) :
00242     _signature(signature), _data(data), _next(NULL) {}
00243   void Add_To_List(HASH_ELEMENT *e) { e->_next = _next; _next = e; }
00244 };
00245 
00246 // ====================================================================
00247 // ====================================================================
00248 //
00249 // HASH_TABLE
00250 //
00251 // This is a basic hash map, with a built-in hash function.
00252 //
00253 // ====================================================================
00254 // ====================================================================
00255 
00256 template <class SIG_TYPE, class DATA_TYPE>
00257 class HASH_TABLE {
00258 private:
00259   MEM_POOL *_pool;
00260   HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *  *_data;  // an array of HASH_ELEMENT *
00261   UINT _num_elements;
00262   UINT _num_entries;
00263 public:
00264   HASH_TABLE<SIG_TYPE,DATA_TYPE>(UINT num_elements, MEM_POOL *pool);
00265   UINT Num_Elements() const { return _num_elements; };
00266   UINT Num_Entries() const { return _num_entries; };
00267   HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *Data(UINT i) const { return _data[i]; };
00268 
00269   void Enter(SIG_TYPE signature,DATA_TYPE data) {
00270     typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00271     typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00272     HASH_ELEMENTP element = 
00273       CXX_NEW(THIS_HASH_ELEMENT(signature,data),_pool);
00274     UINT location = abs((INT)(INTPS)signature) % _num_elements;
00275     if (_data[location]) { // some thing is there
00276       _data[location]->Add_To_List(element);
00277     } else {
00278       _data[location] = element;
00279     }
00280     _num_entries++;
00281   }
00282 
00283   void Enter_If_Unique(SIG_TYPE signature,DATA_TYPE data); 
00284   DATA_TYPE Find(SIG_TYPE signature) const;
00285   void Remove(SIG_TYPE signature); 
00286 
00287   // Destructor -- remove all entries and the pointer array:
00288   ~HASH_TABLE() {  
00289     typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00290     for (UINT loc = 0; loc < _num_elements; loc++) {
00291       HASH_ELEMENTP element = _data[loc];
00292       HASH_ELEMENTP next_element;
00293       while (element) {
00294         next_element = element->_next;
00295         CXX_DELETE(element, _pool);
00296         element = next_element;
00297       }
00298     }
00299     CXX_DELETE_ARRAY(_data, _pool); 
00300   };
00301 
00302 };
00303 
00304 template <class SIG_TYPE, class DATA_TYPE>
00305 class HASH_TABLE_ITER {
00306  private:
00307   INT                                   _loc;
00308   HASH_ELEMENT<SIG_TYPE,DATA_TYPE>      *_he;
00309   const HASH_TABLE<SIG_TYPE,DATA_TYPE>  *_hash;
00310  public:
00311   BOOL                  Step(SIG_TYPE* sig, DATA_TYPE* data);   // TRUE of ok
00312   HASH_TABLE_ITER(const HASH_TABLE<SIG_TYPE,DATA_TYPE> * h) : 
00313                         _hash(h), _loc(-1), _he(NULL) {}
00314   ~HASH_TABLE_ITER() {}
00315 };
00316 
00317 // ====================================================================
00318 // ====================================================================
00319 //
00320 // Support for USER_HASH_TABLE
00321 //
00322 // Define the required result type of the hash function, and provide
00323 // basic string hash and equality function objects.
00324 //
00325 // ====================================================================
00326 // ====================================================================
00327 
00328 // Hash value typedef:
00329 typedef UINT32 HASH;
00330 
00331 // String hash function:
00332 struct String_Hash
00333 {
00334   HASH operator() ( const char * k ) const;
00335 };
00336 
00337 // String equality function:
00338 struct String_Equal
00339 {
00340   BOOL operator() ( const char *a, const char *b ) const
00341         { return ! strcmp ( a, b ); }
00342 };
00343 
00344 // ====================================================================
00345 // ====================================================================
00346 //
00347 // USER_HASH_TABLE
00348 //
00349 // This is a hash map, very similar to HASH_TABLE, but allowing the
00350 // user to specify the hash function and key equality as function
00351 // objects.
00352 //
00353 // ====================================================================
00354 // ====================================================================
00355 
00356 // The template parameter list is long and unwieldy:
00357 #define TEMPLATE_USER_HASH_TABLE template \
00358     < class KEY_TYPE, class DATA_TYPE, class HASH_FUNC, class KEY_EQ >
00359 #define CLASS_USER_HASH_TABLE \
00360     USER_HASH_TABLE < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ >
00361 
00362 TEMPLATE_USER_HASH_TABLE
00363 class USER_HASH_TABLE {
00364  private:
00365   MEM_POOL *_pool;
00366   HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *  *_data;  // array of HASH_ELEMENT*
00367   UINT32 _num_elements;
00368   UINT _num_entries;
00369   HASH_FUNC _hash;
00370   KEY_EQ _equal;
00371 
00372  public:
00373   // Constructor -- Build a map in 'pool' with 'num_elements' slots:
00374   USER_HASH_TABLE ( UINT32 num_elements, MEM_POOL *pool );
00375 
00376   // Tracing -- only valid if KEY_TYPE is char*:
00377   void Print ( FILE *f );
00378 
00379   // Field access:
00380   UINT32 Num_Elements ( void ) const { return _num_elements; };
00381   UINT Num_Entries( void ) const { return _num_entries; };
00382   HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *Data ( UINT32 i) const
00383         { return _data[i]; }
00384 
00385   // Enter a new element without checking for duplication:
00386   void Enter ( KEY_TYPE key, DATA_TYPE data ) {
00387     typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00388     typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00389     HASH_ELEMENTP element = 
00390       CXX_NEW ( THIS_HASH_ELEMENT(key,data), _pool );
00391     UINT32 location = _hash(key) % _num_elements;
00392 
00393     element->_next = _data[location];
00394     _data[location] = element;
00395     _num_entries++;
00396   }
00397 
00398   // Enter a new element only if the given key is not already mapped:
00399   void Enter_If_Unique ( KEY_TYPE key, DATA_TYPE data ); 
00400 
00401   // Find the given key in the map:
00402   DATA_TYPE Find(KEY_TYPE key) const;
00403 
00404   // Destructor -- remove all entries and the pointer array:
00405   ~USER_HASH_TABLE() {  
00406     typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00407     for (UINT loc = 0; loc < _num_elements; loc++) {
00408       HASH_ELEMENTP element = _data[loc];
00409       HASH_ELEMENTP next_element;
00410       while (element) {
00411         next_element = element->_next;
00412         CXX_DELETE(element, _pool);
00413         element = next_element;
00414       }
00415     }
00416     CXX_DELETE_ARRAY(_data, _pool); 
00417   };
00418 };
00419 
00420 TEMPLATE_USER_HASH_TABLE
00421 class USER_HASH_TABLE_ITER {
00422  private:
00423   INT                                   _loc;
00424   HASH_ELEMENT<KEY_TYPE,DATA_TYPE>      *_he;
00425   const USER_HASH_TABLE < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ > *_hash;
00426 
00427  public:
00428   BOOL  Step ( KEY_TYPE* key, DATA_TYPE* data );        // TRUE of ok
00429   USER_HASH_TABLE_ITER (
00430     const USER_HASH_TABLE < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ > * h ) : 
00431     _hash(h), _loc(-1), _he(NULL) {}
00432   ~USER_HASH_TABLE_ITER ( void ) {}
00433 };
00434 
00435 // Implementation stuff follows. This was taken from cxx_hash.cxx,
00436 // since g++ (rightly) doesn't do the "implicit .cxx file inclusion"
00437 // thing.
00438 
00439 // ====================================================================
00440 // ====================================================================
00441 //
00442 // HASH_TABLE
00443 //
00444 // This is a simple hash map, with the following attributes:
00445 //
00446 //  1)  The size of the hash table is determined at constructor time.
00447 //
00448 //  2)  The hash table elements are lists of objects.
00449 //
00450 //  3)  The objects in the table's lists are pairs consisting of a
00451 //      signature (key) and a data element to which the key is mapped.
00452 //
00453 //  4)  The hash function is built in as the signature modulo the table
00454 //      size.  Therefore, for example, it will be the pointer value for
00455 //      a string key, and will produce different entries for distinct
00456 //      pointers to the same character string.
00457 //
00458 // ====================================================================
00459 // ====================================================================
00460 
00461 template <class SIG_TYPE, class DATA_TYPE>
00462 HASH_TABLE<SIG_TYPE,DATA_TYPE> :: HASH_TABLE (
00463   UINT num_elements,
00464   MEM_POOL *pool )
00465 {
00466   typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00467   _pool = pool;
00468   _num_elements = num_elements;
00469   _num_entries = 0;
00470   _data = CXX_NEW_ARRAY(HASH_ELEMENTP ,num_elements,pool);
00471   for (INT i=0; i<num_elements; i++) {
00472     _data[i] = (HASH_ELEMENTP) 0;
00473   }
00474 }
00475 
00476 template <class SIG_TYPE, class DATA_TYPE>
00477 void
00478 HASH_TABLE<SIG_TYPE,DATA_TYPE> :: Enter_If_Unique(SIG_TYPE signature, 
00479                                                   DATA_TYPE data)
00480 { 
00481   typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00482   typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00483   HASH_ELEMENTP element = 
00484     CXX_NEW(THIS_HASH_ELEMENT(signature,data),_pool);
00485   UINT location = abs((INT)(INTPS)signature) % _num_elements;
00486 
00487   if (_data[location]) { // something is there
00488     HASH_ELEMENTP iter = _data[location];
00489     for (; iter != NULL ; iter = iter->_next) {
00490       if (iter->_signature == signature) {
00491          return; // not unique
00492       }
00493     }
00494     _data[location]->Add_To_List(element);
00495   } else {
00496     _data[location] = element;
00497   }
00498   _num_entries++;
00499 }
00500 
00501 template <class SIG_TYPE, class DATA_TYPE>
00502 DATA_TYPE
00503 HASH_TABLE<SIG_TYPE,DATA_TYPE> :: Find (
00504   SIG_TYPE signature ) const
00505 {
00506   typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00507   HASH_ELEMENTP hash_element = _data[abs((INT)(INTPS)signature) % _num_elements];
00508 
00509   for (; hash_element != NULL; hash_element = hash_element->_next) {
00510     if (hash_element->_signature == signature) {
00511       return(hash_element->_data);
00512     }
00513   }
00514   return((DATA_TYPE)0);
00515 }
00516 
00517 template <class SIG_TYPE, class DATA_TYPE>
00518 void HASH_TABLE<SIG_TYPE,DATA_TYPE> :: Remove (
00519   SIG_TYPE signature ) 
00520 {
00521   typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00522   HASH_ELEMENTP hash_element = _data[abs((INT)signature) % _num_elements];
00523 
00524   if (hash_element->_signature == signature) {
00525     _data[abs((INT)(INTPS)signature) % _num_elements] = hash_element->_next;
00526     CXX_DELETE(hash_element,_pool);
00527     _num_entries--;
00528     return;
00529   }
00530 
00531   HASH_ELEMENTP prev = hash_element;
00532   for (hash_element = hash_element->_next; hash_element; 
00533                                 hash_element = hash_element->_next) {
00534     if (hash_element->_signature == signature) {
00535       prev->_next = hash_element->_next;
00536       CXX_DELETE(hash_element,_pool);
00537       _num_entries--;
00538       return;
00539     }
00540     prev = hash_element;
00541   }
00542 }
00543 
00544 template <class SIG_TYPE, class DATA_TYPE>
00545 BOOL
00546 HASH_TABLE_ITER<SIG_TYPE,DATA_TYPE> :: Step (
00547   SIG_TYPE* sig,
00548   DATA_TYPE* data )
00549 {
00550   if (_he && _he->_next) {
00551     _he = _he->_next;
00552     *sig = _he->_signature;
00553     *data = _he->_data;
00554     return TRUE;
00555   }
00556     
00557   for (_loc++; _loc < _hash->Num_Elements(); _loc++) {
00558     if (_hash->Data(_loc)) {
00559       _he = _hash->Data(_loc);
00560       *sig = _he->_signature;
00561       *data = _he->_data;
00562       return TRUE;
00563     }
00564   }
00565 
00566   return FALSE;
00567 }
00568 
00569 // ====================================================================
00570 // ====================================================================
00571 //
00572 // USER_HASH_TABLE
00573 //
00574 // This is a hash map, very similar to HASH_TABLE, with the following
00575 // attributes (only #4 differs from HASH_TABLE):
00576 //
00577 //  1)  The size of the hash table is determined at constructor time.
00578 //
00579 //  2)  The hash table elements are lists of objects.
00580 //
00581 //  3)  The objects in the table's lists are pairs consisting of a
00582 //      signature (key) and a data element to which the key is mapped.
00583 //
00584 //  4)  The hash function is provided by the user as a function object
00585 //      HASH_FUNC on the KEY_TYPE, and equivalence between keys is
00586 //      also provided by a user function object KEY_EQ.
00587 //
00588 // ====================================================================
00589 // ====================================================================
00590 
00591 TEMPLATE_USER_HASH_TABLE
00592 CLASS_USER_HASH_TABLE :: USER_HASH_TABLE
00593   ( UINT32 num_elements, MEM_POOL *pool )
00594 {
00595   typedef HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *pHASH_ELEMENT;
00596 
00597   _pool = pool;
00598   _num_elements = num_elements;
00599   _num_entries = 0;
00600   _data = CXX_NEW_ARRAY ( pHASH_ELEMENT, num_elements, pool );
00601   if ( _data == NULL ) {
00602     ErrMsg ( EC_No_Mem, "USER_HASH_TABLE::USER_HASH_TABLE" );
00603   }
00604   for ( INT i=0; i<num_elements; i++ ) {
00605     _data[i] = (pHASH_ELEMENT) NULL;
00606   }
00607 }
00608 
00609 TEMPLATE_USER_HASH_TABLE
00610 void
00611 CLASS_USER_HASH_TABLE :: Print ( FILE *f )
00612 {
00613   HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *elt;
00614 
00615   for ( INT32 i = 0; i < _num_elements; i++ ) {
00616     if ( _data[i] != NULL ) {
00617       fprintf ( f, "%2d:", i );
00618       elt = _data[i];
00619       while  ( elt != NULL ) {
00620         fprintf ( f, " k%2d:%s:d%d:n0x%06lx",
00621                   _hash(elt->_signature) % _num_elements,
00622                   elt->_signature, elt->_data, elt->_next );
00623         elt = elt->_next;
00624       }
00625       fprintf ( f, "\n" );
00626     }
00627   }
00628 }
00629 
00630 TEMPLATE_USER_HASH_TABLE
00631 void
00632 CLASS_USER_HASH_TABLE :: Enter_If_Unique(KEY_TYPE key, DATA_TYPE data)
00633 { 
00634   typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00635   typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *pHASH_ELEMENT;
00636   pHASH_ELEMENT element = 
00637         CXX_NEW ( THIS_HASH_ELEMENT(key,data), _pool );
00638   UINT32 location = _hash ( key ) % _num_elements;
00639 
00640   if ( element == NULL ) {
00641     ErrMsg ( EC_No_Mem, "USER_HASH_TABLE::Enter_If_Unique" );
00642   }
00643 
00644   if ( _data[location] ) { // something is there
00645     pHASH_ELEMENT iter = _data[location];
00646 
00647     for ( ; iter != NULL ; iter = iter->_next ) {
00648       if ( _equal ( iter->_signature, key ) ) {
00649         return; // not unique
00650       }
00651     }
00652     element->_next = _data[location];
00653   }
00654   _data[location] = element;
00655   _num_entries++;
00656 }
00657 
00658 TEMPLATE_USER_HASH_TABLE
00659 DATA_TYPE
00660 CLASS_USER_HASH_TABLE :: Find ( KEY_TYPE key ) const
00661 {
00662   typedef HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *pHASH_ELEMENT;
00663   HASH hash = _hash(key) % _num_elements;
00664   pHASH_ELEMENT hash_element = _data[hash];
00665 
00666   // fprintf ( TFile, "Find: 0x%08lx %2d 0x%08lx %s\n",
00667   //          key, hash, hash_element, key );
00668   // fflush ( TFile );
00669 
00670   for ( ; hash_element != NULL; hash_element = hash_element->_next ) {
00671     if ( _equal ( hash_element->_signature, key ) ) {
00672       return ( hash_element->_data );
00673     }
00674   }
00675 
00676   return((DATA_TYPE)0);
00677 }
00678 
00679 TEMPLATE_USER_HASH_TABLE
00680 BOOL
00681 USER_HASH_TABLE_ITER < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ > :: Step
00682   ( KEY_TYPE* key, DATA_TYPE* data )
00683 {
00684   if ( _he && _he->_next ) {
00685     _he = _he->_next;
00686     *key = _he->_signature;
00687     *data = _he->_data;
00688     return TRUE;
00689   }
00690     
00691   for ( _loc++; _loc < _hash->Num_Elements(); _loc++ ) {
00692     if ( _hash->Data(_loc) ) {
00693       _he = _hash->Data(_loc);
00694       *key = _he->_signature;
00695       *data = _he->_data;
00696       return TRUE;
00697     }
00698   }
00699 
00700   return FALSE;
00701 }
00702 #endif /* cxx_hash_INCLUDED */
00703 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines