1 /* Martin Asser Hansen (mail@maasha.dk) Copyright (C) 2008 - All right reserved */
9 hash *hash_new( size_t size )
11 /* Martin A. Hansen, June 2008 */
13 /* Initialize a new generic hash structure. */
15 hash *new_hash = NULL;
16 size_t table_size = 0;
18 new_hash = mem_get( sizeof( new_hash ) );
20 table_size = 1 << size; /* table_size = ( 2 ** size ) */
22 new_hash->table_size = table_size;
23 new_hash->mask = table_size - 1;
24 new_hash->table = mem_get( sizeof( hash_elem * ) * table_size );
26 new_hash->index_table = 0;
27 new_hash->index_bucket = mem_get( sizeof( hash_elem ) );
28 new_hash->index_bucket = NULL;
34 hash_elem *hash_elem_new()
36 /* Martin A. Hansen, November 2008. */
38 /* Initializes a new hash_elem structure. */
40 hash_elem *new_elem = NULL;
42 new_elem = mem_get( sizeof( hash_elem ) );
44 new_elem->next = NULL;
52 void hash_add( hash *hash_pt, char *key, void *val )
54 /* Martin A. Hansen, June 2008 */
56 /* Add a new hash element consisting of a key/value pair to an existing hash. */
58 hash_elem *old_elem = NULL;
59 hash_elem *new_elem = NULL;
60 size_t hash_index = 0;
62 if ( ( old_elem = hash_elem_get( hash_pt, key ) ) != NULL )
68 new_elem = hash_elem_new();
70 hash_index = ( hash_key( key ) & hash_pt->mask );
72 new_elem->key = mem_clone( key, strlen( key ) );
74 new_elem->next = hash_pt->table[ hash_index ];
76 hash_pt->table[ hash_index ] = new_elem;
82 void *hash_get( hash *hash_pt, char *key )
84 /* Martin A. Hansen, June 2008 */
86 /* Lookup a key in a given hash and return the value - or NULL if not found. */
90 bucket = hash_pt->table[ ( hash_key( key ) & hash_pt->mask ) ];
92 while ( bucket != NULL )
94 if ( strcmp( bucket->key, key ) == 0 ) {
98 bucket = bucket->next;
105 hash_elem *hash_elem_get( hash *hash_pt, char *key )
107 /* Martin A. Hansen, June 2008 */
109 /* Lookup a key in a given hash and return the hash element - or NULL if not found. */
113 bucket = hash_pt->table[ ( hash_key( key ) & hash_pt->mask ) ];
115 while ( bucket != NULL )
117 if ( strcmp( bucket->key, key ) == 0 ) {
121 bucket = bucket->next;
128 bool hash_each( hash *hash_pt, char **key_ppt, void *val )
130 /* Martin A. Hansen, December 2008. */
132 /* Get the next key/value pair from a hash table. */
134 char *key = *key_ppt;
136 printf( "\nhash_each INIT -> i: %zu he: %p\n", hash_pt->index_table, hash_pt->index_bucket );
138 if ( hash_pt->index_bucket != NULL )
140 key = hash_pt->index_bucket->key;
141 val = hash_pt->index_bucket->val;
143 hash_pt->index_bucket = hash_pt->index_bucket->next;
147 printf( "\nhash_each BUCKET -> i: %zu he: %p\n", hash_pt->index_table, hash_pt->index_bucket );
151 while ( hash_pt->index_table < hash_pt->table_size )
153 hash_pt->index_bucket = hash_pt->table[ hash_pt->index_table ];
155 if ( hash_pt->index_bucket != NULL )
157 key = hash_pt->index_bucket->key;
158 val = hash_pt->index_bucket->val;
160 hash_pt->index_bucket = hash_pt->index_bucket->next;
164 printf( "hash_each TABLE table[ %zu ]\n", hash_pt->index_table );
168 hash_pt->index_table++;
171 printf( "\nhash_each FALSE -> i: %zu he: %p\n", hash_pt->index_table, hash_pt->index_bucket );
179 void hash_destroy( hash *hash_pt )
181 /* Martin A. Hansen, June 2008 */
183 /* Deallocate memory for hash and all hash elements. */
188 for ( i = 0; i < hash_pt->table_size; i++ )
190 for ( bucket = hash_pt->table[ i ]; bucket != NULL; bucket = bucket->next )
192 // mem_free( bucket->key );
193 // mem_free( bucket->val );
198 mem_free( hash_pt->table );
203 uint hash_key( char *string )
205 /* Martin A. Hansen, June 2008 */
207 /* Hash function that generates a hash key, */
208 /* based on the Jim Kent's stuff. */
214 while ( ( c = *key++ ) != '\0' ) {
215 result += ( result << 3 ) + c;
222 void hash_print( hash *hash_pt )
224 /* Martin A. Hansen, November 2008. */
226 /* Debug function that prints hash meta data and
227 * all hash elements. */
229 hash_elem *bucket = NULL;
232 printf( "table_size: %zu mask: %zu elem_count: %zu\n", hash_pt->table_size, hash_pt->mask, hash_pt->nmemb );
234 for ( i = 0; i < hash_pt->table_size; i++ )
236 bucket = hash_pt->table[ i ];
238 while ( bucket != NULL )
240 printf( "i: %zu key: %s val: %s\n", i, bucket->key, ( char * ) bucket->val );
242 bucket = bucket->next;
248 void hash_collision_stats( hash *hash_pt )
250 /* Martin A. Hansen, June 2008 */
252 /* Output some collision stats for a given hash. */
254 /* Use with Biopieces: ... | plot_histogram -k Col -x */
258 hash_elem *bucket = NULL;
260 for ( i = 0; i < hash_pt->table_size; i++ )
264 for ( bucket = hash_pt->table[ i ]; bucket != NULL; bucket = bucket->next ) {
268 printf( "Col: %zu\n---\n", col );