#ifndef StringHash_h
#define StringHash_h
#include "AtomicString.h"
#include "WTFString.h"
#include <wtf/Forward.h>
#include <wtf/HashTraits.h>
#include <wtf/StringHasher.h>
#include <wtf/unicode/Unicode.h>
namespace WTF {
struct StringHash {
static unsigned hash(StringImpl* key) { return key->hash(); }
static bool equal(const StringImpl* a, const StringImpl* b)
{
if (a == b)
return true;
if (!a || !b)
return false;
unsigned aLength = a->length();
unsigned bLength = b->length();
if (aLength != bLength)
return false;
#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC)
const UChar* aChars = a->characters();
const UChar* bChars = b->characters();
for (unsigned i = 0; i != aLength; ++i) {
if (*aChars++ != *bChars++)
return false;
}
return true;
#else
const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters());
const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters());
unsigned halfLength = aLength >> 1;
for (unsigned i = 0; i != halfLength; ++i)
if (*aChars++ != *bChars++)
return false;
if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars))
return false;
return true;
#endif
}
static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); }
static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
{
return equal(a.get(), b.get());
}
static unsigned hash(const String& key) { return key.impl()->hash(); }
static bool equal(const String& a, const String& b)
{
return equal(a.impl(), b.impl());
}
static const bool safeToCompareToEmptyOrDeleted = false;
};
class CaseFoldingHash {
public:
template<typename T> static inline UChar foldCase(T ch)
{
return WTF::Unicode::foldCase(ch);
}
static unsigned hash(const UChar* data, unsigned length)
{
return StringHasher::computeHash<UChar, foldCase<UChar> >(data, length);
}
static unsigned hash(StringImpl* str)
{
return hash(str->characters(), str->length());
}
static unsigned hash(const char* data, unsigned length)
{
return StringHasher::computeHash<char, foldCase<char> >(data, length);
}
static bool equal(const StringImpl* a, const StringImpl* b)
{
if (a == b)
return true;
if (!a || !b)
return false;
unsigned length = a->length();
if (length != b->length())
return false;
return WTF::Unicode::umemcasecmp(a->characters(), b->characters(), length) == 0;
}
static unsigned hash(const RefPtr<StringImpl>& key)
{
return hash(key.get());
}
static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
{
return equal(a.get(), b.get());
}
static unsigned hash(const String& key)
{
return hash(key.impl());
}
static unsigned hash(const AtomicString& key)
{
return hash(key.impl());
}
static bool equal(const String& a, const String& b)
{
return equal(a.impl(), b.impl());
}
static bool equal(const AtomicString& a, const AtomicString& b)
{
return (a == b) || equal(a.impl(), b.impl());
}
static const bool safeToCompareToEmptyOrDeleted = false;
};
struct AlreadyHashed : IntHash<unsigned> {
static unsigned hash(unsigned key) { return key; }
static unsigned avoidDeletedValue(unsigned hash)
{
ASSERT(hash);
unsigned newHash = hash | (!(hash + 1) << 31);
ASSERT(newHash);
ASSERT(newHash != 0xFFFFFFFF);
return newHash;
}
};
template<> struct HashTraits<String> : SimpleClassHashTraits<String> { };
}
using WTF::StringHash;
using WTF::CaseFoldingHash;
using WTF::AlreadyHashed;
#endif