#pragma once #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" #include #include namespace stingray_plugin_foundation { // Implementation of the 64 bit murmur hash function // http://murmurhash.googlepages.com/ inline uint64_t murmur_hash_64(const void * key, int len, uint64_t seed) { const uint64_t m = 0xc6a4a7935bd1e995ULL; const int r = 47; uint64_t h = seed ^ (len * m); const uint64_t * data = (const uint64_t *)key; const uint64_t * end = data + (len/8); while(data != end) { #if defined(ANDROID) || defined(IOS) || defined(WEB) // Unaligned 64bit reads not supported! uint64_t k; char *p = (char *)&k, *d = (char *)data; p[0] = d[0]; p[1] = d[1]; p[2] = d[2]; p[3] = d[3]; p[4] = d[4]; p[5] = d[5]; p[6] = d[6]; p[7] = d[7]; data++; #elif defined(WINDOWSPC) || defined(UWP) || defined(XBOXONE) || defined(__ORBIS__) || defined(MACOSX) || defined(LINUXPC) uint64_t k = *data++; #else #error Unaligned 64bit reads undefined! #endif k *= m; k ^= k >> r; k *= m; h ^= k; h *= m; } const unsigned char * data2 = (const unsigned char*)data; switch(len & 7) { case 7: h ^= uint64_t(data2[6]) << 48; case 6: h ^= uint64_t(data2[5]) << 40; case 5: h ^= uint64_t(data2[4]) << 32; case 4: h ^= uint64_t(data2[3]) << 24; case 3: h ^= uint64_t(data2[2]) << 16; case 2: h ^= uint64_t(data2[1]) << 8; case 1: h ^= uint64_t(data2[0]); h *= m; }; h ^= h >> r; h *= m; h ^= h >> r; return h; } inline uint64_t hash64(const char *s) { return murmur_hash_64(s, int(strlen(s)), 0); } inline unsigned hash32(const char *s) { uint64_t id64 = murmur_hash_64(s, int(strlen(s)), 0); return unsigned(id64 >> 32); } inline unsigned hash32(const void * key, int len) { uint64_t id64 = murmur_hash_64(key, len, 0); return unsigned(id64 >> 32); } // A quick hash for four byte sized values based on a single // iteration of the murmur hash function. // // Another option would be to convert the bit pattern directly to // an int. That would be faster, but might lead to clustering if // the input values do not distribute evenly. inline unsigned int four_byte_hash(const void * key) { const unsigned int m = 0x5bd1e995; const int r = 24; unsigned int k = *(unsigned int *)key; k *= m; k ^= k >> r; k *= m; return k; } inline uint64_t eight_byte_hash_64(const void * key) { const uint64_t m = 0xc6a4a7935bd1e995ULL; const int r = 47; uint64_t k = *(const uint64_t *)key; k *= m; k ^= k >> r; k *= m; return k; } // Default hashing for builtin-types. template struct default_hash; template struct default_hash { unsigned operator()(T *t) const { #ifdef PLATFORM_64BIT return (unsigned)eight_byte_hash_64(&t); #else return four_byte_hash(&t); #endif } }; template struct default_hash { unsigned operator()(const T *t) const { #ifdef PLATFORM_64BIT return (unsigned)eight_byte_hash_64(&t); #else return four_byte_hash(&t); #endif } }; template <> struct default_hash { unsigned operator()(unsigned t) const { return four_byte_hash(&t); } }; template <> struct default_hash { unsigned operator()(int t) const { return four_byte_hash(&t); } }; template <> struct default_hash { unsigned operator()(uint64_t t) const { return hash32(&t, sizeof(t)); } }; template <> struct default_hash { unsigned operator()(int64_t t) const { return hash32(&t, sizeof(t)); } }; // Utility functions inline uint64_t mix(uint64_t h, uint64_t k) { const uint64_t m = 0xc6a4a7935bd1e995ULL; const int r = 47; k *= m; k ^= k >> r; k *= m; h ^= k; h *= m; return h; } inline unsigned mix(unsigned h, unsigned k) { const unsigned int m = 0x5bd1e995; const int r = 24; k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; return h; } } // namespace stingray_plugin_foundation #pragma GCC diagnostic push