| Replace murmurhash algorithm with Robert Jenkin's hash algorithm |
| |
| Upstream-Status: Pending |
| |
| From test result, murmurhash algorithm does not work in big endian |
| processor, so replace it with Robert Jenkin's hash which has worked |
| in linux kernel for many years and has more adaptability. |
| |
| Signed-off-by: Roy.Li <rongqing.li@windriver.com> |
| --- |
| libfdproto/ostr.c | 192 +++++++++++++++++++++-------------------------------- |
| 1 file changed, 74 insertions(+), 118 deletions(-) |
| |
| diff --git a/libfdproto/ostr.c b/libfdproto/ostr.c |
| index 8f29b48..ce1f4dd 100644 |
| --- a/libfdproto/ostr.c |
| +++ b/libfdproto/ostr.c |
| @@ -430,128 +430,84 @@ after_proto: |
| |
| |
| /********************************************************************************************************/ |
| -/* Hash function -- credits to Austin Appleby, thank you ^^ */ |
| -/* See http://murmurhash.googlepages.com for more information on this function */ |
| - |
| -/* the strings are NOT always aligned properly (ex: received in RADIUS message), so we use the aligned MurmurHash2 function as needed */ |
| -#define _HASH_MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; } |
| -uint32_t fd_os_hash ( uint8_t * string, size_t len ) |
| +/* |
| + * Robert Jenkin's hash function. |
| + * http://burtleburtle.net/bob/hash/evahash.html |
| + * This is in the public domain. |
| + */ |
| +#define mix(a, b, c) \ |
| + do { \ |
| + a = a - b; a = a - c; a = a ^ (c >> 13); \ |
| + b = b - c; b = b - a; b = b ^ (a << 8); \ |
| + c = c - a; c = c - b; c = c ^ (b >> 13); \ |
| + a = a - b; a = a - c; a = a ^ (c >> 12); \ |
| + b = b - c; b = b - a; b = b ^ (a << 16); \ |
| + c = c - a; c = c - b; c = c ^ (b >> 5); \ |
| + a = a - b; a = a - c; a = a ^ (c >> 3); \ |
| + b = b - c; b = b - a; b = b ^ (a << 10); \ |
| + c = c - a; c = c - b; c = c ^ (b >> 15); \ |
| + } while (0) |
| + |
| +unsigned hash_rjenkins(const char *str, unsigned length) |
| { |
| - uint32_t hash = len; |
| - uint8_t * data = string; |
| - |
| - const unsigned int m = 0x5bd1e995; |
| - const int r = 24; |
| - int align = (long)string & 3; |
| - |
| - if (!align || (len < 4)) { |
| - /* In case data is aligned, MurmurHash2 function */ |
| - while(len >= 4) |
| - { |
| - /* Mix 4 bytes at a time into the hash */ |
| - uint32_t k = *(uint32_t *)data; /* We don't care about the byte order */ |
| - |
| - _HASH_MIX(hash, k, m); |
| - |
| - data += 4; |
| - len -= 4; |
| - } |
| - |
| - /* Handle the last few bytes of the input */ |
| - switch(len) { |
| - case 3: hash ^= data[2] << 16; |
| - case 2: hash ^= data[1] << 8; |
| - case 1: hash ^= data[0]; |
| - hash *= m; |
| - } |
| - |
| - } else { |
| - /* Unaligned data, use alignment-safe slower version */ |
| - |
| - /* Pre-load the temp registers */ |
| - uint32_t t = 0, d = 0; |
| - switch(align) |
| - { |
| - case 1: t |= data[2] << 16; |
| - case 2: t |= data[1] << 8; |
| - case 3: t |= data[0]; |
| - } |
| - t <<= (8 * align); |
| - |
| - data += 4-align; |
| - len -= 4-align; |
| - |
| - /* From this point, "data" can be read by chunks of 4 bytes */ |
| - |
| - int sl = 8 * (4-align); |
| - int sr = 8 * align; |
| - |
| - /* Mix */ |
| - while(len >= 4) |
| - { |
| - uint32_t k; |
| - |
| - d = *(unsigned int *)data; |
| - k = (t >> sr) | (d << sl); |
| - |
| - _HASH_MIX(hash, k, m); |
| - |
| - t = d; |
| - |
| - data += 4; |
| - len -= 4; |
| - } |
| - |
| - /* Handle leftover data in temp registers */ |
| - d = 0; |
| - if(len >= align) |
| - { |
| - uint32_t k; |
| - |
| - switch(align) |
| - { |
| - case 3: d |= data[2] << 16; |
| - case 2: d |= data[1] << 8; |
| - case 1: d |= data[0]; |
| - } |
| - |
| - k = (t >> sr) | (d << sl); |
| - _HASH_MIX(hash, k, m); |
| - |
| - data += align; |
| - len -= align; |
| - |
| - /* Handle tail bytes */ |
| - |
| - switch(len) |
| - { |
| - case 3: hash ^= data[2] << 16; |
| - case 2: hash ^= data[1] << 8; |
| - case 1: hash ^= data[0]; |
| - hash *= m; |
| - }; |
| - } |
| - else |
| - { |
| - switch(len) |
| - { |
| - case 3: d |= data[2] << 16; |
| - case 2: d |= data[1] << 8; |
| - case 1: d |= data[0]; |
| - case 0: hash ^= (t >> sr) | (d << sl); |
| - hash *= m; |
| - } |
| - } |
| - |
| + const unsigned char *k = (const unsigned char *)str; |
| + uint32_t a, b, c; /* the internal state */ |
| + uint32_t len; /* how many key bytes still need mixing */ |
| + |
| + /* Set up the internal state */ |
| + len = length; |
| + a = 0x9e3779b9; /* the golden ratio; an arbitrary value */ |
| + b = a; |
| + c = 0; /* variable initialization of internal state */ |
| + |
| + /* handle most of the key */ |
| + while (len >= 12) { |
| + a = a + (k[0] + ((uint32_t)k[1] << 8) + ((uint32_t)k[2] << 16) + |
| + ((uint32_t)k[3] << 24)); |
| + b = b + (k[4] + ((uint32_t)k[5] << 8) + ((uint32_t)k[6] << 16) + |
| + ((uint32_t)k[7] << 24)); |
| + c = c + (k[8] + ((uint32_t)k[9] << 8) + ((uint32_t)k[10] << 16) + |
| + ((uint32_t)k[11] << 24)); |
| + mix(a, b, c); |
| + k = k + 12; |
| + len = len - 12; |
| + } |
| |
| + /* handle the last 11 bytes */ |
| + c = c + length; |
| + switch (len) { /* all the case statements fall through */ |
| + case 11: |
| + c = c + ((uint32_t)k[10] << 24); |
| + case 10: |
| + c = c + ((uint32_t)k[9] << 16); |
| + case 9: |
| + c = c + ((uint32_t)k[8] << 8); |
| + /* the first byte of c is reserved for the length */ |
| + case 8: |
| + b = b + ((uint32_t)k[7] << 24); |
| + case 7: |
| + b = b + ((uint32_t)k[6] << 16); |
| + case 6: |
| + b = b + ((uint32_t)k[5] << 8); |
| + case 5: |
| + b = b + k[4]; |
| + case 4: |
| + a = a + ((uint32_t)k[3] << 24); |
| + case 3: |
| + a = a + ((uint32_t)k[2] << 16); |
| + case 2: |
| + a = a + ((uint32_t)k[1] << 8); |
| + case 1: |
| + a = a + k[0]; |
| + /* case 0: nothing left to add */ |
| } |
| + mix(a, b, c); |
| |
| - /* Do a few final mixes of the hash to ensure the last few |
| - bytes are well-incorporated. */ |
| - hash ^= hash >> 13; |
| - hash *= m; |
| - hash ^= hash >> 15; |
| + return c; |
| +} |
| |
| - return hash; |
| +uint32_t fd_os_hash ( uint8_t * string, size_t len ) |
| +{ |
| + return hash_rjenkins(string, len); |
| } |
| |
| -- |
| 1.7.10.4 |
| |