Commit f359fde1 authored by Rusty Russell's avatar Rusty Russell

htable: add htable_copy.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 7b567629
......@@ -5,6 +5,7 @@
#include <limits.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>
/* We use 0x1 as deleted marker. */
#define HTABLE_DELETED (0x1)
......@@ -52,6 +53,13 @@ void htable_init(struct htable *ht,
ht->table = &ht->perfect_bit;
}
/* We've changed ht->bits, update ht->max and ht->max_with_deleted */
static void htable_adjust_capacity(struct htable *ht)
{
ht->max = ((size_t)3 << ht->bits) / 4;
ht->max_with_deleted = ((size_t)9 << ht->bits) / 10;
}
bool htable_init_sized(struct htable *ht,
size_t (*rehash)(const void *, void *),
void *priv, size_t expect)
......@@ -69,9 +77,7 @@ bool htable_init_sized(struct htable *ht,
ht->table = &ht->perfect_bit;
return false;
}
ht->max = ((size_t)3 << ht->bits) / 4;
ht->max_with_deleted = ((size_t)9 << ht->bits) / 10;
htable_adjust_capacity(ht);
return true;
}
......@@ -82,6 +88,19 @@ void htable_clear(struct htable *ht)
htable_init(ht, ht->rehash, ht->priv);
}
bool htable_copy(struct htable *dst, const struct htable *src)
{
uintptr_t *htable = malloc(sizeof(size_t) << src->bits);
if (!htable)
return false;
*dst = *src;
dst->table = htable;
memcpy(dst->table, src->table, sizeof(size_t) << src->bits);
return true;
}
static size_t hash_bucket(const struct htable *ht, size_t h)
{
return h & ((1 << ht->bits)-1);
......@@ -174,8 +193,7 @@ static COLD bool double_table(struct htable *ht)
return false;
}
ht->bits++;
ht->max = ((size_t)3 << ht->bits) / 4;
ht->max_with_deleted = ((size_t)9 << ht->bits) / 10;
htable_adjust_capacity(ht);
/* If we lost our "perfect bit", get it back now. */
if (!ht->perfect_bit && ht->common_mask) {
......
......@@ -74,6 +74,25 @@ bool htable_init_sized(struct htable *ht,
*/
void htable_clear(struct htable *ht);
/**
* htable_copy - duplicate a hash table.
* @dst: the hash table to overwrite
* @src: the hash table to copy
*
* Only fails on out-of-memory.
*
* Equivalent to (but faster than):
* if (!htable_init_sized(dst, src->rehash, src->priv, 1U << src->bits))
* return false;
* v = htable_first(src, &i);
* while (v) {
* htable_add(dst, v);
* v = htable_next(src, i);
* }
* return true;
*/
bool htable_copy(struct htable *dst, const struct htable *src);
/**
* htable_rehash - use a hashtree's rehash function
* @elem: the argument to rehash()
......
#include <ccan/htable/htable.h>
#include <ccan/htable/htable.c>
#include <ccan/tap/tap.h>
#include <stdbool.h>
#include <string.h>
#define NUM_VALS 512
static size_t hash(const void *elem, void *unused)
{
size_t h = *(uint64_t *)elem / 2;
return h;
}
static bool cmp(const void *candidate, void *ptr)
{
return *(const uint64_t *)candidate == *(const uint64_t *)ptr;
}
int main(int argc, char *argv[])
{
struct htable ht, ht2;
uint64_t val[NUM_VALS], i;
plan_tests((NUM_VALS) * 3);
for (i = 0; i < NUM_VALS; i++)
val[i] = i;
htable_init(&ht, hash, NULL);
for (i = 0; i < NUM_VALS; i++) {
ok1(ht.max >= i);
ok1(ht.max <= i * 2);
htable_add(&ht, hash(&val[i], NULL), &val[i]);
}
htable_copy(&ht2, &ht);
htable_clear(&ht);
for (i = 0; i < NUM_VALS; i++)
ok1(htable_get(&ht2, hash(&i, NULL), cmp, &i) == &val[i]);
htable_clear(&ht2);
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment