diff options
Diffstat (limited to 'src/libstrongswan/utils/hashtable.c')
-rw-r--r-- | src/libstrongswan/utils/hashtable.c | 152 |
1 files changed, 83 insertions, 69 deletions
diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c index 6d33d023b..02c225833 100644 --- a/src/libstrongswan/utils/hashtable.c +++ b/src/libstrongswan/utils/hashtable.c @@ -30,12 +30,12 @@ struct pair_t { * Key of a hash table item. */ void *key; - + /** * Value of a hash table item. */ void *value; - + /** * Cached hash (used in case of a resize). */ @@ -48,11 +48,11 @@ struct pair_t { pair_t *pair_create(void *key, void *value, u_int hash) { pair_t *this = malloc_thing(pair_t); - + this->key = key; this->value = value; this->hash = hash; - + return this; } @@ -67,37 +67,37 @@ struct private_hashtable_t { * Public part of hash table. */ hashtable_t public; - + /** - * The number of items in the hash table. + * The number of items in the hash table. */ u_int count; - + /** * The current capacity of the hash table (always a power of 2). */ u_int capacity; - + /** - * The current mask to calculate the row index (capacity - 1). + * The current mask to calculate the row index (capacity - 1). */ u_int mask; - + /** * The load factor. */ float load_factor; - + /** * The actual table. */ linked_list_t **table; - + /** * The hashing function. */ hashtable_hash_t hash; - + /** * The equality function. */ @@ -115,17 +115,17 @@ struct private_enumerator_t { * implements enumerator interface */ enumerator_t enumerator; - + /** * associated hash table */ private_hashtable_t *table; - + /** * current row index */ u_int row; - + /** * enumerator for the current row */ @@ -149,6 +149,7 @@ static inline bool pair_equals(pair_t *pair, private_hashtable_t *this, void *ke static u_int get_nearest_powerof2(u_int n) { u_int i; + --n; for (i = 1; i < sizeof(u_int) * 8; i <<= 1) { @@ -166,7 +167,7 @@ static void init_hashtable(private_hashtable_t *this, u_int capacity) this->capacity = get_nearest_powerof2(capacity); this->mask = this->capacity - 1; this->load_factor = 0.75; - + this->table = calloc(this->capacity, sizeof(linked_list_t*)); } @@ -175,30 +176,37 @@ static void init_hashtable(private_hashtable_t *this, u_int capacity) */ static void rehash(private_hashtable_t *this) { - u_int row; - u_int old_capacity = this->capacity; - linked_list_t **old_table = this->table; - - if (old_capacity >= MAX_CAPACITY) + linked_list_t **old_table; + u_int row, old_capacity; + + if (this->capacity < MAX_CAPACITY) { return; } - + + old_capacity = this->capacity; + old_table = this->table; + init_hashtable(this, old_capacity << 1); - - for (row = 0; row < old_capacity; ++row) + + for (row = 0; row < old_capacity; row++) { - linked_list_t *list; - if ((list = old_table[row]) != NULL) + enumerator_t *enumerator; + linked_list_t *list, *new_list; + pair_t *pair; + u_int new_row; + + list = old_table[row]; + if (list) { - pair_t *pair; - enumerator_t *enumerator = list->create_enumerator(list); + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &pair)) { - linked_list_t *new_list; - u_int new_row = pair->hash & this->mask; + new_row = pair->hash & this->mask; + list->remove_at(list, enumerator); - if ((new_list = this->table[new_row]) == NULL) + new_list = this->table[new_row]; + if (!new_list) { new_list = this->table[new_row] = linked_list_create(); } @@ -216,15 +224,20 @@ static void rehash(private_hashtable_t *this) */ static void *put(private_hashtable_t *this, void *key, void *value) { - linked_list_t *list; void *old_value = NULL; - u_int hash = this->hash(key); - u_int row = hash & this->mask; - - if ((list = this->table[row]) != NULL) + linked_list_t *list; + u_int hash; + u_int row; + + hash = this->hash(key); + row = hash & this->mask; + list = this->table[row]; + if (list) { + enumerator_t *enumerator; pair_t *pair; - enumerator_t *enumerator = list->create_enumerator(list); + + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &pair)) { if (pair_equals(pair, this, key)) @@ -240,43 +253,39 @@ static void *put(private_hashtable_t *this, void *key, void *value) { list = this->table[row] = linked_list_create(); } - if (!old_value) { list->insert_last(list, pair_create(key, value, hash)); this->count++; } - if (this->count >= this->capacity * this->load_factor) { rehash(this); } - return old_value; } - + /** - * Implementation of hashtable_t.get + * Implementation of hashtable_t.get */ static void *get(private_hashtable_t *this, void *key) { void *value = NULL; linked_list_t *list; - u_int row = this->hash(key) & this->mask; - - if ((list = this->table[row]) != NULL) + pair_t *pair; + + list = this->table[this->hash(key) & this->mask]; + if (list) { - pair_t *pair; if (list->find_first(list, (linked_list_match_t)pair_equals, - (void**)&pair, this, key) == SUCCESS) + (void**)&pair, this, key) == SUCCESS) { value = pair->value; } } - return value; } - + /** * Implementation of hashtable_t.remove */ @@ -284,12 +293,14 @@ static void *remove_(private_hashtable_t *this, void *key) { void *value = NULL; linked_list_t *list; - u_int row = this->hash(key) & this->mask; - - if ((list = this->table[row]) != NULL) + + list = this->table[this->hash(key) & this->mask]; + if (list) { + enumerator_t *enumerator; pair_t *pair; - enumerator_t *enumerator = list->create_enumerator(list); + + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &pair)) { if (pair_equals(pair, this, key)) @@ -303,10 +314,9 @@ static void *remove_(private_hashtable_t *this, void *key) } enumerator->destroy(enumerator); } - return value; } - + /** * Implementation of hashtable_t.get_count */ @@ -325,7 +335,7 @@ static bool enumerate(private_enumerator_t *this, void **key, void **value) if (this->current) { pair_t *pair; - + if (this->current->enumerate(this->current, &pair)) { if (key) @@ -344,8 +354,9 @@ static bool enumerate(private_enumerator_t *this, void **key, void **value) else { linked_list_t *list; - - if ((list = this->table->table[this->row]) != NULL) + + list = this->table->table[this->row]; + if (list) { this->current = list->create_enumerator(list); continue; @@ -374,26 +385,28 @@ static void enumerator_destroy(private_enumerator_t *this) static enumerator_t* create_enumerator(private_hashtable_t *this) { private_enumerator_t *enumerator = malloc_thing(private_enumerator_t); - + enumerator->enumerator.enumerate = (void*)enumerate; enumerator->enumerator.destroy = (void*)enumerator_destroy; enumerator->table = this; enumerator->row = 0; enumerator->current = NULL; - + return &enumerator->enumerator; } - + /** * Implementation of hashtable_t.destroy */ static void destroy(private_hashtable_t *this) { + linked_list_t *list; u_int row; - for (row = 0; row < this->capacity; ++row) + + for (row = 0; row < this->capacity; row++) { - linked_list_t *list; - if ((list = this->table[row]) != NULL) + list = this->table[row]; + if (list) { list->destroy_function(list, free); } @@ -411,12 +424,12 @@ hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals, private_hashtable_t *this = malloc_thing(private_hashtable_t); this->public.put = (void*(*)(hashtable_t*,void*,void*))put; - this->public.get = (void*(*)(hashtable_t*,void*))get; + this->public.get = (void*(*)(hashtable_t*,void*))get; this->public.remove = (void*(*)(hashtable_t*,void*))remove_; this->public.get_count = (u_int(*)(hashtable_t*))get_count; this->public.create_enumerator = (enumerator_t*(*)(hashtable_t*))create_enumerator; this->public.destroy = (void(*)(hashtable_t*))destroy; - + this->count = 0; this->capacity = 0; this->mask = 0; @@ -424,8 +437,9 @@ hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals, this->table = NULL; this->hash = hash; this->equals = equals; - + init_hashtable(this, capacity); - + return &this->public; } + |