]> git.ozlabs.org Git - ccan/blobdiff - ccan/htable/htable.c
endian: add constant versions.
[ccan] / ccan / htable / htable.c
index f3e529211d5b2456bad5165d3baa848de4314d3d..b7e65d11966acc96be83dffbb25a273fec153145 100644 (file)
@@ -45,18 +45,10 @@ static inline uintptr_t get_hash_ptr_bits(const struct htable *ht,
 void htable_init(struct htable *ht,
                 size_t (*rehash)(const void *elem, void *priv), void *priv)
 {
-       ht->bits = 0;
+       struct htable empty = HTABLE_INITIALIZER(empty, NULL, NULL);
+       *ht = empty;
        ht->rehash = rehash;
        ht->priv = priv;
-       ht->elems = 0;
-       ht->deleted = 0;
-       ht->max = 0;
-       ht->max_with_deleted = 0;
-       /* This guarantees we enter update_common first add. */
-       ht->common_mask = -1;
-       ht->common_bits = 0;
-       ht->perfect_bit = 0;
-       /* Dummy table until first insert. */
        ht->table = &ht->perfect_bit;
 }
 
@@ -205,8 +197,17 @@ static COLD void update_common(struct htable *ht, const void *p)
        uintptr_t maskdiff, bitsdiff;
 
        if (ht->elems == 0) {
-               ht->common_mask = -1;
-               ht->common_bits = (uintptr_t)p;
+               /* Always reveal one bit of the pointer in the bucket,
+                * so it's not zero or HTABLE_DELETED (1), even if
+                * hash happens to be 0.  Assumes (void *)1 is not a
+                * valid pointer. */
+               for (i = sizeof(uintptr_t)*CHAR_BIT - 1; i > 0; i--) {
+                       if ((uintptr_t)p & ((uintptr_t)1 << i))
+                               break;
+               }
+
+               ht->common_mask = ~((uintptr_t)1 << i);
+               ht->common_bits = ((uintptr_t)p & ht->common_mask);
                ht->perfect_bit = 1;
                return;
        }