/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkChecksum.h"
uint32_t SkChecksum::Murmur3(const void* data, size_t bytes, uint32_t seed) {
// Use may_alias to remind the compiler we're intentionally violating strict aliasing,
// and so not to apply strict-aliasing-based optimizations.
typedef uint32_t SK_ATTRIBUTE(may_alias) aliased_uint32_t;
typedef uint8_t SK_ATTRIBUTE(may_alias) aliased_uint8_t;
// Handle 4 bytes at a time while possible.
const aliased_uint32_t* safe_data = (const aliased_uint32_t*)data;
const size_t words = bytes/4;
uint32_t hash = seed;
for (size_t i = 0; i < words; i++) {
uint32_t k = safe_data[i];
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17);
k *= 0x1b873593;
hash ^= k;
hash = (hash << 13) | (hash >> 19);
hash *= 5;
hash += 0xe6546b64;
}
// Handle last 0-3 bytes.
const aliased_uint8_t* safe_tail = (const uint8_t*)(safe_data + words);
uint32_t k = 0;
switch (bytes & 3) {
case 3: k ^= safe_tail[2] << 16;
case 2: k ^= safe_tail[1] << 8;
case 1: k ^= safe_tail[0] << 0;
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17);
k *= 0x1b873593;
hash ^= k;
}
hash ^= bytes;
return SkChecksum::Mix(hash);
}