| 2 |      1 | /*
 | 
|  |      2 | ** 2001 September 22
 | 
|  |      3 | **
 | 
|  |      4 | ** The author disclaims copyright to this source code.  In place of
 | 
|  |      5 | ** a legal notice, here is a blessing:
 | 
|  |      6 | **
 | 
|  |      7 | **    May you do good and not evil.
 | 
|  |      8 | **    May you find forgiveness for yourself and forgive others.
 | 
|  |      9 | **    May you share freely, never taking more than you give.
 | 
|  |     10 | **
 | 
|  |     11 | *************************************************************************
 | 
|  |     12 | ** This is the implementation of generic hash-tables
 | 
|  |     13 | ** used in SQLite.
 | 
|  |     14 | **
 | 
|  |     15 | ** $Id: hash.cpp 1282 2008-11-13 09:31:33Z LarsPson $
 | 
|  |     16 | */
 | 
|  |     17 | #include "sqliteInt.h"
 | 
|  |     18 | #include <assert.h>
 | 
|  |     19 | 
 | 
|  |     20 | /* Turn bulk memory into a hash table object by initializing the
 | 
|  |     21 | ** fields of the Hash structure.
 | 
|  |     22 | **
 | 
|  |     23 | ** "pNew" is a pointer to the hash table that is to be initialized.
 | 
|  |     24 | ** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
 | 
|  |     25 | ** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING.  The value of keyClass 
 | 
|  |     26 | ** determines what kind of key the hash table will use.  "copyKey" is
 | 
|  |     27 | ** true if the hash table should make its own private copy of keys and
 | 
|  |     28 | ** false if it should just use the supplied pointer.  CopyKey only makes
 | 
|  |     29 | ** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
 | 
|  |     30 | ** for other key classes.
 | 
|  |     31 | */
 | 
|  |     32 | void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
 | 
|  |     33 |   assert( pNew!=0 );
 | 
|  |     34 |   assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
 | 
|  |     35 |   pNew->keyClass = keyClass;
 | 
|  |     36 | #if 0
 | 
|  |     37 |   if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
 | 
|  |     38 | #endif
 | 
|  |     39 |   pNew->copyKey = copyKey;
 | 
|  |     40 |   pNew->first = 0;
 | 
|  |     41 |   pNew->count = 0;
 | 
|  |     42 |   pNew->htsize = 0;
 | 
|  |     43 |   pNew->ht = 0;
 | 
|  |     44 | }
 | 
|  |     45 | 
 | 
|  |     46 | /* Remove all entries from a hash table.  Reclaim all memory.
 | 
|  |     47 | ** Call this routine to delete a hash table or to reset a hash table
 | 
|  |     48 | ** to the empty state.
 | 
|  |     49 | */
 | 
|  |     50 | void sqlite3HashClear(Hash *pH){
 | 
|  |     51 |   HashElem *elem;         /* For looping over all elements of the table */
 | 
|  |     52 | 
 | 
|  |     53 |   assert( pH!=0 );
 | 
|  |     54 |   elem = pH->first;
 | 
|  |     55 |   pH->first = 0;
 | 
|  |     56 |   if( pH->ht ) sqlite3_free(pH->ht);
 | 
|  |     57 |   pH->ht = 0;
 | 
|  |     58 |   pH->htsize = 0;
 | 
|  |     59 |   while( elem ){
 | 
|  |     60 |     HashElem *next_elem = elem->next;
 | 
|  |     61 |     if( pH->copyKey && elem->pKey ){
 | 
|  |     62 |       sqlite3_free(elem->pKey);
 | 
|  |     63 |     }
 | 
|  |     64 |     sqlite3_free(elem);
 | 
|  |     65 |     elem = next_elem;
 | 
|  |     66 |   }
 | 
|  |     67 |   pH->count = 0;
 | 
|  |     68 | }
 | 
|  |     69 | 
 | 
|  |     70 | #if 0 /* NOT USED */
 | 
|  |     71 | /*
 | 
|  |     72 | ** Hash and comparison functions when the mode is SQLITE_HASH_INT
 | 
|  |     73 | */
 | 
