Created
August 5, 2012 15:00
-
-
Save stevenbristol/3265249 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
st_hash(const void *ptr, size_t len, st_index_t h) | |
{ | |
const char *data = ptr; | |
st_index_t t = 0; | |
h += 0xdeadbeef; | |
#define data_at(n) (st_index_t)((unsigned char)data[(n)]) | |
#define UNALIGNED_ADD_4 UNALIGNED_ADD(2); UNALIGNED_ADD(1); UNALIGNED_ADD(0) | |
#if SIZEOF_ST_INDEX_T > 4 | |
#define UNALIGNED_ADD_8 UNALIGNED_ADD(6); UNALIGNED_ADD(5); UNALIGNED_ADD(4); UNALIGNED_ADD(3); UNALIGNED_ADD_4 | |
#if SIZEOF_ST_INDEX_T > 8 | |
#define UNALIGNED_ADD_16 UNALIGNED_ADD(14); UNALIGNED_ADD(13); UNALIGNED_ADD(12); UNALIGNED_ADD(11); \ | |
UNALIGNED_ADD(10); UNALIGNED_ADD(9); UNALIGNED_ADD(8); UNALIGNED_ADD(7); UNALIGNED_ADD_8 | |
#define UNALIGNED_ADD_ALL UNALIGNED_ADD_16 | |
#endif | |
#define UNALIGNED_ADD_ALL UNALIGNED_ADD_8 | |
#else | |
#define UNALIGNED_ADD_ALL UNALIGNED_ADD_4 | |
#endif | |
if (len >= sizeof(st_index_t)) { | |
#if !UNALIGNED_WORD_ACCESS | |
int align = (int)((st_data_t)data % sizeof(st_index_t)); | |
if (align) { | |
st_index_t d = 0; | |
int sl, sr, pack; | |
switch (align) { | |
#ifdef WORDS_BIGENDIAN | |
# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \ | |
t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2) | |
#else | |
# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \ | |
t |= data_at(n) << CHAR_BIT*(n) | |
#endif | |
UNALIGNED_ADD_ALL; | |
#undef UNALIGNED_ADD | |
} | |
#ifdef WORDS_BIGENDIAN | |
t >>= (CHAR_BIT * align) - CHAR_BIT; | |
#else | |
t <<= (CHAR_BIT * align); | |
#endif | |
data += sizeof(st_index_t)-align; | |
len -= sizeof(st_index_t)-align; | |
sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align); | |
sr = CHAR_BIT * align; | |
while (len >= sizeof(st_index_t)) { | |
d = *(st_index_t *)data; | |
#ifdef WORDS_BIGENDIAN | |
t = (t << sr) | (d >> sl); | |
#else | |
t = (t >> sr) | (d << sl); | |
#endif | |
h = murmur_step(h, t); | |
t = d; | |
data += sizeof(st_index_t); | |
len -= sizeof(st_index_t); | |
} | |
pack = len < (size_t)align ? (int)len : align; | |
d = 0; | |
switch (pack) { | |
#ifdef WORDS_BIGENDIAN | |
# define UNALIGNED_ADD(n) case (n) + 1: \ | |
d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1) | |
#else | |
# define UNALIGNED_ADD(n) case (n) + 1: \ | |
d |= data_at(n) << CHAR_BIT*(n) | |
#endif | |
UNALIGNED_ADD_ALL; | |
#undef UNALIGNED_ADD | |
} | |
#ifdef WORDS_BIGENDIAN | |
t = (t << sr) | (d >> sl); | |
#else | |
t = (t >> sr) | (d << sl); | |
#endif | |
#if MURMUR == 2 | |
if (len < (size_t)align) goto skip_tail; | |
#endif | |
h = murmur_step(h, t); | |
data += pack; | |
len -= pack; | |
} | |
else | |
#endif | |
{ | |
do { | |
h = murmur_step(h, *(st_index_t *)data); | |
data += sizeof(st_index_t); | |
len -= sizeof(st_index_t); | |
} while (len >= sizeof(st_index_t)); | |
} | |
} | |
t = 0; | |
switch (len) { | |
#ifdef WORDS_BIGENDIAN | |
# define UNALIGNED_ADD(n) case (n) + 1: \ | |
t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1) | |
#else | |
# define UNALIGNED_ADD(n) case (n) + 1: \ | |
t |= data_at(n) << CHAR_BIT*(n) | |
#endif | |
UNALIGNED_ADD_ALL; | |
#undef UNALIGNED_ADD | |
#if MURMUR == 1 | |
h = murmur_step(h, t); | |
#elif MURMUR == 2 | |
# if !UNALIGNED_WORD_ACCESS | |
skip_tail: | |
# endif | |
h ^= t; | |
h *= MurmurMagic; | |
#endif | |
} | |
return murmur_finish(h); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment