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 #include <string.h>
00032 #include <stddef.h>
00033
00034 #ifndef UTHASH_H
00035 #define UTHASH_H
00036
00037 #define uthash_fatal(msg) exit(-1)
00038 #define uthash_bkt_malloc(sz) malloc(sz)
00039 #define uthash_bkt_free(ptr) free(ptr)
00040 #define uthash_tbl_malloc(sz) malloc(sz)
00041 #define uthash_tbl_free(ptr) free(ptr)
00042
00043 #define uthash_noexpand_fyi(tbl)
00044 #define uthash_expand_fyi(tbl)
00045
00046
00047 #define HASH_INITIAL_NUM_BUCKETS 32
00048 #define HASH_INITIAL_NUM_BUCKETS_LOG2 5
00049 #define HASH_BKT_CAPACITY_THRESH 10
00050
00051 #define HASH_FIND(hh,head,keyptr,keylen_in,out) \
00052 do { \
00053 out=head; \
00054 if (head) { \
00055 (head)->hh.tbl->key = (char*)(keyptr); \
00056 (head)->hh.tbl->keylen = keylen_in; \
00057 HASH_FCN((head)->hh.tbl->key,(head)->hh.tbl->keylen, \
00058 (head)->hh.tbl->num_buckets, \
00059 (head)->hh.tbl->hash_scratch, (head)->hh.tbl->bkt, \
00060 (head)->hh.tbl->i, (head)->hh.tbl->j,(head)->hh.tbl->k); \
00061 HASH_FIND_IN_BKT(hh, (head)->hh.tbl->buckets[ (head)->hh.tbl->bkt], \
00062 keyptr,keylen_in,out); \
00063 } \
00064 } while (0)
00065
00066 #define HASH_ADD(hh,head,fieldname,keylen_in,add) \
00067 HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
00068
00069 #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
00070 do { \
00071 add->hh.next = NULL; \
00072 add->hh.key = (char*)keyptr; \
00073 add->hh.keylen = keylen_in; \
00074 add->hh.elmt = add; \
00075 if (!(head)) { \
00076 head = add; \
00077 (head)->hh.prev = NULL; \
00078 (head)->hh.tbl = (UT_hash_table*)uthash_tbl_malloc( \
00079 sizeof(UT_hash_table)); \
00080 if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
00081 memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
00082 (head)->hh.tbl->tail = &(add->hh); \
00083 (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
00084 (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
00085 (head)->hh.tbl->hho = (void*)(&add->hh) - (void*)(add); \
00086 (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_bkt_malloc( \
00087 HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
00088 if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
00089 memset((head)->hh.tbl->buckets, 0, \
00090 HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
00091 } else { \
00092 (head)->hh.tbl->tail->next = add; \
00093 add->hh.prev = (head)->hh.tbl->tail->elmt; \
00094 (head)->hh.tbl->tail = &(add->hh); \
00095 } \
00096 (head)->hh.tbl->num_items++; \
00097 add->hh.tbl = (head)->hh.tbl; \
00098 (head)->hh.tbl->key = (char*)keyptr; \
00099 (head)->hh.tbl->keylen = keylen_in; \
00100 HASH_FCN((head)->hh.tbl->key,(head)->hh.tbl->keylen, \
00101 (head)->hh.tbl->num_buckets, \
00102 (add)->hh.hashv, \
00103 (head)->hh.tbl->bkt, \
00104 (head)->hh.tbl->i, (head)->hh.tbl->j, (head)->hh.tbl->k ); \
00105 HASH_ADD_TO_BKT(hh,(head)->hh.tbl->buckets[(head)->hh.tbl->bkt],add); \
00106 HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
00107 HASH_FSCK(hh,head); \
00108 } while(0)
00109
00110 #define HASH_TO_BKT( hashv, num_bkts, bkt ) bkt = ((hashv) & ((num_bkts) - 1))
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 #define HASH_DELETE(hh,head,delptr) \
00125 do { \
00126 if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
00127 uthash_bkt_free((head)->hh.tbl->buckets ); \
00128 uthash_tbl_free((head)->hh.tbl); \
00129 head = NULL; \
00130 } else { \
00131 (head)->hh.tbl->hh_del = &((delptr)->hh); \
00132 if ((delptr) == (head)->hh.tbl->tail->elmt) { \
00133 (head)->hh.tbl->tail = (void*)(((delptr)->hh.prev) + \
00134 (head)->hh.tbl->hho); \
00135 } \
00136 if ((delptr)->hh.prev) { \
00137 ((UT_hash_handle*)(((delptr)->hh.prev) + \
00138 (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
00139 } else { \
00140 head = (delptr)->hh.next; \
00141 } \
00142 if ((head)->hh.tbl->hh_del->next) { \
00143 ((UT_hash_handle*)((head)->hh.tbl->hh_del->next + \
00144 (head)->hh.tbl->hho))->prev = \
00145 (head)->hh.tbl->hh_del->prev; \
00146 } \
00147 HASH_TO_BKT( (head)->hh.tbl->hh_del->hashv, \
00148 (head)->hh.tbl->num_buckets, \
00149 (head)->hh.tbl->bkt); \
00150 HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[(head)->hh.tbl->bkt], \
00151 (head)->hh.tbl->hh_del); \
00152 (head)->hh.tbl->num_items--; \
00153 } \
00154 HASH_FSCK(hh,head); \
00155 } while (0)
00156
00157
00158
00159 #define HASH_FIND_STR(head,findstr,out) \
00160 HASH_FIND(hh,head,findstr,strlen(findstr),out)
00161 #define HASH_ADD_STR(head,strfield,add) \
00162 HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
00163 #define HASH_FIND_INT(head,findint,out) \
00164 HASH_FIND(hh,head,findint,sizeof(int),out)
00165 #define HASH_ADD_INT(head,intfield,add) \
00166 HASH_ADD(hh,head,intfield,sizeof(int),add)
00167 #define HASH_DEL(head,delptr) \
00168 HASH_DELETE(hh,head,delptr)
00169
00170
00171
00172
00173
00174 #ifdef HASH_DEBUG
00175 #define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
00176 #define HASH_FSCK(hh,head) \
00177 do { \
00178 if (head) { \
00179 (head)->hh.tbl->keylen = 0; \
00180 for( (head)->hh.tbl->bkt_i = 0; \
00181 (head)->hh.tbl->bkt_i < (head)->hh.tbl->num_buckets; \
00182 (head)->hh.tbl->bkt_i++) \
00183 { \
00184 (head)->hh.tbl->ideal_chain_maxlen = 0; \
00185 (head)->hh.tbl->thh = \
00186 (head)->hh.tbl->buckets[(head)->hh.tbl->bkt_i].hh_head; \
00187 (head)->hh.tbl->key = NULL; \
00188 while ((head)->hh.tbl->thh) { \
00189 if ((head)->hh.tbl->key != \
00190 (char*)((head)->hh.tbl->thh->hh_prev)) { \
00191 HASH_OOPS("invalid hh_prev %x, actual %x\n", \
00192 (head)->hh.tbl->thh->hh_prev, \
00193 (head)->hh.tbl->key ); \
00194 } \
00195 (head)->hh.tbl->ideal_chain_maxlen++; \
00196 (head)->hh.tbl->key = (char*)((head)->hh.tbl->thh); \
00197 (head)->hh.tbl->thh = (head)->hh.tbl->thh->hh_next; \
00198 } \
00199 (head)->hh.tbl->keylen += \
00200 (head)->hh.tbl->ideal_chain_maxlen; \
00201 if ((head)->hh.tbl->buckets[(head)->hh.tbl->bkt_i].count \
00202 != (head)->hh.tbl->ideal_chain_maxlen) { \
00203 HASH_OOPS("invalid bucket count %d, actual %d\n", \
00204 (head)->hh.tbl->buckets[(head)->hh.tbl->bkt_i].count, \
00205 (head)->hh.tbl->ideal_chain_maxlen); \
00206 } \
00207 } \
00208 if ((head)->hh.tbl->keylen != (head)->hh.tbl->num_items) { \
00209 HASH_OOPS("invalid hh item count %d, actual %d\n", \
00210 (head)->hh.tbl->num_items, (head)->hh.tbl->keylen ); \
00211 } \
00212 \
00213 (head)->hh.tbl->keylen = 0; \
00214 (head)->hh.tbl->key = NULL; \
00215 (head)->hh.tbl->thh = &(head)->hh; \
00216 while ((head)->hh.tbl->thh) { \
00217 (head)->hh.tbl->keylen++; \
00218 if ((head)->hh.tbl->key !=(char*)((head)->hh.tbl->thh->prev)) { \
00219 HASH_OOPS("invalid prev %x, actual %x\n", \
00220 (head)->hh.tbl->thh->prev, \
00221 (head)->hh.tbl->key ); \
00222 } \
00223 (head)->hh.tbl->key = (head)->hh.tbl->thh->elmt; \
00224 (head)->hh.tbl->thh = ( (head)->hh.tbl->thh->next ? \
00225 (UT_hash_handle*)(((head)->hh.tbl->thh->next) + \
00226 (head)->hh.tbl->hho) \
00227 : NULL ); \
00228 } \
00229 if ((head)->hh.tbl->keylen != (head)->hh.tbl->num_items) { \
00230 HASH_OOPS("invalid app item count %d, actual %d\n", \
00231 (head)->hh.tbl->num_items, (head)->hh.tbl->keylen ); \
00232 } \
00233 } \
00234 } while (0)
00235 #else
00236 #define HASH_FSCK(hh,head)
00237 #endif
00238
00239
00240
00241
00242 #ifdef HASH_EMIT_KEYS
00243 #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
00244 (head)->hh.tbl->keylen = fieldlen; \
00245 write(HASH_EMIT_KEYS, &((head)->hh.tbl->keylen), sizeof(int)); \
00246 write(HASH_EMIT_KEYS, keyptr, fieldlen);
00247 #else
00248 #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
00249 #endif
00250
00251
00252 #ifdef HASH_FUNCTION
00253 #define HASH_FCN HASH_FUNCTION
00254 #else
00255 #define HASH_FCN HASH_JEN
00256 #endif
00257
00258
00259 #define HASH_BER(key,keylen,num_bkts,hash,bkt,i,j,k) \
00260 hash = 0; \
00261 while (keylen--) hash = (hash * 33) + *key++; \
00262 bkt = hash & (num_bkts-1);
00263
00264
00265
00266
00267 #define HASH_SAX(key,keylen,num_bkts,hash,bkt,i,j,k) \
00268 hash = 0; \
00269 for(i=0; i < keylen; i++) \
00270 hash ^= (hash << 5) + (hash >> 2) + key[i]; \
00271 bkt = hash & (num_bkts-1);
00272
00273 #define HASH_FNV(key,keylen,num_bkts,hash,bkt,i,j,k) \
00274 hash = 2166136261UL; \
00275 for(i=0; i < keylen; i++) \
00276 hash = (hash * 16777619) ^ key[i]; \
00277 bkt = hash & (num_bkts-1);
00278
00279 #define HASH_OAT(key,keylen,num_bkts,hash,bkt,i,j,k) \
00280 hash = 0; \
00281 for(i=0; i < keylen; i++) { \
00282 hash += key[i]; \
00283 hash += (hash << 10); \
00284 hash ^= (hash >> 6); \
00285 } \
00286 hash += (hash << 3); \
00287 hash ^= (hash >> 11); \
00288 hash += (hash << 15); \
00289 bkt = hash & (num_bkts-1);
00290
00291 #define HASH_JEN_MIX(a,b,c) \
00292 { \
00293 a -= b; a -= c; a ^= ( c >> 13 ); \
00294 b -= c; b -= a; b ^= ( a << 8 ); \
00295 c -= a; c -= b; c ^= ( b >> 13 ); \
00296 a -= b; a -= c; a ^= ( c >> 12 ); \
00297 b -= c; b -= a; b ^= ( a << 16 ); \
00298 c -= a; c -= b; c ^= ( b >> 5 ); \
00299 a -= b; a -= c; a ^= ( c >> 3 ); \
00300 b -= c; b -= a; b ^= ( a << 10 ); \
00301 c -= a; c -= b; c ^= ( b >> 15 ); \
00302 }
00303
00304 #define HASH_JEN(key,keylen,num_bkts,hash,bkt,i,j,k) \
00305 hash = 0xfeedbeef; \
00306 i = j = 0x9e3779b9; \
00307 k = keylen; \
00308 while (k >= 12) { \
00309 i += (key[0] + ( (unsigned)key[1] << 8 ) \
00310 + ( (unsigned)key[2] << 16 ) \
00311 + ( (unsigned)key[3] << 24 ) ); \
00312 j += (key[4] + ( (unsigned)key[5] << 8 ) \
00313 + ( (unsigned)key[6] << 16 ) \
00314 + ( (unsigned)key[7] << 24 ) ); \
00315 hash += (key[8] + ( (unsigned)key[9] << 8 ) \
00316 + ( (unsigned)key[10] << 16 ) \
00317 + ( (unsigned)key[11] << 24 ) ); \
00318 \
00319 HASH_JEN_MIX(i, j, hash); \
00320 \
00321 key += 12; \
00322 k -= 12; \
00323 } \
00324 hash += keylen; \
00325 switch ( k ) { \
00326 case 11: hash += ( (unsigned)key[10] << 24 ); \
00327 case 10: hash += ( (unsigned)key[9] << 16 ); \
00328 case 9: hash += ( (unsigned)key[8] << 8 ); \
00329 case 8: j += ( (unsigned)key[7] << 24 ); \
00330 case 7: j += ( (unsigned)key[6] << 16 ); \
00331 case 6: j += ( (unsigned)key[5] << 8 ); \
00332 case 5: j += key[4]; \
00333 case 4: i += ( (unsigned)key[3] << 24 ); \
00334 case 3: i += ( (unsigned)key[2] << 16 ); \
00335 case 2: i += ( (unsigned)key[1] << 8 ); \
00336 case 1: i += key[0]; \
00337 } \
00338 HASH_JEN_MIX(i, j, hash); \
00339 bkt = hash & (num_bkts-1);
00340
00341
00342
00343 #define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
00344
00345
00346 #define HASH_FIND_IN_BKT(hh,head,keyptr,keylen_in,out) \
00347 out = (head.hh_head) ? (head.hh_head->elmt) : NULL; \
00348 while (out) { \
00349 if (out->hh.keylen == keylen_in) { \
00350 if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
00351 } \
00352 out= (out->hh.hh_next) ? (out->hh.hh_next->elmt) : NULL; \
00353 }
00354
00355
00356 #define HASH_ADD_TO_BKT(hh,head,add) \
00357 head.count++; \
00358 add->hh.hh_next = head.hh_head; \
00359 add->hh.hh_prev = NULL; \
00360 if (head.hh_head) head.hh_head->hh_prev = &add->hh; \
00361 head.hh_head=&add->hh; \
00362 if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
00363 && add->hh.tbl->noexpand != 1) { \
00364 HASH_EXPAND_BUCKETS(add->hh.tbl) \
00365 }
00366
00367
00368 #define HASH_DEL_IN_BKT(hh,head,hh_del) \
00369 (head).count--; \
00370 if ((head).hh_head->elmt == hh_del->elmt) { \
00371 (head).hh_head = hh_del->hh_next; \
00372 } \
00373 if (hh_del->hh_prev) { \
00374 hh_del->hh_prev->hh_next = hh_del->hh_next; \
00375 } \
00376 if (hh_del->hh_next) { \
00377 hh_del->hh_next->hh_prev = hh_del->hh_prev; \
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 #define HASH_EXPAND_BUCKETS(tbl) \
00412 tbl->new_buckets = (UT_hash_bucket*)uthash_bkt_malloc( \
00413 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
00414 if (!tbl->new_buckets) { uthash_fatal( "out of memory"); } \
00415 memset(tbl->new_buckets, 0, \
00416 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
00417 tbl->ideal_chain_maxlen = \
00418 (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
00419 ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
00420 tbl->nonideal_items = 0; \
00421 for(tbl->bkt_i = 0; tbl->bkt_i < tbl->num_buckets; tbl->bkt_i++) \
00422 { \
00423 tbl->thh = tbl->buckets[ tbl->bkt_i ].hh_head; \
00424 while (tbl->thh) { \
00425 tbl->hh_nxt = tbl->thh->hh_next; \
00426 HASH_TO_BKT( tbl->thh->hashv, tbl->num_buckets*2, tbl->bkt); \
00427 tbl->newbkt = &(tbl->new_buckets[ tbl->bkt ]); \
00428 if (++(tbl->newbkt->count) > tbl->ideal_chain_maxlen) { \
00429 tbl->nonideal_items++; \
00430 tbl->newbkt->expand_mult = tbl->newbkt->count / \
00431 tbl->ideal_chain_maxlen; \
00432 } \
00433 tbl->thh->hh_prev = NULL; \
00434 tbl->thh->hh_next = tbl->newbkt->hh_head; \
00435 if (tbl->newbkt->hh_head) tbl->newbkt->hh_head->hh_prev = \
00436 tbl->thh; \
00437 tbl->newbkt->hh_head = tbl->thh; \
00438 tbl->thh = tbl->hh_nxt; \
00439 } \
00440 } \
00441 tbl->num_buckets *= 2; \
00442 tbl->log2_num_buckets++; \
00443 uthash_bkt_free( tbl->buckets ); \
00444 tbl->buckets = tbl->new_buckets; \
00445 tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) \
00446 ? (tbl->ineff_expands+1) : 0; \
00447 if (tbl->ineff_expands > 1) { \
00448 tbl->noexpand=1; \
00449 uthash_noexpand_fyi(tbl); \
00450 } \
00451 uthash_expand_fyi(tbl);
00452
00453
00454
00455
00456
00457 #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
00458 #define HASH_SRT(hh,head,cmpfcn) \
00459 if (head) { \
00460 (head)->hh.tbl->insize = 1; \
00461 (head)->hh.tbl->looping = 1; \
00462 (head)->hh.tbl->list = &((head)->hh); \
00463 while ((head)->hh.tbl->looping) { \
00464 (head)->hh.tbl->p = (head)->hh.tbl->list; \
00465 (head)->hh.tbl->list = NULL; \
00466 (head)->hh.tbl->tale = NULL; \
00467 (head)->hh.tbl->nmerges = 0; \
00468 while ((head)->hh.tbl->p) { \
00469 (head)->hh.tbl->nmerges++; \
00470 (head)->hh.tbl->q = (head)->hh.tbl->p; \
00471 (head)->hh.tbl->psize = 0; \
00472 for ( (head)->hh.tbl->i = 0; \
00473 (head)->hh.tbl->i < (head)->hh.tbl->insize; \
00474 (head)->hh.tbl->i++ ) { \
00475 (head)->hh.tbl->psize++; \
00476 (head)->hh.tbl->q = (((head)->hh.tbl->q->next) ? \
00477 ((void*)(((head)->hh.tbl->q->next) + \
00478 (head)->hh.tbl->hho)) : NULL); \
00479 if (! ((head)->hh.tbl->q) ) break; \
00480 } \
00481 (head)->hh.tbl->qsize = (head)->hh.tbl->insize; \
00482 while (((head)->hh.tbl->psize > 0) || \
00483 (((head)->hh.tbl->qsize > 0) && (head)->hh.tbl->q )) { \
00484 if ((head)->hh.tbl->psize == 0) { \
00485 (head)->hh.tbl->e = (head)->hh.tbl->q; \
00486 (head)->hh.tbl->q = (((head)->hh.tbl->q->next) ? \
00487 ((void*)(((head)->hh.tbl->q->next) + \
00488 (head)->hh.tbl->hho)) : NULL); \
00489 (head)->hh.tbl->qsize--; \
00490 } else if ( ((head)->hh.tbl->qsize == 0) || \
00491 !((head)->hh.tbl->q) ) { \
00492 (head)->hh.tbl->e = (head)->hh.tbl->p; \
00493 (head)->hh.tbl->p = (((head)->hh.tbl->p->next) ? \
00494 ((void*)(((head)->hh.tbl->p->next) + \
00495 (head)->hh.tbl->hho)) : NULL); \
00496 (head)->hh.tbl->psize--; \
00497 } else if (( \
00498 cmpfcn((head)->hh.tbl->p->elmt,(head)->hh.tbl->q->elmt))\
00499 <= 0) { \
00500 (head)->hh.tbl->e = (head)->hh.tbl->p; \
00501 (head)->hh.tbl->p = (((head)->hh.tbl->p->next) ? \
00502 ((void*)(((head)->hh.tbl->p->next) + \
00503 (head)->hh.tbl->hho)) : NULL); \
00504 (head)->hh.tbl->psize--; \
00505 } else { \
00506 (head)->hh.tbl->e = (head)->hh.tbl->q; \
00507 (head)->hh.tbl->q = (((head)->hh.tbl->q->next) ? \
00508 ((void*)(((head)->hh.tbl->q->next) + \
00509 (head)->hh.tbl->hho)) : NULL); \
00510 (head)->hh.tbl->qsize--; \
00511 } \
00512 if ( (head)->hh.tbl->tale ) { \
00513 (head)->hh.tbl->tale->next = (((head)->hh.tbl->e) ? \
00514 ((head)->hh.tbl->e->elmt) : NULL); \
00515 } else { \
00516 (head)->hh.tbl->list = (head)->hh.tbl->e; \
00517 } \
00518 (head)->hh.tbl->e->prev = (((head)->hh.tbl->tale) ? \
00519 ((head)->hh.tbl->tale->elmt) : NULL); \
00520 (head)->hh.tbl->tale = (head)->hh.tbl->e; \
00521 } \
00522 (head)->hh.tbl->p = (head)->hh.tbl->q; \
00523 } \
00524 (head)->hh.tbl->tale->next = NULL; \
00525 if ( (head)->hh.tbl->nmerges <= 1 ) { \
00526 (head)->hh.tbl->looping=0; \
00527 (head)->hh.tbl->tail = (head)->hh.tbl->tale; \
00528 (head) = (head)->hh.tbl->list->elmt; \
00529 } \
00530 (head)->hh.tbl->insize *= 2; \
00531 } \
00532 HASH_FSCK(hh,head); \
00533 }
00534
00535 typedef struct UT_hash_bucket {
00536 struct UT_hash_handle *hh_head;
00537 unsigned count;
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 unsigned expand_mult;
00552
00553 } UT_hash_bucket;
00554
00555 typedef struct UT_hash_table {
00556 UT_hash_bucket *buckets;
00557 unsigned num_buckets, log2_num_buckets;
00558 unsigned num_items;
00559 struct UT_hash_handle *tail;
00560 ptrdiff_t hho;
00561
00562
00563
00564 unsigned ideal_chain_maxlen;
00565
00566
00567
00568
00569 unsigned nonideal_items;
00570
00571
00572
00573
00574
00575
00576
00577 unsigned ineff_expands, noexpand;
00578
00579
00580 unsigned hash_scratch, bkt, bkt_i, keylen, i, j, k;
00581 char *key;
00582 struct UT_hash_handle *thh, *hh_nxt, *hh_del;
00583
00584
00585 UT_hash_bucket *new_buckets, *newbkt;
00586
00587
00588 int looping,nmerges,insize,psize,qsize;
00589 struct UT_hash_handle *p, *q, *e, *list, *tale;
00590
00591 } UT_hash_table;
00592
00593
00594 typedef struct UT_hash_handle {
00595 struct UT_hash_table *tbl;
00596 void *elmt;
00597 void *prev;
00598 void *next;
00599 struct UT_hash_handle *hh_prev;
00600 struct UT_hash_handle *hh_next;
00601 void *key;
00602 int keylen;
00603 unsigned hashv;
00604 } UT_hash_handle;
00605
00606 #endif