|  |     74 | static int intHash(const void *pKey, int nKey){
 | 
|  |     75 |   return nKey ^ (nKey<<8) ^ (nKey>>8);
 | 
|  |     76 | }
 | 
|  |     77 | static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
 | 
|  |     78 |   return n2 - n1;
 | 
|  |     79 | }
 | 
|  |     80 | #endif
 | 
|  |     81 | 
 | 
|  |     82 | #if 0 /* NOT USED */
 | 
|  |     83 | /*
 | 
|  |     84 | ** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
 | 
|  |     85 | */
 | 
|  |     86 | static int ptrHash(const void *pKey, int nKey){
 | 
|  |     87 |   uptr x = Addr(pKey);
 | 
|  |     88 |   return x ^ (x<<8) ^ (x>>8);
 | 
|  |     89 | }
 | 
|  |     90 | static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
 | 
|  |     91 |   if( pKey1==pKey2 ) return 0;
 | 
|  |     92 |   if( pKey1<pKey2 ) return -1;
 | 
|  |     93 |   return 1;
 | 
|  |     94 | }
 | 
|  |     95 | #endif
 | 
|  |     96 | 
 | 
|  |     97 | /*
 | 
|  |     98 | ** Hash and comparison functions when the mode is SQLITE_HASH_STRING
 | 
|  |     99 | */
 | 
|  |    100 | static int strHash(const void *pKey, int nKey){
 | 
|  |    101 |   const char *z = (const char *)pKey;
 | 
|  |    102 |   int h = 0;
 | 
|  |    103 |   if( nKey<=0 ) nKey = strlen(z);
 | 
|  |    104 |   while( nKey > 0  ){
 | 
|  |    105 |     h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
 | 
|  |    106 |     nKey--;
 | 
|  |    107 |   }
 | 
|  |    108 |   return h & 0x7fffffff;
 | 
|  |    109 | }
 | 
|  |    110 | static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
 | 
|  |    111 |   if( n1!=n2 ) return 1;
 | 
|  |    112 |   return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
 | 
|  |    113 | }
 | 
|  |    114 | 
 | 
|  |    115 | /*
 | 
|  |    116 | ** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
 | 
|  |    117 | */
 | 
|  |    118 | static int binHash(const void *pKey, int nKey){
 | 
|  |    119 |   int h = 0;
 | 
|  |    120 |   const char *z = (const char *)pKey;
 | 
|  |    121 |   while( nKey-- > 0 ){
 | 
|  |    122 |     h = (h<<3) ^ h ^ *(z++);
 | 
|  |    123 |   }
 | 
|  |    124 |   return h & 0x7fffffff;
 | 
|  |    125 | }
 | 
|  |    126 | static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
 | 
|  |    127 |   if( n1!=n2 ) return 1;
 | 
|  |    128 |   return memcmp(pKey1,pKey2,n1);
 | 
|  |    129 | }
 | 
|  |    130 | 
 | 
|  |    131 | /*
 | 
|  |    132 | ** Return a pointer to the appropriate hash function given the key class.
 | 
|  |    133 | **
 | 
|  |    134 | ** The C syntax in this function definition may be unfamilar to some 
 | 
|  |    135 | ** programmers, so we provide the following additional explanation:
 | 
|  |    136 | **
 | 
|  |    137 | ** The name of the function is "hashFunction".  The function takes a
 | 
|  |    138 | ** single parameter "keyClass".  The return value of hashFunction()
 | 
|  |    139 | ** is a pointer to another function.  Specifically, the return value
 | 
|  |    140 | ** of hashFunction() is a pointer to a function that takes two parameters
 | 
|  |    141 | ** with types "const void*" and "int" and returns an "int".
 | 
|  |    142 | */
 | 
