blob: 5ea1db187e55c4acb6cf67f45f09d4b4f9faf1df [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include <string>
#include "base/util.h"
namespace mozc {
namespace {
const uint32 kFingerPrint32Seed = 0xfd12deff;
const uint32 kFingerPrintSeed0 = 0x6d6f;
const uint32 kFingerPrintSeed1 = 0x7a63;
} // namespace
#define mix(a,b,c) { \
a -= b; a -= c; a ^= (c >> 13); \
b -= c; b -= a; b ^= (a << 8); \
c -= a; c -= b; c ^= (b >> 13); \
a -= b; a -= c; a ^= (c >> 12); \
b -= c; b -= a; b ^= (a << 16); \
c -= a; c -= b; c ^= (b >> 5); \
a -= b; a -= c; a ^= (c >> 3); \
b -= c; b -= a; b ^= (a << 10); \
c -= a; c -= b; c ^= (b >> 15); \
}
uint32 Util::Fingerprint32(const string &key) {
return Fingerprint32WithSeed(key.data(), key.size(),
kFingerPrint32Seed);
}
uint32 Util::Fingerprint32(const char *str, size_t length) {
return Fingerprint32WithSeed(str, length,
kFingerPrint32Seed);
}
uint32 Util::Fingerprint32(const char *str) {
return Fingerprint32WithSeed(str, strlen(str),
kFingerPrint32Seed);
}
uint32 Util::Fingerprint32WithSeed(const string &key,
uint32 seed) {
return Fingerprint32WithSeed(key.data(), key.size(),
seed);
}
uint32 Util::Fingerprint32WithSeed(const char *str,
size_t length,
uint32 seed) {
uint32 len = static_cast<uint32>(length);
uint32 a = 0x9e3779b9;
uint32 b = a;
uint32 c = seed;
while (len >= 12) {
a += (str[0] + ((uint32)str[1] << 8) + ((uint32)str[2] << 16)
+ ((uint32)str[3] << 24));
b += (str[4] + ((uint32)str[5] << 8) + ((uint32)str[6] << 16)
+ ((uint32)str[7] << 24));
c += (str[8] + ((uint32)str[9] << 8) + ((uint32)str[10] << 16)
+ ((uint32)str[11] << 24));
mix(a, b, c);
str += 12;
len -= 12;
}
c += static_cast<uint32>(length);
switch (len) {
case 11:
c += ((uint32) str[10] << 24);
FALLTHROUGH_INTENDED;
case 10:
c += ((uint32) str[9] << 16);
FALLTHROUGH_INTENDED;
case 9:
c += ((uint32) str[8] << 8);
FALLTHROUGH_INTENDED;
case 8:
b += ((uint32) str[7] << 24);
FALLTHROUGH_INTENDED;
case 7:
b += ((uint32) str[6] << 16);
FALLTHROUGH_INTENDED;
case 6:
b += ((uint32) str[5] << 8);
FALLTHROUGH_INTENDED;
case 5:
b += str[4];
FALLTHROUGH_INTENDED;
case 4:
a += ((uint32) str[3] << 24);
FALLTHROUGH_INTENDED;
case 3:
a += ((uint32) str[2] << 16);
FALLTHROUGH_INTENDED;
case 2:
a += ((uint32) str[1] << 8);
FALLTHROUGH_INTENDED;
case 1:
a += str[0];
break;
}
mix(a, b, c);
return c;
}
uint32 Util::Fingerprint32WithSeed(const char *str,
uint32 seed) {
return Fingerprint32WithSeed(str, strlen(str), seed);
}
uint32 Util::Fingerprint32WithSeed(uint32 num, uint32 seed) {
const char* str = reinterpret_cast<const char*>(&num);
return Fingerprint32WithSeed(str, sizeof(num), seed);
}
uint64 Util::Fingerprint(const string &key) {
return Fingerprint(key.data(), key.size());
}
uint64 Util::Fingerprint(const char *str, size_t length) {
return FingerprintWithSeed(str, length, kFingerPrintSeed0);
}
uint64 Util::FingerprintWithSeed(const string &str, uint32 seed) {
return FingerprintWithSeed(str.data(), str.size(), seed);
}
uint64 Util::FingerprintWithSeed(const char *str, size_t length, uint32 seed) {
const uint32 hi = Fingerprint32WithSeed(str, length, seed);
const uint32 lo = Fingerprint32WithSeed(str, length, kFingerPrintSeed1);
uint64 result = static_cast<uint64>(hi) << 32 | static_cast<uint64>(lo);
if ((hi == 0) && (lo < 2)) {
result ^= GG_ULONGLONG(0x130f9bef94a0a928);
}
return result;
}
} // namespace mozc