#include <limits.h>
#include <stdbool.h>
#include <assert.h>
+#include <string.h>
/* We use 0x1 as deleted marker. */
#define HTABLE_DELETED (0x1)
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)
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;
}
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);
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) {
*/
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()
--- /dev/null
+#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();
+}