Merge remote-tracking branch 'origin/topic/jsiwek/h3-byte-size'

* origin/topic/jsiwek/h3-byte-size:
  Fix H3 assumption of an 8-bit byte/char.

Closes #530.
This commit is contained in:
Robin Sommer 2011-08-18 09:54:41 -07:00
commit ecaa05073e
2 changed files with 12 additions and 8 deletions

View file

@ -59,8 +59,13 @@
#ifndef H3_H #ifndef H3_H
#define H3_H #define H3_H
#include <climits>
// The number of values representable by a byte.
#define H3_BYTE_RANGE (UCHAR_MAX+1)
template<class T, int N> class H3 { template<class T, int N> class H3 {
T byte_lookup[N][256]; T byte_lookup[N][H3_BYTE_RANGE];
public: public:
H3(); H3();
~H3() { free(byte_lookup); } ~H3() { free(byte_lookup); }
@ -90,9 +95,9 @@ public:
template<class T, int N> template<class T, int N>
H3<T,N>::H3() H3<T,N>::H3()
{ {
T bit_lookup[N * 8]; T bit_lookup[N * CHAR_BIT];
for (size_t bit = 0; bit < N * 8; bit++) { for (size_t bit = 0; bit < N * CHAR_BIT; bit++) {
bit_lookup[bit] = 0; bit_lookup[bit] = 0;
for (size_t i = 0; i < sizeof(T)/2; i++) { for (size_t i = 0; i < sizeof(T)/2; i++) {
// assume random() returns at least 16 random bits // assume random() returns at least 16 random bits
@ -101,12 +106,12 @@ H3<T,N>::H3()
} }
for (size_t byte = 0; byte < N; byte++) { for (size_t byte = 0; byte < N; byte++) {
for (unsigned val = 0; val < 256; val++) { for (unsigned val = 0; val < H3_BYTE_RANGE; val++) {
byte_lookup[byte][val] = 0; byte_lookup[byte][val] = 0;
for (size_t bit = 0; bit < 8; bit++) { for (size_t bit = 0; bit < CHAR_BIT; bit++) {
// Does this mean byte_lookup[*][0] == 0? -RP // Does this mean byte_lookup[*][0] == 0? -RP
if (val & (1 << bit)) if (val & (1 << bit))
byte_lookup[byte][val] ^= bit_lookup[byte*8+bit]; byte_lookup[byte][val] ^= bit_lookup[byte*CHAR_BIT+bit];
} }
} }
} }

View file

@ -168,13 +168,12 @@ hash_t HashKey::HashBytes(const void* bytes, int size)
{ {
if ( size <= UHASH_KEY_SIZE ) if ( size <= UHASH_KEY_SIZE )
{ {
const uint8* b = reinterpret_cast<const uint8*>(bytes);
// H3 doesn't check if size is zero // H3 doesn't check if size is zero
return ( size == 0 ) ? 0 : (*h3)(bytes, size); return ( size == 0 ) ? 0 : (*h3)(bytes, size);
} }
// Fall back to HMAC/MD5 for longer data (which is usually rare). // Fall back to HMAC/MD5 for longer data (which is usually rare).
hash_t digest[16]; hash_t digest[16];
hmac_md5(size, (unsigned char*) bytes, (unsigned char*) digest); hmac_md5(size, (const unsigned char*) bytes, (unsigned char*) digest);
return digest[0]; return digest[0];
} }