mirror of
https://github.com/DrBeef/Raze.git
synced 2024-12-16 23:51:00 +00:00
e24b1e8903
That's one more third party dependency down. Not only are two hashing algorithms redundant, there was also a large size discrepancy: SuperFastHash is 3 kb of source code while xxhash is 120kb and generally extremely awful code. It was easy to make a choice here. None of the use cases require this kind of performance tweaking, the longest hashed block of data is a 768 byte palette.
127 lines
2.8 KiB
C++
127 lines
2.8 KiB
C++
#include <stdint.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
/* ======================================================================== */
|
|
|
|
/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh derivative
|
|
license. See:
|
|
http://www.azillionmonkeys.com/qed/weblicense.html for license details.
|
|
|
|
http://www.azillionmonkeys.com/qed/hash.html */
|
|
|
|
#undef get16bits
|
|
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
|
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
|
#define get16bits(d) (*((const uint16_t *) (d)))
|
|
#endif
|
|
|
|
#if !defined (get16bits)
|
|
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
|
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
|
#endif
|
|
|
|
uint32_t SuperFastHash (const char *data, size_t len)
|
|
{
|
|
uint32_t hash = 0, tmp;
|
|
size_t rem;
|
|
|
|
if (len == 0 || data == NULL) return 0;
|
|
|
|
rem = len & 3;
|
|
len >>= 2;
|
|
|
|
/* Main loop */
|
|
for (;len > 0; len--)
|
|
{
|
|
hash += get16bits (data);
|
|
tmp = (get16bits (data+2) << 11) ^ hash;
|
|
hash = (hash << 16) ^ tmp;
|
|
data += 2*sizeof (uint16_t);
|
|
hash += hash >> 11;
|
|
}
|
|
|
|
/* Handle end cases */
|
|
switch (rem)
|
|
{
|
|
case 3: hash += get16bits (data);
|
|
hash ^= hash << 16;
|
|
hash ^= data[sizeof (uint16_t)] << 18;
|
|
hash += hash >> 11;
|
|
break;
|
|
case 2: hash += get16bits (data);
|
|
hash ^= hash << 11;
|
|
hash += hash >> 17;
|
|
break;
|
|
case 1: hash += *data;
|
|
hash ^= hash << 10;
|
|
hash += hash >> 1;
|
|
}
|
|
|
|
/* Force "avalanching" of final 127 bits */
|
|
hash ^= hash << 3;
|
|
hash += hash >> 5;
|
|
hash ^= hash << 4;
|
|
hash += hash >> 17;
|
|
hash ^= hash << 25;
|
|
hash += hash >> 6;
|
|
|
|
return hash;
|
|
}
|
|
|
|
/* A modified version to do a case-insensitive hash */
|
|
|
|
#undef get16bits
|
|
#define get16bits(d) ((((uint32_t)tolower(((const uint8_t *)(d))[1])) << 8)\
|
|
+(uint32_t)tolower(((const uint8_t *)(d))[0]) )
|
|
|
|
uint32_t SuperFastHashI (const char *data, size_t len)
|
|
{
|
|
uint32_t hash = 0, tmp;
|
|
size_t rem;
|
|
|
|
if (len <= 0 || data == NULL) return 0;
|
|
|
|
rem = len & 3;
|
|
len >>= 2;
|
|
|
|
/* Main loop */
|
|
for (;len > 0; len--)
|
|
{
|
|
hash += get16bits (data);
|
|
tmp = (get16bits (data+2) << 11) ^ hash;
|
|
hash = (hash << 16) ^ tmp;
|
|
data += 2*sizeof (uint16_t);
|
|
hash += hash >> 11;
|
|
}
|
|
|
|
/* Handle end cases */
|
|
switch (rem)
|
|
{
|
|
case 3: hash += get16bits (data);
|
|
hash ^= hash << 16;
|
|
hash ^= tolower(data[sizeof (uint16_t)]) << 18;
|
|
hash += hash >> 11;
|
|
break;
|
|
case 2: hash += get16bits (data);
|
|
hash ^= hash << 11;
|
|
hash += hash >> 17;
|
|
break;
|
|
case 1: hash += tolower(*data);
|
|
hash ^= hash << 10;
|
|
hash += hash >> 1;
|
|
}
|
|
|
|
/* Force "avalanching" of final 127 bits */
|
|
hash ^= hash << 3;
|
|
hash += hash >> 5;
|
|
hash ^= hash << 4;
|
|
hash += hash >> 17;
|
|
hash ^= hash << 25;
|
|
hash += hash >> 6;
|
|
|
|
return hash;
|
|
}
|
|
|
|
/* ======================================================================== */
|
|
|