|  |    143 | static int (*hashFunction(int keyClass))(const void*,int){
 | 
|  |    144 | #if 0  /* HASH_INT and HASH_POINTER are never used */
 | 
|  |    145 |   switch( keyClass ){
 | 
|  |    146 |     case SQLITE_HASH_INT:     return &intHash;
 | 
|  |    147 |     case SQLITE_HASH_POINTER: return &ptrHash;
 | 
|  |    148 |     case SQLITE_HASH_STRING:  return &strHash;
 | 
|  |    149 |     case SQLITE_HASH_BINARY:  return &binHash;;
 | 
|  |    150 |     default: break;
 | 
|  |    151 |   }
 | 
|  |    152 |   return 0;
 | 
|  |    153 | #else
 | 
|  |    154 |   if( keyClass==SQLITE_HASH_STRING ){
 | 
|  |    155 |     return &strHash;
 | 
|  |    156 |   }else{
 | 
|  |    157 |     assert( keyClass==SQLITE_HASH_BINARY );
 | 
|  |    158 |     return &binHash;
 | 
|  |    159 |   }
 | 
|  |    160 | #endif
 | 
|  |    161 | }
 | 
|  |    162 | 
 | 
|  |    163 | /*
 | 
|  |    164 | ** Return a pointer to the appropriate hash function given the key class.
 | 
|  |    165 | **
 | 
|  |    166 | ** For help in interpreted the obscure C code in the function definition,
 | 
|  |    167 | ** see the header comment on the previous function.
 | 
|  |    168 | */
 | 
|  |    169 | static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
 | 
|  |    170 | #if 0 /* HASH_INT and HASH_POINTER are never used */
 | 
|  |    171 |   switch( keyClass ){
 | 
|  |    172 |     case SQLITE_HASH_INT:     return &intCompare;
 | 
|  |    173 |     case SQLITE_HASH_POINTER: return &ptrCompare;
 | 
|  |    174 |     case SQLITE_HASH_STRING:  return &strCompare;
 | 
|  |    175 |     case SQLITE_HASH_BINARY:  return &binCompare;
 | 
|  |    176 |     default: break;
 | 
|  |    177 |   }
 | 
|  |    178 |   return 0;
 | 
|  |    179 | #else
 | 
|  |    180 |   if( keyClass==SQLITE_HASH_STRING ){
 | 
|  |    181 |     return &strCompare;
 | 
|  |    182 |   }else{
 | 
|  |    183 |     assert( keyClass==SQLITE_HASH_BINARY );
 | 
|  |    184 |     return &binCompare;
 | 
|  |    185 |   }
 | 
|  |    186 | #endif
 | 
|  |    187 | }
 | 
|  |    188 | 
 | 
|  |    189 | /* Link an element into the hash table
 | 
|  |    190 | */
 | 
|  |    191 | static void insertElement(
 | 
|  |    192 |   Hash *pH,              /* The complete hash table */
 | 
|  |    193 |   Hash::_ht *pEntry,    /* The entry into which pNew is inserted */
 | 
|  |    194 |   HashElem *pNew         /* The element to be inserted */
 | 
|  |    195 | ){
 | 
|  |    196 |   HashElem *pHead;       /* First element already in pEntry */
 | 
|  |    197 |   pHead = pEntry->chain;
 | 
|  |    198 |   if( pHead ){
 | 
|  |    199 |     pNew->next = pHead;
 | 
|  |    200 |     pNew->prev = pHead->prev;
 | 
|  |    201 |     if( pHead->prev ){ pHead->prev->next = pNew; }
 | 
|  |    202 |     else             { pH->first = pNew; }
 | 
|  |    203 |     pHead->prev = pNew;
 | 
|  |    204 |   }else{
 | 
|  |    205 |     pNew->next = pH->first;
 | 
|  |    206 |     if( pH->first ){ pH->first->prev = pNew; }
 | 
|  |    207 |     pNew->prev = 0;
 | 
|  |    208 |     pH->first = pNew;
 | 
|  |    209 |   }
 | 
|  |    210 |   pEntry->count++;
 | 
|  |    211 |   pEntry->chain = pNew;
 | 
|  |    212 | }
 | 
|  |    213 | 
 | 
|  |    214 | 
 | 
|  |    215 | /* Resize the hash table so that it cantains "new_size" buckets.
 | 
|  |    216 | ** "new_size" must be a power of 2.  The hash table might fail 
 | 
|  |    217 | ** to resize if sqlite3_malloc() fails.
 | 
|  |    218 | */
 | 
