#include #include #include #include "ucore/htable.h" int uc_htable_init(struct UHTable *table, size_t buckets) { if (buckets == 0) { return EINVAL; } table->buckets = calloc(buckets, sizeof *table->buckets); if (table->buckets == NULL) { return ENOMEM; } table->cnt_buckets = buckets; table->cnt_elements = 0; return 0; } void uc_htable_destroy(struct UHTable *table) { free(table->buckets); table->buckets = NULL; table->cnt_elements = table->cnt_buckets = -1; } struct UHNode *uc_htable_first_hash(const struct UHTable *table, size_t hash) { size_t bucket = uc_htable_bucket(table, hash); struct UHNode *it = table->buckets[bucket]; while (it && it->hash != hash) { it = it->next; } return it; } //given a node, find the next one in the chain with the given hash struct UHNode *uc_htable_next_hash_hlp(struct UHNode *next, size_t hash) { while (next && next->hash != hash) { next = next->next; } return next; } //find a node, starting at bucket struct UHNode *uc_htable_iter_hlp(struct UHTable *table, size_t start_bucket) { size_t i; struct UHNode *found = NULL; //search through buckets until a node is found for (i = start_bucket; i < table->cnt_buckets; i++) { found = uc_htable_first_bucket(table, i); if (found != NULL) { break; } } return found; } struct UHNode *uc_htable_next(struct UHTable *table, struct UHNode *node) { struct UHNode *found; found = uc_htable_next_in_bucket(node); if (found == NULL) { size_t current_bucket = uc_htable_bucket(table, node->hash); found = uc_htable_iter_hlp(table, current_bucket + 1); } return found; } void uc_htable_swap(struct UHTable *a, struct UHTable *b) { struct UHTable tmp; tmp = *a; *a = *b; *b = tmp; } int uc_htable_has_node(struct UHTable *table, struct UHNode *node) { struct UHNode *iter; UC_HTABLE_FOREACH_BUCKET(table, iter, node->hash) { if (node == iter) { return 1; } } return 0; } void uc_htable_clear(struct UHTable *table) { memset(table->buckets, 0 , sizeof *table->buckets * table->cnt_buckets); table->cnt_elements = 0; } void uc_htable_insert(struct UHTable *table, struct UHNode *node, size_t hash) { size_t bucket = uc_htable_bucket(table, hash); node->next = table->buckets[bucket]; table->buckets[bucket] = node; node->hash = hash; table->cnt_elements++; } void uc_htable_remove(struct UHTable *table, struct UHNode *node) { struct UHNode **it = &table->buckets[uc_htable_bucket(table, node->hash)]; while (*it) { if (*it == node) { *it = (*it)->next; table->cnt_elements--; break; } it = &(*it)->next; } } int uc_htable_resize(struct UHTable *table, size_t buckets) { struct UHTable tmp_table; int rc; size_t h; if (buckets == 0) { return EINVAL; } //create new temp table rc = uc_htable_init(&tmp_table, buckets); if (rc != 0) { return rc; } //move all the nodes to the new temp table for (h = 0; h < table->cnt_buckets; h++) { struct UHNode *next; struct UHNode *node; for (node = uc_htable_first_bucket(table, h); node != NULL; node = next) { next = node->next; uc_htable_insert(&tmp_table, node, node->hash); } } //replace the existing table with the resized temp table uc_htable_swap(&tmp_table, table); uc_htable_destroy(&tmp_table); return 0; }