webengine/osswebengine/WebCore/platform/StringHash.h
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebCore/platform/StringHash.h	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StringHash_h
+#define StringHash_h
+
+#include "AtomicStringImpl.h"
+#include "PlatformString.h"
+#include <wtf/HashTraits.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WTF {
+
+    template<typename T> struct StrHash;
+
+    template<> struct StrHash<WebCore::StringImpl*> {
+        static unsigned hash(const WebCore::StringImpl* key) { return key->hash(); }
+        static bool equal(const WebCore::StringImpl* a, const WebCore::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;
+
+            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;
+        }
+    };
+    
+    template<> struct StrHash<WebCore::AtomicStringImpl*> : public StrHash<WebCore::StringImpl*> { };
+
+    template<> struct StrHash<RefPtr<WebCore::StringImpl> > {
+        static unsigned hash(const RefPtr<WebCore::StringImpl>& key) { return key->hash(); }
+        static bool equal(const RefPtr<WebCore::StringImpl>& a, const RefPtr<WebCore::StringImpl>& b)
+        {
+            return StrHash<WebCore::StringImpl*>::equal(a.get(), b.get());
+        }
+    };
+
+    template<> struct StrHash<WebCore::String> {
+        static unsigned hash(const WebCore::String& key) { return key.impl()->hash(); }
+        static bool equal(const WebCore::String& a, const WebCore::String& b)
+        {
+            return StrHash<WebCore::StringImpl*>::equal(a.impl(), b.impl());
+        }
+    };
+
+    template<typename T> struct CaseInsensitiveHash;
+
+    template<> class CaseInsensitiveHash<WebCore::StringImpl*> {
+    private:
+        // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+        static const unsigned PHI = 0x9e3779b9U;
+    public:
+        // Paul Hsieh's SuperFastHash
+        // http://www.azillionmonkeys.com/qed/hash.html
+        static unsigned hash(const WebCore::StringImpl* str)
+        {
+            unsigned l = str->length();
+            const UChar* s = str->characters();
+            uint32_t hash = PHI;
+            uint32_t tmp;
+            
+            int rem = l & 1;
+            l >>= 1;
+            
+            // Main loop
+            for (; l > 0; l--) {
+                hash += WTF::Unicode::foldCase(s[0]);
+                tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash;
+                hash = (hash << 16) ^ tmp;
+                s += 2;
+                hash += hash >> 11;
+            }
+            
+            // Handle end case
+            if (rem) {
+                hash += WTF::Unicode::foldCase(s[0]);
+                hash ^= hash << 11;
+                hash += hash >> 17;
+            }
+            
+            // Force "avalanching" of final 127 bits
+            hash ^= hash << 3;
+            hash += hash >> 5;
+            hash ^= hash << 2;
+            hash += hash >> 15;
+            hash ^= hash << 10;
+            
+            // this avoids ever returning a hash code of 0, since that is used to
+            // signal "hash not computed yet", using a value that is likely to be
+            // effectively the same as 0 when the low bits are masked
+            if (hash == 0)
+                hash = 0x80000000;
+            
+            return hash;
+        }
+        
+        static unsigned hash(const char* str, unsigned length)
+        {
+            // This hash is designed to work on 16-bit chunks at a time. But since the normal case
+            // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
+            // were 16-bit chunks, which will give matching results.
+
+            unsigned l = length;
+            const char* s = str;
+            uint32_t hash = PHI;
+            uint32_t tmp;
+            
+            int rem = l & 1;
+            l >>= 1;
+            
+            // Main loop
+            for (; l > 0; l--) {
+                hash += WTF::Unicode::foldCase(s[0]);
+                tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash;
+                hash = (hash << 16) ^ tmp;
+                s += 2;
+                hash += hash >> 11;
+            }
+            
+            // Handle end case
+            if (rem) {
+                hash += WTF::Unicode::foldCase(s[0]);
+                hash ^= hash << 11;
+                hash += hash >> 17;
+            }
+            
+            // Force "avalanching" of final 127 bits
+            hash ^= hash << 3;
+            hash += hash >> 5;
+            hash ^= hash << 2;
+            hash += hash >> 15;
+            hash ^= hash << 10;
+            
+            // this avoids ever returning a hash code of 0, since that is used to
+            // signal "hash not computed yet", using a value that is likely to be
+            // effectively the same as 0 when the low bits are masked
+            if (hash == 0)
+                hash = 0x80000000;
+            
+            return hash;
+        }
+        
+        static bool equal(const WebCore::StringImpl* a, const WebCore::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;
+        }
+    };
+
+    template<> struct CaseInsensitiveHash<WebCore::AtomicStringImpl*> : public CaseInsensitiveHash<WebCore::StringImpl*> { };
+
+    template<> struct CaseInsensitiveHash<RefPtr<WebCore::StringImpl> > {
+        static unsigned hash(const RefPtr<WebCore::StringImpl>& key) 
+        {
+            return CaseInsensitiveHash<WebCore::StringImpl*>::hash(key.get());
+        }
+
+        static bool equal(const RefPtr<WebCore::StringImpl>& a, const RefPtr<WebCore::StringImpl>& b)
+        {
+            return CaseInsensitiveHash<WebCore::StringImpl*>::equal(a.get(), b.get());
+        }
+    };
+
+    template<> struct CaseInsensitiveHash<WebCore::String> {
+        static unsigned hash(const WebCore::String& key)
+        {
+            return CaseInsensitiveHash<WebCore::StringImpl*>::hash(key.impl());
+        }
+        static bool equal(const WebCore::String& a, const WebCore::String& b)
+        {
+            return CaseInsensitiveHash<WebCore::StringImpl*>::equal(a.impl(), b.impl());
+        }
+    };
+
+    // store WebCore::String as StringImpl*
+
+    template<> struct HashTraits<WebCore::String> : GenericHashTraits<WebCore::String> {
+        typedef HashTraits<WebCore::StringImpl*>::StorageTraits StorageTraits;
+        typedef StorageTraits::TraitType StorageType;
+        static const bool emptyValueIsZero = true;
+        static const bool needsRef = true;
+        
+        typedef union { 
+            WebCore::StringImpl* m_p; 
+            StorageType m_s; 
+        } UnionType;
+
+        static void ref(const StorageType& s) { ref(reinterpret_cast<const UnionType*>(&s)->m_p); }
+        static void deref(const StorageType& s) { deref(reinterpret_cast<const UnionType*>(&s)->m_p); }
+        
+        static void ref(const WebCore::StringImpl* str) { if (str) const_cast<WebCore::StringImpl*>(str)->ref(); }
+        static void deref(const WebCore::StringImpl* str) { if (str) const_cast<WebCore::StringImpl*>(str)->deref(); }
+    };
+
+    // share code between StringImpl*, RefPtr<StringImpl>, and String
+
+    template<> struct HashKeyStorageTraits<StrHash<RefPtr<WebCore::StringImpl> >, HashTraits<RefPtr<WebCore::StringImpl> > > {
+        typedef StrHash<WebCore::StringImpl*> Hash;
+        typedef HashTraits<WebCore::StringImpl*> Traits;
+    };
+    template<> struct HashKeyStorageTraits<StrHash<WebCore::String>, HashTraits<WebCore::String> > {
+        typedef StrHash<WebCore::StringImpl*> Hash;
+        typedef HashTraits<WebCore::StringImpl*> Traits;
+    };
+
+    template<> struct HashKeyStorageTraits<CaseInsensitiveHash<RefPtr<WebCore::StringImpl> >, HashTraits<RefPtr<WebCore::StringImpl> > > {
+        typedef CaseInsensitiveHash<WebCore::StringImpl*> Hash;
+        typedef HashTraits<WebCore::StringImpl*> Traits;
+    };
+    template<> struct HashKeyStorageTraits<CaseInsensitiveHash<WebCore::String>, HashTraits<WebCore::String> > {
+        typedef CaseInsensitiveHash<WebCore::StringImpl*> Hash;
+        typedef HashTraits<WebCore::StringImpl*> Traits;
+    };
+
+}
+
+using WTF::CaseInsensitiveHash;
+
+#endif