Files
libucore/src/htable.c
T
2013-10-17 21:00:05 +02:00

150 lines
3.0 KiB
C

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#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;
}
struct UHNode *uc_htable_next_hash_hlp(struct UHNode *next, size_t hash)
{
while (next && next->hash != hash) {
next = next->next;
}
return next;
}
struct UHNode *uc_htable_next_hlp(struct UHTable *table, size_t bucket)
{
size_t i;
struct UHNode *found = NULL;
for (i = 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_bucket(node);
if (found == NULL) {
found = uc_htable_next_hlp(table, node->hash + 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++;
}
int uc_htable_resize(struct UHTable *table, size_t buckets)
{
struct UHTable tmp_table;
int rc;
size_t h;
if (buckets == 0) {
return EINVAL;
}
rc = uc_htable_init(&tmp_table, buckets);
if (rc != 0) {
return rc;
}
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);
}
}
uc_htable_swap(&tmp_table, table);
uc_htable_destroy(&tmp_table);
return 0;
}