uint32_t gpr_murmur_hash3(const void *key, size_t len, uint32_t seed) { const uint8_t *data = (const uint8_t *)key; const size_t nblocks = len / 4; int i; uint32_t h1 = seed; uint32_t k1; const uint32_t c1 = 0xcc9e2d51; const uint32_t c2 = 0x1b873593; const uint32_t *blocks = ((const uint32_t *)key) + nblocks; const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); /* body */ for (i = -(int)nblocks; i; i++) { memcpy(&k1, blocks + i, sizeof(uint32_t)); k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; h1 = ROTL32(h1, 13); h1 = h1 * 5 + 0xe6546b64; } k1 = 0; /* tail */ switch (len & 3) { case 3: k1 ^= ((uint32_t)tail[2]) << 16; /* fallthrough */ case 2: k1 ^= ((uint32_t)tail[1]) << 8; /* fallthrough */ case 1: k1 ^= tail[0]; k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; }; /* finalization */ h1 ^= (uint32_t)len; FMIX32(h1); return h1; }
gpr_uint32 gpr_murmur_hash3(const void *key, size_t len, gpr_uint32 seed) { const gpr_uint8 *data = (const gpr_uint8 *)key; const int nblocks = len / 4; int i; gpr_uint32 h1 = seed; gpr_uint32 k1; const gpr_uint32 c1 = 0xcc9e2d51; const gpr_uint32 c2 = 0x1b873593; const gpr_uint32 *blocks = (const uint32_t *)(data + nblocks * 4); const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); /* body */ for (i = -nblocks; i; i++) { k1 = GETBLOCK32(blocks, i); k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; h1 = ROTL32(h1, 13); h1 = h1 * 5 + 0xe6546b64; } k1 = 0; /* tail */ switch (len & 3) { case 3: k1 ^= tail[2] << 16; case 2: k1 ^= tail[1] << 8; case 1: k1 ^= tail[0]; k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; }; /* finalization */ h1 ^= len; FMIX32(h1); return h1; }