the public domain. It has no warranty.
You probably want to use hashlittle(). hashlittle() and hashbig()
-hash byte arrays. hashlittle() is is faster than hashbig() on
+hash byte arrays. hashlittle() is faster than hashbig() on
little-endian machines. Intel and AMD are little-endian machines.
On second thought, you probably want hashlittle2(), which is identical to
hashlittle() except it returns two 32-bit hashes for the price of one.
*/
/* #define SELF_TEST 1 */
-#include <stdio.h> /* defines printf for tests */
-#include <time.h> /* defines time_t for timings in the test */
#include <stdint.h> /* defines uint32_t etc */
+#include <stdio.h> /* defines printf for tests */
#include <sys/param.h> /* attempt to define endianness */
+#include <time.h> /* defines time_t for timings in the test */
#ifdef linux
# include <endian.h> /* attempt to define endianness */
#endif
+#if __GNUC__ >= 7
+_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
+#endif
+
/*
* My best guess at if you are big-endian or little-endian. This may
* need adjustment.
return c;
}
-
/*
--------------------------------------------------------------------
hashword2() -- same as hashword(), but take two seeds and return two
*pc=c; *pb=b;
}
-
/*
-------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
+ * noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !VALGRIND && !HAS_FEATURE_ADDRESS_SANITIZER
switch(length)
{
}
#else /* make valgrind happy */
-
- k8 = (const uint8_t *)k;
- switch(length)
{
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
- case 1 : a+=k8[0]; break;
- case 0 : return c;
+ const uint8_t *k8 = (const uint8_t *) k;
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : return c;
+ }
}
#endif /* !valgrind */
return c;
}
-
/*
* hashlittle2: return 2 32-bit hash values
*
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
+ * noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !VALGRIND && !HAS_FEATURE_ADDRESS_SANITIZER
switch(length)
{
#else /* make valgrind happy */
- k8 = (const uint8_t *)k;
- switch(length)
{
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
- case 9 : c+=k8[8]; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
- case 5 : b+=k8[4]; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
- case 1 : a+=k8[0]; break;
- case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ const uint8_t *k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
+ }
}
#endif /* !valgrind */
*pc=c; *pb=b;
}
-
-
/*
* hashbig():
* This is the same as hashword() on big-endian machines. It is different
* then shifts out the part it's not allowed to read. Because the
* string is aligned, the illegal read is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
+ * noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !VALGRIND && !HAS_FEATURE_ADDRESS_SANITIZER
switch(length)
{
#else /* make valgrind happy */
- k8 = (const uint8_t *)k;
- switch(length) /* all the case statements fall through */
{
- case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
- case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
- case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
- case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
- case 8 : b+=k[1]; a+=k[0]; break;
- case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
- case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
- case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
- case 4 : a+=k[0]; break;
- case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
- case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
- case 1 : a+=((uint32_t)k8[0])<<24; break;
- case 0 : return c;
+ const uint8_t *k8 = (const uint8_t *)k;
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
+ case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
+ case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
+ case 1 : a+=((uint32_t)k8[0])<<24; break;
+ case 0 : return c;
+ }
}
#endif /* !VALGRIND */
return c;
}
-
#ifdef SELF_TEST
/* used for timings */
uint8_t buf[1];
uint32_t h,i,state[HASHSTATE];
-
buf[0] = ~0;
for (i=0; i<HASHSTATE; ++i) state[i] = 1;
printf("These should all be different\n");
printf("hash is %.8lx\n", c); /* cd628161 */
}
-
int main()
{
driver1(); /* test that the key is hashed: used for timings */