|  |    219 | static void rehash(Hash *pH, int new_size){
 | 
|  |    220 |   Hash::_ht *new_ht;            /* The new hash table */
 | 
|  |    221 |   HashElem *elem, *next_elem;    /* For looping over existing elements */
 | 
|  |    222 |   int (*xHash)(const void*,int); /* The hash function */
 | 
|  |    223 | 
 | 
|  |    224 |   assert( (new_size & (new_size-1))==0 );
 | 
|  |    225 | 
 | 
|  |    226 |   /* There is a call to sqlite3_malloc() inside rehash(). If there is
 | 
|  |    227 |   ** already an allocation at pH->ht, then if this malloc() fails it
 | 
|  |    228 |   ** is benign (since failing to resize a hash table is a performance
 | 
|  |    229 |   ** hit only, not a fatal error).
 | 
|  |    230 |   */
 | 
|  |    231 |   sqlite3MallocBenignFailure(pH->htsize>0);
 | 
|  |    232 | 
 | 
|  |    233 |   new_ht = (Hash::_ht *)sqlite3MallocZero( new_size*sizeof(Hash::_ht) );
 | 
|  |    234 |   if( new_ht==0 ) return;
 | 
|  |    235 |   if( pH->ht ) sqlite3_free(pH->ht);
 | 
|  |    236 |   pH->ht = new_ht;
 | 
|  |    237 |   pH->htsize = new_size;
 | 
|  |    238 |   xHash = hashFunction(pH->keyClass);
 | 
|  |    239 |   for(elem=pH->first, pH->first=0; elem; elem = next_elem){
 | 
|  |    240 |     int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
 | 
|  |    241 |     next_elem = elem->next;
 | 
|  |    242 |     insertElement(pH, &new_ht[h], elem);
 | 
|  |    243 |   }
 | 
|  |    244 | }
 | 
|  |    245 | 
 | 
|  |    246 | /* This function (for internal use only) locates an element in an
 | 
|  |    247 | ** hash table that matches the given key.  The hash for this key has
 | 
|  |    248 | ** already been computed and is passed as the 4th parameter.
 | 
|  |    249 | */
 | 
|  |    250 | static HashElem *findElementGivenHash(
 | 
|  |    251 |   const Hash *pH,     /* The pH to be searched */
 | 
|  |    252 |   const void *pKey,   /* The key we are searching for */
 | 
|  |    253 |   int nKey,
 | 
|  |    254 |   int h               /* The hash for this key. */
 | 
|  |    255 | ){
 | 
|  |    256 |   HashElem *elem;                /* Used to loop thru the element list */
 | 
|  |    257 |   int count;                     /* Number of elements left to test */
 | 
|  |    258 |   int (*xCompare)(const void*,int,const void*,int);  /* comparison function */
 | 
|  |    259 | 
 | 
|  |    260 |   if( pH->ht ){
 | 
|  |    261 | 	  Hash::_ht *pEntry = &pH->ht[h];
 | 
|  |    262 |     elem = pEntry->chain;
 | 
|  |    263 |     count = pEntry->count;
 | 
|  |    264 |     xCompare = compareFunction(pH->keyClass);
 | 
|  |    265 |     while( count-- && elem ){
 | 
|  |    266 |       if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
 | 
|  |    267 |         return elem;
 | 
|  |    268 |       }
 | 
|  |    269 |       elem = elem->next;
 | 
|  |    270 |     }
 | 
|  |    271 |   }
 | 
|  |    272 |   return 0;
 | 
|  |    273 | }
 | 
|  |    274 | 
 | 
|  |    275 | /* Remove a single entry from the hash table given a pointer to that
 | 
|  |    276 | ** element and a hash on the element's key.
 | 
|  |    277 | */
 | 
