]> git.ozlabs.org Git - ccan/blobdiff - ccan/hash/hash.h
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / hash / hash.h
index 1f8ccbf06212e3b3b7b98ce32ee07659c717a8df..217068406af701b74257d4066c5bdf39d41f41e8 100644 (file)
@@ -1,8 +1,9 @@
+/* CC0 (Public domain) - see LICENSE file for details */
 #ifndef CCAN_HASH_H
 #define CCAN_HASH_H
+#include "config.h"
 #include <stdint.h>
 #include <stdlib.h>
-#include "config.h"
 #include <ccan/build_assert/build_assert.h>
 
 /* Stolen mostly from: lookup3.c, by Bob Jenkins, May 2006, Public Domain.
  * See also: hash64, hash_stable.
  *
  * Example:
- *     #include "hash/hash.h"
+ *     #include <ccan/hash/hash.h>
  *     #include <err.h>
  *     #include <stdio.h>
+ *     #include <string.h>
  *
  *     // Simple demonstration: idential strings will have the same hash, but
  *     // two different strings will probably not.
  *     hash64_stable
  *
  * Example:
- *     #include "hash/hash.h"
+ *     #include <ccan/hash/hash.h>
  *     #include <err.h>
  *     #include <stdio.h>
+ *     #include <string.h>
  *
  *     int main(int argc, char *argv[])
  *     {
@@ -89,8 +92,8 @@
  *     }
  */
 #define hash_stable(p, num, base)                                      \
-       (EXPR_BUILD_ASSERT(sizeof(*(p)) == 8 || sizeof(*(p)) == 4       \
-                          || sizeof(*(p)) == 2 || sizeof(*(p)) == 1) + \
+       (BUILD_ASSERT_OR_ZERO(sizeof(*(p)) == 8 || sizeof(*(p)) == 4    \
+                             || sizeof(*(p)) == 2 || sizeof(*(p)) == 1) + \
         sizeof(*(p)) == 8 ? hash_stable_64((p), (num), (base))         \
         : sizeof(*(p)) == 4 ? hash_stable_32((p), (num), (base))       \
         : sizeof(*(p)) == 2 ? hash_stable_16((p), (num), (base))       \
@@ -159,6 +162,7 @@ static inline uint32_t hash_string(const char *string)
  *     #include <ccan/hash/hash.h>
  *     #include <err.h>
  *     #include <stdio.h>
+ *     #include <string.h>
  *
  *     // Simple demonstration: idential strings will have the same hash, but
  *     // two different strings will probably not.
@@ -204,6 +208,7 @@ static inline uint32_t hash_string(const char *string)
  *     #include <ccan/hash/hash.h>
  *     #include <err.h>
  *     #include <stdio.h>
+ *     #include <string.h>
  *
  *     int main(int argc, char *argv[])
  *     {
@@ -216,8 +221,8 @@ static inline uint32_t hash_string(const char *string)
  *     }
  */
 #define hash64_stable(p, num, base)                                    \
-       (EXPR_BUILD_ASSERT(sizeof(*(p)) == 8 || sizeof(*(p)) == 4       \
-                          || sizeof(*(p)) == 2 || sizeof(*(p)) == 1) + \
+       (BUILD_ASSERT_OR_ZERO(sizeof(*(p)) == 8 || sizeof(*(p)) == 4    \
+                             || sizeof(*(p)) == 2 || sizeof(*(p)) == 1) + \
         sizeof(*(p)) == 8 ? hash64_stable_64((p), (num), (base))       \
         : sizeof(*(p)) == 4 ? hash64_stable_32((p), (num), (base))     \
         : sizeof(*(p)) == 2 ? hash64_stable_16((p), (num), (base))     \
@@ -233,8 +238,8 @@ static inline uint32_t hash_string(const char *string)
  * This is either hash() or hash64(), on 32/64 bit long machines.
  */
 #define hashl(p, num, base)                                            \
-       (EXPR_BUILD_ASSERT(sizeof(long) == sizeof(uint32_t)             \
-                          || sizeof(long) == sizeof(uint64_t)) +       \
+       (BUILD_ASSERT_OR_ZERO(sizeof(long) == sizeof(uint32_t)          \
+                             || sizeof(long) == sizeof(uint64_t)) +    \
        (sizeof(long) == sizeof(uint64_t)                               \
         ? hash64((p), (num), (base)) : hash((p), (num), (base))))
 
@@ -263,7 +268,7 @@ uint64_t hash64_stable_8(const void *key, size_t n, uint64_t base);
  * network or saved to disk).
  *
  * Example:
- *     #include "hash/hash.h"
+ *     #include <ccan/hash/hash.h>
  *
  *     // Code to keep track of memory regions.
  *     struct region {
@@ -276,17 +281,17 @@ uint64_t hash64_stable_8(const void *key, size_t n, uint64_t base);
  *
  *     static void add_region(struct region *r)
  *     {
- *             unsigned int h = hash_pointer(r->start);
+ *             unsigned int h = hash_pointer(r->start, 0);
  *
  *             r->chain = region_hash[h];
  *             region_hash[h] = r->chain;
  *     }
  *
- *     static void find_region(const void *start)
+ *     static struct region *find_region(const void *start)
  *     {
  *             struct region *r;
  *
- *             for (r = region_hash[hash_pointer(start)]; r; r = r->chain)
+ *             for (r = region_hash[hash_pointer(start, 0)]; r; r = r->chain)
  *                     if (r->start == start)
  *                             return r;
  *             return NULL;
@@ -297,11 +302,11 @@ static inline uint32_t hash_pointer(const void *p, uint32_t base)
        if (sizeof(p) % sizeof(uint32_t) == 0) {
                /* This convoluted union is the right way of aliasing. */
                union {
-                       uint32_t u32[sizeof(p) / sizeof(uint32_t)];
+                       uint32_t a[sizeof(p) / sizeof(uint32_t)];
                        const void *p;
                } u;
                u.p = p;
-               return hash_u32(u.u32, sizeof(p) / sizeof(uint32_t), base);
+               return hash_u32(u.a, sizeof(p) / sizeof(uint32_t), base);
        } else
                return hash(&p, 1, base);
 }