2 * Copyright (C) 2008 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include <utils/linked_list.h>
20 #include "hashtable.h"
22 /** The maximum capacity of the hash table (MUST be a power of 2) */
23 #define MAX_CAPACITY (1 << 30)
25 typedef struct pair_t pair_t
;
28 * This pair holds a pointer to the key and value it represents.
32 * Key of a hash table item.
37 * Value of a hash table item.
42 * Cached hash (used in case of a resize).
48 * Creates an empty pair object.
50 pair_t
*pair_create(void *key
, void *value
, u_int hash
)
52 pair_t
*this = malloc_thing(pair_t
);
61 typedef struct private_hashtable_t private_hashtable_t
;
64 * Private data of a hashtable_t object.
67 struct private_hashtable_t
{
69 * Public part of hash table.
74 * The number of items in the hash table.
79 * The current capacity of the hash table (always a power of 2).
84 * The current mask to calculate the row index (capacity - 1).
96 linked_list_t
**table
;
99 * The hashing function.
101 hashtable_hash_t hash
;
104 * The equality function.
106 hashtable_equals_t equals
;
109 typedef struct private_enumerator_t private_enumerator_t
;
112 * hash table enumerator implementation
114 struct private_enumerator_t
{
117 * implements enumerator interface
119 enumerator_t enumerator
;
122 * associated hash table
124 private_hashtable_t
*table
;
132 * enumerator for the current row
134 enumerator_t
*current
;
138 * Compare a pair in a list with the given key.
140 static inline bool pair_equals(pair_t
*pair
, private_hashtable_t
*this, void *key
)
142 return this->equals(key
, pair
->key
);
146 * This function returns the next-highest power of two for the given number.
147 * The algorithm works by setting all bits on the right-hand side of the most
148 * significant 1 to 1 and then increments the whole number so it rolls over
149 * to the nearest power of two. Note: returns 0 for n == 0
151 static u_int
get_nearest_powerof2(u_int n
)
155 for (i
= 1; i
< sizeof(u_int
) * 8; i
<<= 1)
163 * Init hash table parameters
165 static void init_hashtable(private_hashtable_t
*this, u_int capacity
)
167 capacity
= max(1, min(capacity
, MAX_CAPACITY
));
169 this->capacity
= get_nearest_powerof2(capacity
);
170 this->mask
= this->capacity
- 1;
171 this->load_factor
= 0.75;
173 this->table
= (linked_list_t
**)calloc(this->capacity
, sizeof(linked_list_t
*));
174 memset(this->table
, 0, this->capacity
* sizeof(linked_list_t
*));
178 * Double the size of the hash table and rehash all the elements.
180 static void rehash(private_hashtable_t
*this)
183 u_int old_capacity
= this->capacity
;
184 linked_list_t
**old_table
= this->table
;
186 if (old_capacity
>= MAX_CAPACITY
)
191 init_hashtable(this, old_capacity
<< 1);
193 for (row
= 0; row
< old_capacity
; ++row
)
196 if ((list
= old_table
[row
]) != NULL
)
199 enumerator_t
*enumerator
= list
->create_enumerator(list
);
200 while (enumerator
->enumerate(enumerator
, &pair
))
202 linked_list_t
*new_list
;
203 u_int new_row
= pair
->hash
& this->mask
;
204 list
->remove_at(list
, enumerator
);
205 if ((new_list
= this->table
[new_row
]) == NULL
)
207 new_list
= this->table
[new_row
] = linked_list_create();
209 new_list
->insert_last(new_list
, pair
);
211 enumerator
->destroy(enumerator
);
219 * Implementation of hashtable_t.put
221 static void *put(private_hashtable_t
*this, void *key
, void *value
)
224 void *old_value
= NULL
;
225 u_int hash
= this->hash(key
);
226 u_int row
= hash
& this->mask
;
228 if ((list
= this->table
[row
]) != NULL
)
231 enumerator_t
*enumerator
= list
->create_enumerator(list
);
232 while (enumerator
->enumerate(enumerator
, &pair
))
234 if (pair_equals(pair
, this, key
))
236 old_value
= pair
->value
;
241 enumerator
->destroy(enumerator
);
245 list
= this->table
[row
] = linked_list_create();
250 list
->insert_last(list
, pair_create(key
, value
, hash
));
254 if (this->count
>= this->capacity
* this->load_factor
)
263 * Implementation of hashtable_t.get
265 static void *get(private_hashtable_t
*this, void *key
)
269 u_int row
= this->hash(key
) & this->mask
;
271 if ((list
= this->table
[row
]) != NULL
)
274 if (list
->find_first(list
, (linked_list_match_t
)pair_equals
,
275 (void**)&pair
, this, key
) == SUCCESS
)
285 * Implementation of hashtable_t.remove
287 static void *remove(private_hashtable_t
*this, void *key
)
291 u_int row
= this->hash(key
) & this->mask
;
293 if ((list
= this->table
[row
]) != NULL
)
296 enumerator_t
*enumerator
= list
->create_enumerator(list
);
297 while (enumerator
->enumerate(enumerator
, &pair
))
299 if (pair_equals(pair
, this, key
))
301 list
->remove_at(list
, enumerator
);
308 enumerator
->destroy(enumerator
);
315 * Implementation of hashtable_t.get_count
317 static u_int
get_count(private_hashtable_t
*this)
323 * Implementation of private_enumerator_t.enumerator.enumerate.
325 static bool enumerate(private_enumerator_t
*this, void **item
)
327 while (this->row
< this->table
->capacity
)
332 if (this->current
->enumerate(this->current
, (void**)&pair
))
337 this->current
->destroy(this->current
);
338 this->current
= NULL
;
343 if ((list
= this->table
->table
[this->row
]) != NULL
)
345 this->current
= list
->create_enumerator(list
);
355 * Implementation of private_enumerator_t.enumerator.destroy.
357 static void enumerator_destroy(private_enumerator_t
*this)
361 this->current
->destroy(this->current
);
367 * Implementation of hashtable_t.create_enumerator.
369 static enumerator_t
* create_enumerator(private_hashtable_t
*this)
371 private_enumerator_t
*enumerator
= malloc_thing(private_enumerator_t
);
373 enumerator
->enumerator
.enumerate
= (void*)enumerate
;
374 enumerator
->enumerator
.destroy
= (void*)enumerator_destroy
;
375 enumerator
->table
= this;
377 enumerator
->current
= NULL
;
379 return &enumerator
->enumerator
;
383 * Implementation of hashtable_t.destroy
385 static void destroy(private_hashtable_t
*this)
388 for (row
= 0; row
< this->capacity
; ++row
)
391 if ((list
= this->table
[row
]) != NULL
)
393 list
->destroy_function(list
, free
);
401 * Described in header.
403 hashtable_t
*hashtable_create(hashtable_hash_t hash
, hashtable_equals_t equals
,
406 private_hashtable_t
*this = malloc_thing(private_hashtable_t
);
408 this->public.put
= (void*(*)(hashtable_t
*,void*,void*))put
;
409 this->public.get
= (void*(*)(hashtable_t
*,void*))get
;
410 this->public.remove
= (void*(*)(hashtable_t
*,void*))remove
;
411 this->public.get_count
= (u_int(*)(hashtable_t
*))get_count
;
412 this->public.create_enumerator
= (enumerator_t
*(*)(hashtable_t
*))create_enumerator
;
413 this->public.destroy
= (void(*)(hashtable_t
*))destroy
;
418 this->load_factor
= 0;
421 this->equals
= equals
;
423 init_hashtable(this, capacity
);
425 return &this->public;