|  |    278 | static void removeElementGivenHash(
 | 
|  |    279 |   Hash *pH,         /* The pH containing "elem" */
 | 
|  |    280 |   HashElem* elem,   /* The element to be removed from the pH */
 | 
|  |    281 |   int h             /* Hash value for the element */
 | 
|  |    282 | ){
 | 
|  |    283 | 	Hash::_ht *pEntry;
 | 
|  |    284 |   if( elem->prev ){
 | 
|  |    285 |     elem->prev->next = elem->next; 
 | 
|  |    286 |   }else{
 | 
|  |    287 |     pH->first = elem->next;
 | 
|  |    288 |   }
 | 
|  |    289 |   if( elem->next ){
 | 
|  |    290 |     elem->next->prev = elem->prev;
 | 
|  |    291 |   }
 | 
|  |    292 |   pEntry = &pH->ht[h];
 | 
|  |    293 |   if( pEntry->chain==elem ){
 | 
|  |    294 |     pEntry->chain = elem->next;
 | 
|  |    295 |   }
 | 
|  |    296 |   pEntry->count--;
 | 
|  |    297 |   if( pEntry->count<=0 ){
 | 
|  |    298 |     pEntry->chain = 0;
 | 
|  |    299 |   }
 | 
|  |    300 |   if( pH->copyKey ){
 | 
|  |    301 |     sqlite3_free(elem->pKey);
 | 
|  |    302 |   }
 | 
|  |    303 |   sqlite3_free( elem );
 | 
|  |    304 |   pH->count--;
 | 
|  |    305 |   if( pH->count<=0 ){
 | 
|  |    306 |     assert( pH->first==0 );
 | 
|  |    307 |     assert( pH->count==0 );
 | 
|  |    308 |     sqlite3HashClear(pH);
 | 
|  |    309 |   }
 | 
|  |    310 | }
 | 
|  |    311 | 
 | 
|  |    312 | /* Attempt to locate an element of the hash table pH with a key
 | 
|  |    313 | ** that matches pKey,nKey.  Return a pointer to the corresponding 
 | 
|  |    314 | ** HashElem structure for this element if it is found, or NULL
 | 
|  |    315 | ** otherwise.
 | 
|  |    316 | */
 | 
|  |    317 | HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){
 | 
|  |    318 |   int h;             /* A hash on key */
 | 
|  |    319 |   HashElem *elem;    /* The element that matches key */
 | 
|  |    320 |   int (*xHash)(const void*,int);  /* The hash function */
 | 
|  |    321 | 
 | 
|  |    322 |   if( pH==0 || pH->ht==0 ) return 0;
 | 
|  |    323 |   xHash = hashFunction(pH->keyClass);
 | 
|  |    324 |   assert( xHash!=0 );
 | 
|  |    325 |   h = (*xHash)(pKey,nKey);
 | 
|  |    326 |   assert( (pH->htsize & (pH->htsize-1))==0 );
 | 
|  |    327 |   elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
 | 
|  |    328 |   return elem;
 | 
|  |    329 | }
 | 
|  |    330 | 
 | 
|  |    331 | /* Attempt to locate an element of the hash table pH with a key
 | 
|  |    332 | ** that matches pKey,nKey.  Return the data for this element if it is
 | 
|  |    333 | ** found, or NULL if there is no match.
 | 
|  |    334 | */
 | 
|  |    335 | void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
 | 
|  |    336 |   HashElem *elem;    /* The element that matches key */
 | 
|  |    337 |   elem = sqlite3HashFindElem(pH, pKey, nKey);
 | 
|  |    338 |   return elem ? elem->data : 0;
 | 
|  |    339 | }
 | 
|  |    340 | 
 | 
|  |    341 | /* Insert an element into the hash table pH.  The key is pKey,nKey
 | 
|  |    342 | ** and the data is "data".
 | 
|  |    343 | **
 | 
|  |    344 | ** If no element exists with a matching key, then a new
 | 
|  |    345 | ** element is created.  A copy of the key is made if the copyKey
 | 
|  |    346 | ** flag is set.  NULL is returned.
 | 
|  |    347 | **
 | 
|  |    348 | ** If another element already exists with the same key, then the
 | 
|  |    349 | ** new data replaces the old data and the old data is returned.
 | 
|  |    350 | ** The key is not copied in this instance.  If a malloc fails, then
 | 
|  |    351 | ** the new data is returned and the hash table is unchanged.
 | 
|  |    352 | **
 | 
|  |    353 | ** If the "data" parameter to this function is NULL, then the
 | 
|  |    354 | ** element corresponding to "key" is removed from the hash table.
 | 
|  |    355 | */
 | 
