• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2012, 2013 Apple Inc. All rights reserved
3  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21 
22 #ifndef StringHash_h
23 #define StringHash_h
24 
25 #include "wtf/text/AtomicString.h"
26 #include "wtf/HashTraits.h"
27 #include "wtf/StringHasher.h"
28 
29 namespace WTF {
30 
isEmptyValue(const String & value)31     inline bool HashTraits<String>::isEmptyValue(const String& value)
32     {
33         return value.isNull();
34     }
35 
36     // The hash() functions on StringHash and CaseFoldingHash do not support
37     // null strings. get(), contains(), and add() on HashMap<String,..., StringHash>
38     // cause a null-pointer dereference when passed null strings.
39 
40     // FIXME: We should really figure out a way to put the computeHash function that's
41     // currently a member function of StringImpl into this file so we can be a little
42     // closer to having all the nearly-identical hash functions in one place.
43 
44     struct StringHash {
hashStringHash45         static unsigned hash(StringImpl* key) { return key->hash(); }
equalStringHash46         static inline bool equal(const StringImpl* a, const StringImpl* b)
47         {
48             return equalNonNull(a, b);
49         }
50 
hashStringHash51         static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); }
equalStringHash52         static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
53         {
54             return equal(a.get(), b.get());
55         }
56 
hashStringHash57         static unsigned hash(const String& key) { return key.impl()->hash(); }
equalStringHash58         static bool equal(const String& a, const String& b)
59         {
60             return equal(a.impl(), b.impl());
61         }
62 
63         static const bool safeToCompareToEmptyOrDeleted = false;
64     };
65 
66     class CaseFoldingHash {
67     public:
foldCase(T ch)68         template<typename T> static inline UChar foldCase(T ch)
69         {
70             return WTF::Unicode::foldCase(ch);
71         }
72 
hash(const UChar * data,unsigned length)73         static unsigned hash(const UChar* data, unsigned length)
74         {
75             return StringHasher::computeHashAndMaskTop8Bits<UChar, foldCase<UChar> >(data, length);
76         }
77 
hash(StringImpl * str)78         static unsigned hash(StringImpl* str)
79         {
80             if (str->is8Bit())
81                 return hash(str->characters8(), str->length());
82             return hash(str->characters16(), str->length());
83         }
84 
hash(const LChar * data,unsigned length)85         static unsigned hash(const LChar* data, unsigned length)
86         {
87             return StringHasher::computeHashAndMaskTop8Bits<LChar, foldCase<LChar> >(data, length);
88         }
89 
hash(const char * data,unsigned length)90         static inline unsigned hash(const char* data, unsigned length)
91         {
92             return CaseFoldingHash::hash(reinterpret_cast<const LChar*>(data), length);
93         }
94 
equal(const StringImpl * a,const StringImpl * b)95         static inline bool equal(const StringImpl* a, const StringImpl* b)
96         {
97             return equalIgnoringCaseNonNull(a, b);
98         }
99 
hash(const RefPtr<StringImpl> & key)100         static unsigned hash(const RefPtr<StringImpl>& key)
101         {
102             return hash(key.get());
103         }
104 
equal(const RefPtr<StringImpl> & a,const RefPtr<StringImpl> & b)105         static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
106         {
107             return equal(a.get(), b.get());
108         }
109 
hash(const String & key)110         static unsigned hash(const String& key)
111         {
112             return hash(key.impl());
113         }
hash(const AtomicString & key)114         static unsigned hash(const AtomicString& key)
115         {
116             return hash(key.impl());
117         }
equal(const String & a,const String & b)118         static bool equal(const String& a, const String& b)
119         {
120             return equal(a.impl(), b.impl());
121         }
equal(const AtomicString & a,const AtomicString & b)122         static bool equal(const AtomicString& a, const AtomicString& b)
123         {
124             return (a == b) || equal(a.impl(), b.impl());
125         }
126 
127         static const bool safeToCompareToEmptyOrDeleted = false;
128     };
129 
130     // This hash can be used in cases where the key is a hash of a string, but we don't
131     // want to store the string. It's not really specific to string hashing, but all our
132     // current uses of it are for strings.
133     struct AlreadyHashed : IntHash<unsigned> {
hashAlreadyHashed134         static unsigned hash(unsigned key) { return key; }
135 
136         // To use a hash value as a key for a hash table, we need to eliminate the
137         // "deleted" value, which is negative one. That could be done by changing
138         // the string hash function to never generate negative one, but this works
139         // and is still relatively efficient.
avoidDeletedValueAlreadyHashed140         static unsigned avoidDeletedValue(unsigned hash)
141         {
142             ASSERT(hash);
143             unsigned newHash = hash | (!(hash + 1) << 31);
144             ASSERT(newHash);
145             ASSERT(newHash != 0xFFFFFFFF);
146             return newHash;
147         }
148     };
149 
150 }
151 
152 using WTF::AlreadyHashed;
153 using WTF::CaseFoldingHash;
154 using WTF::StringHash;
155 
156 #endif
157