1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is C++ hashtable templates.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Benjamin Smedberg.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef nsTHashKeys_h__
39 : #define nsTHashKeys_h__
40 :
41 : #include "nsID.h"
42 : #include "nsISupports.h"
43 : #include "nsIHashable.h"
44 : #include "nsCOMPtr.h"
45 : #include "pldhash.h"
46 : #include NEW_H
47 :
48 : #include "nsStringGlue.h"
49 : #include "nsCRTGlue.h"
50 : #include "nsUnicharUtils.h"
51 :
52 : #include <stdlib.h>
53 : #include <string.h>
54 :
55 : #include "mozilla/HashFunctions.h"
56 :
57 : namespace mozilla {
58 :
59 : // These are defined analogously to the HashString overloads in mfbt.
60 :
61 : inline PRUint32
62 : HashString(const nsAString& aStr)
63 : {
64 : return HashString(aStr.BeginReading(), aStr.Length());
65 : }
66 :
67 : inline PRUint32
68 0 : HashString(const nsACString& aStr)
69 : {
70 0 : return HashString(aStr.BeginReading(), aStr.Length());
71 : }
72 :
73 : } // namespace mozilla
74 :
75 : /** @file nsHashKeys.h
76 : * standard HashKey classes for nsBaseHashtable and relatives. Each of these
77 : * classes follows the nsTHashtable::EntryType specification
78 : *
79 : * Lightweight keytypes provided here:
80 : * nsStringHashKey
81 : * nsCStringHashKey
82 : * nsUint32HashKey
83 : * nsUint64HashKey
84 : * nsPtrHashkey
85 : * nsClearingPtrHashKey
86 : * nsVoidPtrHashKey
87 : * nsClearingVoidPtrHashKey
88 : * nsISupportsHashKey
89 : * nsIDHashKey
90 : * nsDepCharHashKey
91 : * nsCharPtrHashKey
92 : * nsUnicharPtrHashKey
93 : * nsHashableHashKey
94 : */
95 :
96 : /**
97 : * hashkey wrapper using nsAString KeyType
98 : *
99 : * @see nsTHashtable::EntryType for specification
100 : */
101 : class nsStringHashKey : public PLDHashEntryHdr
102 : {
103 : public:
104 : typedef const nsAString& KeyType;
105 : typedef const nsAString* KeyTypePointer;
106 :
107 : nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) { }
108 : nsStringHashKey(const nsStringHashKey& toCopy) : mStr(toCopy.mStr) { }
109 : ~nsStringHashKey() { }
110 :
111 : KeyType GetKey() const { return mStr; }
112 : bool KeyEquals(const KeyTypePointer aKey) const
113 : {
114 : return mStr.Equals(*aKey);
115 : }
116 :
117 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
118 : static PLDHashNumber HashKey(const KeyTypePointer aKey)
119 : {
120 : return mozilla::HashString(*aKey);
121 : }
122 : enum { ALLOW_MEMMOVE = true };
123 :
124 : private:
125 : const nsString mStr;
126 : };
127 :
128 : #ifdef MOZILLA_INTERNAL_API
129 :
130 : /**
131 : * hashkey wrapper using nsAString KeyType
132 : *
133 : * This is internal-API only because nsCaseInsensitiveStringComparator is
134 : * internal-only.
135 : *
136 : * @see nsTHashtable::EntryType for specification
137 : */
138 : class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
139 : {
140 : public:
141 : typedef const nsAString& KeyType;
142 : typedef const nsAString* KeyTypePointer;
143 :
144 : nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
145 : nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
146 : ~nsStringCaseInsensitiveHashKey() { }
147 :
148 : KeyType GetKey() const { return mStr; }
149 : bool KeyEquals(const KeyTypePointer aKey) const
150 : {
151 : return mStr.Equals(*aKey, nsCaseInsensitiveStringComparator());
152 : }
153 :
154 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
155 : static PLDHashNumber HashKey(const KeyTypePointer aKey)
156 : {
157 : nsAutoString tmKey(*aKey);
158 : ToLowerCase(tmKey);
159 : return mozilla::HashString(tmKey);
160 : }
161 : enum { ALLOW_MEMMOVE = true };
162 :
163 : private:
164 : const nsString mStr;
165 : };
166 :
167 : #endif
168 :
169 : /**
170 : * hashkey wrapper using nsACString KeyType
171 : *
172 : * @see nsTHashtable::EntryType for specification
173 : */
174 : class nsCStringHashKey : public PLDHashEntryHdr
175 : {
176 : public:
177 : typedef const nsACString& KeyType;
178 : typedef const nsACString* KeyTypePointer;
179 :
180 0 : nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) { }
181 : nsCStringHashKey(const nsCStringHashKey& toCopy) : mStr(toCopy.mStr) { }
182 0 : ~nsCStringHashKey() { }
183 :
184 : KeyType GetKey() const { return mStr; }
185 :
186 0 : bool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
187 :
188 0 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
189 0 : static PLDHashNumber HashKey(KeyTypePointer aKey)
190 : {
191 0 : return mozilla::HashString(*aKey);
192 : }
193 : enum { ALLOW_MEMMOVE = true };
194 :
195 : private:
196 : const nsCString mStr;
197 : };
198 :
199 : /**
200 : * hashkey wrapper using PRUint32 KeyType
201 : *
202 : * @see nsTHashtable::EntryType for specification
203 : */
204 : class nsUint32HashKey : public PLDHashEntryHdr
205 : {
206 : public:
207 : typedef const PRUint32& KeyType;
208 : typedef const PRUint32* KeyTypePointer;
209 :
210 : nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
211 : nsUint32HashKey(const nsUint32HashKey& toCopy) : mValue(toCopy.mValue) { }
212 : ~nsUint32HashKey() { }
213 :
214 : KeyType GetKey() const { return mValue; }
215 : bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
216 :
217 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
218 : static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
219 : enum { ALLOW_MEMMOVE = true };
220 :
221 : private:
222 : const PRUint32 mValue;
223 : };
224 :
225 : /**
226 : * hashkey wrapper using PRUint64 KeyType
227 : *
228 : * @see nsTHashtable::EntryType for specification
229 : */
230 : class nsUint64HashKey : public PLDHashEntryHdr
231 : {
232 : public:
233 : typedef const PRUint64& KeyType;
234 : typedef const PRUint64* KeyTypePointer;
235 :
236 : nsUint64HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
237 : nsUint64HashKey(const nsUint64HashKey& toCopy) : mValue(toCopy.mValue) { }
238 : ~nsUint64HashKey() { }
239 :
240 : KeyType GetKey() const { return mValue; }
241 : bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
242 :
243 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
244 : static PLDHashNumber HashKey(KeyTypePointer aKey) { return PLDHashNumber(*aKey); }
245 : enum { ALLOW_MEMMOVE = true };
246 :
247 : private:
248 : const PRUint64 mValue;
249 : };
250 :
251 : /**
252 : * hashkey wrapper using nsISupports* KeyType
253 : *
254 : * @see nsTHashtable::EntryType for specification
255 : */
256 : class nsISupportsHashKey : public PLDHashEntryHdr
257 : {
258 : public:
259 : typedef nsISupports* KeyType;
260 : typedef const nsISupports* KeyTypePointer;
261 :
262 : nsISupportsHashKey(const nsISupports* key) :
263 : mSupports(const_cast<nsISupports*>(key)) { }
264 : nsISupportsHashKey(const nsISupportsHashKey& toCopy) :
265 : mSupports(toCopy.mSupports) { }
266 : ~nsISupportsHashKey() { }
267 :
268 : KeyType GetKey() const { return mSupports; }
269 :
270 : bool KeyEquals(KeyTypePointer aKey) const { return aKey == mSupports; }
271 :
272 : static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
273 : static PLDHashNumber HashKey(KeyTypePointer aKey)
274 : {
275 : return NS_PTR_TO_INT32(aKey) >>2;
276 : }
277 : enum { ALLOW_MEMMOVE = true };
278 :
279 : private:
280 : nsCOMPtr<nsISupports> mSupports;
281 : };
282 :
283 : /**
284 : * hashkey wrapper using refcounted * KeyType
285 : *
286 : * @see nsTHashtable::EntryType for specification
287 : */
288 : template<class T>
289 : class nsRefPtrHashKey : public PLDHashEntryHdr
290 : {
291 : public:
292 : typedef T* KeyType;
293 : typedef const T* KeyTypePointer;
294 :
295 : nsRefPtrHashKey(const T* key) :
296 : mKey(const_cast<T*>(key)) { }
297 : nsRefPtrHashKey(const nsRefPtrHashKey& toCopy) :
298 : mKey(toCopy.mKey) { }
299 : ~nsRefPtrHashKey() { }
300 :
301 : KeyType GetKey() const { return mKey; }
302 :
303 : bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
304 :
305 : static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
306 : static PLDHashNumber HashKey(KeyTypePointer aKey)
307 : {
308 : return NS_PTR_TO_INT32(aKey) >>2;
309 : }
310 : enum { ALLOW_MEMMOVE = true };
311 :
312 : private:
313 : nsRefPtr<T> mKey;
314 : };
315 :
316 : /**
317 : * hashkey wrapper using T* KeyType
318 : *
319 : * @see nsTHashtable::EntryType for specification
320 : */
321 : template<class T>
322 : class nsPtrHashKey : public PLDHashEntryHdr
323 : {
324 : public:
325 : typedef T *KeyType;
326 : typedef const T *KeyTypePointer;
327 :
328 : nsPtrHashKey(const T *key) : mKey(const_cast<T*>(key)) {}
329 : nsPtrHashKey(const nsPtrHashKey<T> &toCopy) : mKey(toCopy.mKey) {}
330 : ~nsPtrHashKey() {}
331 :
332 : KeyType GetKey() const { return mKey; }
333 :
334 : bool KeyEquals(KeyTypePointer key) const { return key == mKey; }
335 :
336 : static KeyTypePointer KeyToPointer(KeyType key) { return key; }
337 : static PLDHashNumber HashKey(KeyTypePointer key)
338 : {
339 : return NS_PTR_TO_INT32(key) >> 2;
340 : }
341 : enum { ALLOW_MEMMOVE = true };
342 :
343 : protected:
344 : T *mKey;
345 : };
346 :
347 : /**
348 : * hashkey wrapper using T* KeyType that sets key to NULL upon
349 : * destruction. Relevant only in cases where a memory pointer-scanner
350 : * like valgrind might get confused about stale references.
351 : *
352 : * @see nsTHashtable::EntryType for specification
353 : */
354 :
355 : template<class T>
356 : class nsClearingPtrHashKey : public nsPtrHashKey<T>
357 : {
358 : public:
359 : nsClearingPtrHashKey(const T *key) : nsPtrHashKey<T>(key) {}
360 : nsClearingPtrHashKey(const nsClearingPtrHashKey<T> &toCopy) :
361 : nsPtrHashKey<T>(toCopy) {}
362 : ~nsClearingPtrHashKey() { nsPtrHashKey<T>::mKey = nsnull; }
363 : };
364 :
365 : typedef nsPtrHashKey<const void> nsVoidPtrHashKey;
366 : typedef nsClearingPtrHashKey<const void> nsClearingVoidPtrHashKey;
367 :
368 : /**
369 : * hashkey wrapper using nsID KeyType
370 : *
371 : * @see nsTHashtable::EntryType for specification
372 : */
373 : class nsIDHashKey : public PLDHashEntryHdr
374 : {
375 : public:
376 : typedef const nsID& KeyType;
377 : typedef const nsID* KeyTypePointer;
378 :
379 : nsIDHashKey(const nsID* inID) : mID(*inID) { }
380 : nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { }
381 : ~nsIDHashKey() { }
382 :
383 : KeyType GetKey() const { return mID; }
384 :
385 : bool KeyEquals(KeyTypePointer aKey) const { return aKey->Equals(mID); }
386 :
387 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
388 : static PLDHashNumber HashKey(KeyTypePointer aKey)
389 : {
390 : // Hash the nsID object's raw bytes.
391 : return mozilla::HashBytes(aKey, sizeof(KeyType));
392 : }
393 :
394 : enum { ALLOW_MEMMOVE = true };
395 :
396 : private:
397 : const nsID mID;
398 : };
399 :
400 : /**
401 : * hashkey wrapper for "dependent" const char*; this class does not "own"
402 : * its string pointer.
403 : *
404 : * This class must only be used if the strings have a lifetime longer than
405 : * the hashtable they occupy. This normally occurs only for static
406 : * strings or strings that have been arena-allocated.
407 : *
408 : * @see nsTHashtable::EntryType for specification
409 : */
410 : class nsDepCharHashKey : public PLDHashEntryHdr
411 : {
412 : public:
413 : typedef const char* KeyType;
414 : typedef const char* KeyTypePointer;
415 :
416 0 : nsDepCharHashKey(const char* aKey) { mKey = aKey; }
417 : nsDepCharHashKey(const nsDepCharHashKey& toCopy) { mKey = toCopy.mKey; }
418 0 : ~nsDepCharHashKey() { }
419 :
420 0 : const char* GetKey() const { return mKey; }
421 0 : bool KeyEquals(const char* aKey) const
422 : {
423 0 : return !strcmp(mKey, aKey);
424 : }
425 :
426 0 : static const char* KeyToPointer(const char* aKey) { return aKey; }
427 0 : static PLDHashNumber HashKey(const char* aKey) { return mozilla::HashString(aKey); }
428 : enum { ALLOW_MEMMOVE = true };
429 :
430 : private:
431 : const char* mKey;
432 : };
433 :
434 : /**
435 : * hashkey wrapper for const char*; at construction, this class duplicates
436 : * a string pointed to by the pointer so that it doesn't matter whether or not
437 : * the string lives longer than the hash table.
438 : */
439 : class nsCharPtrHashKey : public PLDHashEntryHdr
440 : {
441 : public:
442 : typedef const char* KeyType;
443 : typedef const char* KeyTypePointer;
444 :
445 0 : nsCharPtrHashKey(const char* aKey) : mKey(strdup(aKey)) { }
446 : nsCharPtrHashKey(const nsCharPtrHashKey& toCopy) : mKey(strdup(toCopy.mKey)) { }
447 0 : ~nsCharPtrHashKey() { if (mKey) free(const_cast<char *>(mKey)); }
448 :
449 : const char* GetKey() const { return mKey; }
450 0 : bool KeyEquals(KeyTypePointer aKey) const
451 : {
452 0 : return !strcmp(mKey, aKey);
453 : }
454 :
455 : static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
456 0 : static PLDHashNumber HashKey(KeyTypePointer aKey) { return mozilla::HashString(aKey); }
457 :
458 : enum { ALLOW_MEMMOVE = true };
459 :
460 : private:
461 : const char* mKey;
462 : };
463 :
464 : /**
465 : * hashkey wrapper for const PRUnichar*; at construction, this class duplicates
466 : * a string pointed to by the pointer so that it doesn't matter whether or not
467 : * the string lives longer than the hash table.
468 : */
469 : class nsUnicharPtrHashKey : public PLDHashEntryHdr
470 : {
471 : public:
472 : typedef const PRUnichar* KeyType;
473 : typedef const PRUnichar* KeyTypePointer;
474 :
475 : nsUnicharPtrHashKey(const PRUnichar* aKey) : mKey(NS_strdup(aKey)) { }
476 : nsUnicharPtrHashKey(const nsUnicharPtrHashKey& toCopy) : mKey(NS_strdup(toCopy.mKey)) { }
477 : ~nsUnicharPtrHashKey() { if (mKey) NS_Free(const_cast<PRUnichar *>(mKey)); }
478 :
479 : const PRUnichar* GetKey() const { return mKey; }
480 : bool KeyEquals(KeyTypePointer aKey) const
481 : {
482 : return !NS_strcmp(mKey, aKey);
483 : }
484 :
485 : static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
486 : static PLDHashNumber HashKey(KeyTypePointer aKey) { return mozilla::HashString(aKey); }
487 :
488 : enum { ALLOW_MEMMOVE = true };
489 :
490 : private:
491 : const PRUnichar* mKey;
492 : };
493 :
494 : /**
495 : * Hashtable key class to use with objects that support nsIHashable
496 : */
497 : class nsHashableHashKey : public PLDHashEntryHdr
498 : {
499 : public:
500 : typedef nsIHashable* KeyType;
501 : typedef const nsIHashable* KeyTypePointer;
502 :
503 : nsHashableHashKey(const nsIHashable* aKey) :
504 : mKey(const_cast<nsIHashable*>(aKey)) { }
505 : nsHashableHashKey(const nsHashableHashKey& toCopy) :
506 : mKey(toCopy.mKey) { }
507 : ~nsHashableHashKey() { }
508 :
509 : nsIHashable* GetKey() const { return mKey; }
510 :
511 : bool KeyEquals(const nsIHashable* aKey) const {
512 : bool eq;
513 : if (NS_SUCCEEDED(mKey->Equals(const_cast<nsIHashable*>(aKey), &eq))) {
514 : return eq;
515 : }
516 : return false;
517 : }
518 :
519 : static const nsIHashable* KeyToPointer(nsIHashable* aKey) { return aKey; }
520 : static PLDHashNumber HashKey(const nsIHashable* aKey) {
521 : PRUint32 code = 8888; // magic number if GetHashCode fails :-(
522 : #ifdef NS_DEBUG
523 : nsresult rv =
524 : #endif
525 : const_cast<nsIHashable*>(aKey)->GetHashCode(&code);
526 : NS_ASSERTION(NS_SUCCEEDED(rv), "GetHashCode should not throw!");
527 : return code;
528 : }
529 :
530 : enum { ALLOW_MEMMOVE = true };
531 :
532 : private:
533 : nsCOMPtr<nsIHashable> mKey;
534 : };
535 :
536 : #endif // nsTHashKeys_h__
|