|  |    356 | void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
 | 
|  |    357 |   int hraw;             /* Raw hash value of the key */
 | 
|  |    358 |   int h;                /* the hash of the key modulo hash table size */
 | 
|  |    359 |   HashElem *elem;       /* Used to loop thru the element list */
 | 
|  |    360 |   HashElem *new_elem;   /* New element added to the pH */
 | 
|  |    361 |   int (*xHash)(const void*,int);  /* The hash function */
 | 
|  |    362 | 
 | 
|  |    363 |   assert( pH!=0 );
 | 
|  |    364 |   xHash = hashFunction(pH->keyClass);
 | 
|  |    365 |   assert( xHash!=0 );
 | 
|  |    366 |   hraw = (*xHash)(pKey, nKey);
 | 
|  |    367 |   assert( (pH->htsize & (pH->htsize-1))==0 );
 | 
|  |    368 |   h = hraw & (pH->htsize-1);
 | 
|  |    369 |   elem = findElementGivenHash(pH,pKey,nKey,h);
 | 
|  |    370 |   if( elem ){
 | 
|  |    371 |     void *old_data = elem->data;
 | 
|  |    372 |     if( data==0 ){
 | 
|  |    373 |       removeElementGivenHash(pH,elem,h);
 | 
|  |    374 |     }else{
 | 
|  |    375 |       elem->data = data;
 | 
|  |    376 |       if( !pH->copyKey ){
 | 
|  |    377 |         elem->pKey = (void *)pKey;
 | 
|  |    378 |       }
 | 
|  |    379 |       assert(nKey==elem->nKey);
 | 
|  |    380 |     }
 | 
|  |    381 |     return old_data;
 | 
|  |    382 |   }
 | 
|  |    383 |   if( data==0 ) return 0;
 | 
|  |    384 |   new_elem = (HashElem*)sqlite3_malloc( sizeof(HashElem) );
 | 
|  |    385 |   if( new_elem==0 ) return data;
 | 
|  |    386 |   if( pH->copyKey && pKey!=0 ){
 | 
|  |    387 |     new_elem->pKey = sqlite3_malloc( nKey );
 | 
|  |    388 |     if( new_elem->pKey==0 ){
 | 
|  |    389 |       sqlite3_free(new_elem);
 | 
|  |    390 |       return data;
 | 
|  |    391 |     }
 | 
|  |    392 |     memcpy((void*)new_elem->pKey, pKey, nKey);
 | 
|  |    393 |   }else{
 | 
|  |    394 |     new_elem->pKey = (void*)pKey;
 | 
|  |    395 |   }
 | 
|  |    396 |   new_elem->nKey = nKey;
 | 
|  |    397 |   pH->count++;
 | 
|  |    398 |   if( pH->htsize==0 ){
 | 
|  |    399 |     rehash(pH,8);
 | 
|  |    400 |     if( pH->htsize==0 ){
 | 
|  |    401 |       pH->count = 0;
 | 
|  |    402 |       if( pH->copyKey ){
 | 
|  |    403 |         sqlite3_free(new_elem->pKey);
 | 
|  |    404 |       }
 | 
|  |    405 |       sqlite3_free(new_elem);
 | 
|  |    406 |       return data;
 | 
|  |    407 |     }
 | 
|  |    408 |   }
 | 
|  |    409 |   if( pH->count > pH->htsize ){
 | 
|  |    410 |     rehash(pH,pH->htsize*2);
 | 
|  |    411 |   }
 | 
|  |    412 |   assert( pH->htsize>0 );
 | 
|  |    413 |   assert( (pH->htsize & (pH->htsize-1))==0 );
 | 
|  |    414 |   h = hraw & (pH->htsize-1);
 | 
|  |    415 |   insertElement(pH, &pH->ht[h], new_elem);
 | 
|  |    416 |   new_elem->data = data;
 | 
|  |    417 |   return 0;
 | 
|  |    418 | }
 |