fnv: work with non-64-bit aligned chunks of data
[fio.git] / crc / fnv.c
index 04c0560c9f421bea6796b1f3aef680bc5eb80827..4cd06501fd2e1b92bed2bb8d5e9eff0a85c74ddc 100644 (file)
--- a/crc/fnv.c
+++ b/crc/fnv.c
@@ -2,14 +2,32 @@
 
 #define FNV_PRIME      0x100000001b3ULL
 
+/*
+ * 64-bit fnv, but don't require 64-bit multiples of data. Use bytes
+ * for the last unaligned chunk.
+ */
 uint64_t fnv(const void *buf, uint32_t len, uint64_t hval)
 {
        const uint64_t *ptr = buf;
-       const uint64_t *end = (void *) buf + len;
 
-       while (ptr < end) {
+       while (len) {
                hval *= FNV_PRIME;
-               hval ^= (uint64_t) *ptr++;
+               if (len >= sizeof(uint64_t)) {
+                       hval ^= (uint64_t) *ptr++;
+                       len -= sizeof(uint64_t);
+                       continue;
+               } else {
+                       const uint8_t *ptr8 = (const uint8_t *) ptr;
+                       uint64_t val = 0;
+                       int i;
+
+                       for (i = 0; i < len; i++) {
+                               val <<= 8;
+                               val |= (uint8_t) *ptr8++;
+                       }
+                       hval ^= val;
+                       break;
+               }
        }
 
        return hval;