xpcom/glue/nsHashKeys.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:ce3275354720
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #ifndef nsTHashKeys_h__
7 #define nsTHashKeys_h__
8
9 #include "nsID.h"
10 #include "nsISupports.h"
11 #include "nsIHashable.h"
12 #include "nsAutoPtr.h"
13 #include "nsCOMPtr.h"
14 #include "pldhash.h"
15 #include <new>
16
17 #include "nsStringGlue.h"
18 #include "nsCRTGlue.h"
19 #include "nsUnicharUtils.h"
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "mozilla/HashFunctions.h"
25 #include "mozilla/Move.h"
26
27 namespace mozilla {
28
29 // These are defined analogously to the HashString overloads in mfbt.
30
31 inline uint32_t
32 HashString(const nsAString& aStr)
33 {
34 return HashString(aStr.BeginReading(), aStr.Length());
35 }
36
37 inline uint32_t
38 HashString(const nsACString& aStr)
39 {
40 return HashString(aStr.BeginReading(), aStr.Length());
41 }
42
43 } // namespace mozilla
44
45 /** @file nsHashKeys.h
46 * standard HashKey classes for nsBaseHashtable and relatives. Each of these
47 * classes follows the nsTHashtable::EntryType specification
48 *
49 * Lightweight keytypes provided here:
50 * nsStringHashKey
51 * nsCStringHashKey
52 * nsUint32HashKey
53 * nsUint64HashKey
54 * nsFloatHashKey
55 * nsPtrHashkey
56 * nsClearingPtrHashKey
57 * nsVoidPtrHashKey
58 * nsClearingVoidPtrHashKey
59 * nsISupportsHashKey
60 * nsIDHashKey
61 * nsDepCharHashKey
62 * nsCharPtrHashKey
63 * nsUnicharPtrHashKey
64 * nsHashableHashKey
65 * nsGenericHashKey
66 */
67
68 /**
69 * hashkey wrapper using nsAString KeyType
70 *
71 * @see nsTHashtable::EntryType for specification
72 */
73 class nsStringHashKey : public PLDHashEntryHdr
74 {
75 public:
76 typedef const nsAString& KeyType;
77 typedef const nsAString* KeyTypePointer;
78
79 nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) { }
80 nsStringHashKey(const nsStringHashKey& toCopy) : mStr(toCopy.mStr) { }
81 ~nsStringHashKey() { }
82
83 KeyType GetKey() const { return mStr; }
84 bool KeyEquals(const KeyTypePointer aKey) const
85 {
86 return mStr.Equals(*aKey);
87 }
88
89 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
90 static PLDHashNumber HashKey(const KeyTypePointer aKey)
91 {
92 return mozilla::HashString(*aKey);
93 }
94 enum { ALLOW_MEMMOVE = true };
95
96 private:
97 const nsString mStr;
98 };
99
100 #ifdef MOZILLA_INTERNAL_API
101
102 /**
103 * hashkey wrapper using nsAString KeyType
104 *
105 * This is internal-API only because nsCaseInsensitiveStringComparator is
106 * internal-only.
107 *
108 * @see nsTHashtable::EntryType for specification
109 */
110 class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
111 {
112 public:
113 typedef const nsAString& KeyType;
114 typedef const nsAString* KeyTypePointer;
115
116 nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey
117 nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
118 ~nsStringCaseInsensitiveHashKey() { }
119
120 KeyType GetKey() const { return mStr; }
121 bool KeyEquals(const KeyTypePointer aKey) const
122 {
123 return mStr.Equals(*aKey, nsCaseInsensitiveStringComparator());
124 }
125
126 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
127 static PLDHashNumber HashKey(const KeyTypePointer aKey)
128 {
129 nsAutoString tmKey(*aKey);
130 ToLowerCase(tmKey);
131 return mozilla::HashString(tmKey);
132 }
133 enum { ALLOW_MEMMOVE = true };
134
135 private:
136 const nsString mStr;
137 };
138
139 #endif
140
141 /**
142 * hashkey wrapper using nsACString KeyType
143 *
144 * @see nsTHashtable::EntryType for specification
145 */
146 class nsCStringHashKey : public PLDHashEntryHdr
147 {
148 public:
149 typedef const nsACString& KeyType;
150 typedef const nsACString* KeyTypePointer;
151
152 nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) { }
153 nsCStringHashKey(const nsCStringHashKey& toCopy) : mStr(toCopy.mStr) { }
154 ~nsCStringHashKey() { }
155
156 KeyType GetKey() const { return mStr; }
157
158 bool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
159
160 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
161 static PLDHashNumber HashKey(KeyTypePointer aKey)
162 {
163 return mozilla::HashString(*aKey);
164 }
165 enum { ALLOW_MEMMOVE = true };
166
167 private:
168 const nsCString mStr;
169 };
170
171 /**
172 * hashkey wrapper using uint32_t KeyType
173 *
174 * @see nsTHashtable::EntryType for specification
175 */
176 class nsUint32HashKey : public PLDHashEntryHdr
177 {
178 public:
179 typedef const uint32_t& KeyType;
180 typedef const uint32_t* KeyTypePointer;
181
182 nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
183 nsUint32HashKey(const nsUint32HashKey& toCopy) : mValue(toCopy.mValue) { }
184 ~nsUint32HashKey() { }
185
186 KeyType GetKey() const { return mValue; }
187 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
188
189 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
190 static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
191 enum { ALLOW_MEMMOVE = true };
192
193 private:
194 const uint32_t mValue;
195 };
196
197 /**
198 * hashkey wrapper using uint64_t KeyType
199 *
200 * @see nsTHashtable::EntryType for specification
201 */
202 class nsUint64HashKey : public PLDHashEntryHdr
203 {
204 public:
205 typedef const uint64_t& KeyType;
206 typedef const uint64_t* KeyTypePointer;
207
208 nsUint64HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
209 nsUint64HashKey(const nsUint64HashKey& toCopy) : mValue(toCopy.mValue) { }
210 ~nsUint64HashKey() { }
211
212 KeyType GetKey() const { return mValue; }
213 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
214
215 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
216 static PLDHashNumber HashKey(KeyTypePointer aKey) { return PLDHashNumber(*aKey); }
217 enum { ALLOW_MEMMOVE = true };
218
219 private:
220 const uint64_t mValue;
221 };
222
223 /**
224 * hashkey wrapper using float KeyType
225 *
226 * @see nsTHashtable::EntryType for specification
227 */
228 class nsFloatHashKey : public PLDHashEntryHdr
229 {
230 public:
231 typedef const float& KeyType;
232 typedef const float* KeyTypePointer;
233
234 nsFloatHashKey(KeyTypePointer aKey) : mValue(*aKey) { }
235 nsFloatHashKey(const nsFloatHashKey& toCopy) : mValue(toCopy.mValue) { }
236 ~nsFloatHashKey() { }
237
238 KeyType GetKey() const { return mValue; }
239 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
240
241 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
242 static PLDHashNumber HashKey(KeyTypePointer aKey) { return *reinterpret_cast<const uint32_t*>(aKey); }
243 enum { ALLOW_MEMMOVE = true };
244
245 private:
246 const float mValue;
247 };
248
249 /**
250 * hashkey wrapper using nsISupports* KeyType
251 *
252 * @see nsTHashtable::EntryType for specification
253 */
254 class nsISupportsHashKey : public PLDHashEntryHdr
255 {
256 public:
257 typedef nsISupports* KeyType;
258 typedef const nsISupports* KeyTypePointer;
259
260 nsISupportsHashKey(const nsISupports* key) :
261 mSupports(const_cast<nsISupports*>(key)) { }
262 nsISupportsHashKey(const nsISupportsHashKey& toCopy) :
263 mSupports(toCopy.mSupports) { }
264 ~nsISupportsHashKey() { }
265
266 KeyType GetKey() const { return mSupports; }
267
268 bool KeyEquals(KeyTypePointer aKey) const { return aKey == mSupports; }
269
270 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
271 static PLDHashNumber HashKey(KeyTypePointer aKey)
272 {
273 return NS_PTR_TO_INT32(aKey) >>2;
274 }
275 enum { ALLOW_MEMMOVE = true };
276
277 private:
278 nsCOMPtr<nsISupports> mSupports;
279 };
280
281 /**
282 * hashkey wrapper using refcounted * KeyType
283 *
284 * @see nsTHashtable::EntryType for specification
285 */
286 template<class T>
287 class nsRefPtrHashKey : public PLDHashEntryHdr
288 {
289 public:
290 typedef T* KeyType;
291 typedef const T* KeyTypePointer;
292
293 nsRefPtrHashKey(const T* key) :
294 mKey(const_cast<T*>(key)) { }
295 nsRefPtrHashKey(const nsRefPtrHashKey& toCopy) :
296 mKey(toCopy.mKey) { }
297 ~nsRefPtrHashKey() { }
298
299 KeyType GetKey() const { return mKey; }
300
301 bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
302
303 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
304 static PLDHashNumber HashKey(KeyTypePointer aKey)
305 {
306 return NS_PTR_TO_INT32(aKey) >>2;
307 }
308 enum { ALLOW_MEMMOVE = true };
309
310 private:
311 nsRefPtr<T> mKey;
312 };
313
314 template <class T>
315 inline void
316 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
317 nsRefPtrHashKey<T>& aField,
318 const char* aName,
319 uint32_t aFlags = 0)
320 {
321 CycleCollectionNoteChild(aCallback, aField.GetKey(), aName, aFlags);
322 }
323
324 /**
325 * hashkey wrapper using T* KeyType
326 *
327 * @see nsTHashtable::EntryType for specification
328 */
329 template<class T>
330 class nsPtrHashKey : public PLDHashEntryHdr
331 {
332 public:
333 typedef T *KeyType;
334 typedef const T *KeyTypePointer;
335
336 nsPtrHashKey(const T *key) : mKey(const_cast<T*>(key)) {}
337 nsPtrHashKey(const nsPtrHashKey<T> &toCopy) : mKey(toCopy.mKey) {}
338 ~nsPtrHashKey() {}
339
340 KeyType GetKey() const { return mKey; }
341
342 bool KeyEquals(KeyTypePointer key) const { return key == mKey; }
343
344 static KeyTypePointer KeyToPointer(KeyType key) { return key; }
345 static PLDHashNumber HashKey(KeyTypePointer key)
346 {
347 return NS_PTR_TO_INT32(key) >> 2;
348 }
349 enum { ALLOW_MEMMOVE = true };
350
351 protected:
352 T *mKey;
353 };
354
355 /**
356 * hashkey wrapper using T* KeyType that sets key to nullptr upon
357 * destruction. Relevant only in cases where a memory pointer-scanner
358 * like valgrind might get confused about stale references.
359 *
360 * @see nsTHashtable::EntryType for specification
361 */
362
363 template<class T>
364 class nsClearingPtrHashKey : public nsPtrHashKey<T>
365 {
366 public:
367 nsClearingPtrHashKey(const T *key) : nsPtrHashKey<T>(key) {}
368 nsClearingPtrHashKey(const nsClearingPtrHashKey<T> &toCopy) :
369 nsPtrHashKey<T>(toCopy) {}
370 ~nsClearingPtrHashKey() { nsPtrHashKey<T>::mKey = nullptr; }
371 };
372
373 typedef nsPtrHashKey<const void> nsVoidPtrHashKey;
374 typedef nsClearingPtrHashKey<const void> nsClearingVoidPtrHashKey;
375
376 /**
377 * hashkey wrapper using a function pointer KeyType
378 *
379 * @see nsTHashtable::EntryType for specification
380 */
381 template<class T>
382 class nsFuncPtrHashKey : public PLDHashEntryHdr
383 {
384 public:
385 typedef T &KeyType;
386 typedef const T *KeyTypePointer;
387
388 nsFuncPtrHashKey(const T *key) : mKey(*const_cast<T*>(key)) {}
389 nsFuncPtrHashKey(const nsFuncPtrHashKey<T> &toCopy) : mKey(toCopy.mKey) {}
390 ~nsFuncPtrHashKey() {}
391
392 KeyType GetKey() const { return const_cast<T&>(mKey); }
393
394 bool KeyEquals(KeyTypePointer key) const { return *key == mKey; }
395
396 static KeyTypePointer KeyToPointer(KeyType key) { return &key; }
397 static PLDHashNumber HashKey(KeyTypePointer key)
398 {
399 return NS_PTR_TO_INT32(*key) >> 2;
400 }
401 enum { ALLOW_MEMMOVE = true };
402
403 protected:
404 T mKey;
405 };
406
407 /**
408 * hashkey wrapper using nsID KeyType
409 *
410 * @see nsTHashtable::EntryType for specification
411 */
412 class nsIDHashKey : public PLDHashEntryHdr
413 {
414 public:
415 typedef const nsID& KeyType;
416 typedef const nsID* KeyTypePointer;
417
418 nsIDHashKey(const nsID* inID) : mID(*inID) { }
419 nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { }
420 ~nsIDHashKey() { }
421
422 KeyType GetKey() const { return mID; }
423
424 bool KeyEquals(KeyTypePointer aKey) const { return aKey->Equals(mID); }
425
426 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
427 static PLDHashNumber HashKey(KeyTypePointer aKey)
428 {
429 // Hash the nsID object's raw bytes.
430 return mozilla::HashBytes(aKey, sizeof(KeyType));
431 }
432
433 enum { ALLOW_MEMMOVE = true };
434
435 private:
436 const nsID mID;
437 };
438
439 /**
440 * hashkey wrapper for "dependent" const char*; this class does not "own"
441 * its string pointer.
442 *
443 * This class must only be used if the strings have a lifetime longer than
444 * the hashtable they occupy. This normally occurs only for static
445 * strings or strings that have been arena-allocated.
446 *
447 * @see nsTHashtable::EntryType for specification
448 */
449 class nsDepCharHashKey : public PLDHashEntryHdr
450 {
451 public:
452 typedef const char* KeyType;
453 typedef const char* KeyTypePointer;
454
455 nsDepCharHashKey(const char* aKey) { mKey = aKey; }
456 nsDepCharHashKey(const nsDepCharHashKey& toCopy) { mKey = toCopy.mKey; }
457 ~nsDepCharHashKey() { }
458
459 const char* GetKey() const { return mKey; }
460 bool KeyEquals(const char* aKey) const
461 {
462 return !strcmp(mKey, aKey);
463 }
464
465 static const char* KeyToPointer(const char* aKey) { return aKey; }
466 static PLDHashNumber HashKey(const char* aKey) { return mozilla::HashString(aKey); }
467 enum { ALLOW_MEMMOVE = true };
468
469 private:
470 const char* mKey;
471 };
472
473 /**
474 * hashkey wrapper for const char*; at construction, this class duplicates
475 * a string pointed to by the pointer so that it doesn't matter whether or not
476 * the string lives longer than the hash table.
477 */
478 class nsCharPtrHashKey : public PLDHashEntryHdr
479 {
480 public:
481 typedef const char* KeyType;
482 typedef const char* KeyTypePointer;
483
484 nsCharPtrHashKey(const char* aKey) : mKey(strdup(aKey)) { }
485 nsCharPtrHashKey(const nsCharPtrHashKey& toCopy) : mKey(strdup(toCopy.mKey)) { }
486
487 nsCharPtrHashKey(nsCharPtrHashKey&& other)
488 : mKey(other.mKey)
489 {
490 other.mKey = nullptr;
491 }
492
493 ~nsCharPtrHashKey() { if (mKey) free(const_cast<char *>(mKey)); }
494
495 const char* GetKey() const { return mKey; }
496 bool KeyEquals(KeyTypePointer aKey) const
497 {
498 return !strcmp(mKey, aKey);
499 }
500
501 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
502 static PLDHashNumber HashKey(KeyTypePointer aKey) { return mozilla::HashString(aKey); }
503
504 enum { ALLOW_MEMMOVE = true };
505
506 private:
507 const char* mKey;
508 };
509
510 /**
511 * hashkey wrapper for const char16_t*; at construction, this class duplicates
512 * a string pointed to by the pointer so that it doesn't matter whether or not
513 * the string lives longer than the hash table.
514 */
515 class nsUnicharPtrHashKey : public PLDHashEntryHdr
516 {
517 public:
518 typedef const char16_t* KeyType;
519 typedef const char16_t* KeyTypePointer;
520
521 nsUnicharPtrHashKey(const char16_t* aKey) : mKey(NS_strdup(aKey)) { }
522 nsUnicharPtrHashKey(const nsUnicharPtrHashKey& toCopy) : mKey(NS_strdup(toCopy.mKey)) { }
523
524 nsUnicharPtrHashKey(nsUnicharPtrHashKey&& other)
525 : mKey(other.mKey)
526 {
527 other.mKey = nullptr;
528 }
529
530 ~nsUnicharPtrHashKey() { if (mKey) NS_Free(const_cast<char16_t *>(mKey)); }
531
532 const char16_t* GetKey() const { return mKey; }
533 bool KeyEquals(KeyTypePointer aKey) const
534 {
535 return !NS_strcmp(mKey, aKey);
536 }
537
538 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
539 static PLDHashNumber HashKey(KeyTypePointer aKey) { return mozilla::HashString(aKey); }
540
541 enum { ALLOW_MEMMOVE = true };
542
543 private:
544 const char16_t* mKey;
545 };
546
547 /**
548 * Hashtable key class to use with objects that support nsIHashable
549 */
550 class nsHashableHashKey : public PLDHashEntryHdr
551 {
552 public:
553 typedef nsIHashable* KeyType;
554 typedef const nsIHashable* KeyTypePointer;
555
556 nsHashableHashKey(const nsIHashable* aKey) :
557 mKey(const_cast<nsIHashable*>(aKey)) { }
558 nsHashableHashKey(const nsHashableHashKey& toCopy) :
559 mKey(toCopy.mKey) { }
560 ~nsHashableHashKey() { }
561
562 nsIHashable* GetKey() const { return mKey; }
563
564 bool KeyEquals(const nsIHashable* aKey) const {
565 bool eq;
566 if (NS_SUCCEEDED(mKey->Equals(const_cast<nsIHashable*>(aKey), &eq))) {
567 return eq;
568 }
569 return false;
570 }
571
572 static const nsIHashable* KeyToPointer(nsIHashable* aKey) { return aKey; }
573 static PLDHashNumber HashKey(const nsIHashable* aKey) {
574 uint32_t code = 8888; // magic number if GetHashCode fails :-(
575 #ifdef DEBUG
576 nsresult rv =
577 #endif
578 const_cast<nsIHashable*>(aKey)->GetHashCode(&code);
579 NS_ASSERTION(NS_SUCCEEDED(rv), "GetHashCode should not throw!");
580 return code;
581 }
582
583 enum { ALLOW_MEMMOVE = true };
584
585 private:
586 nsCOMPtr<nsIHashable> mKey;
587 };
588
589 /**
590 * Hashtable key class to use with objects for which Hash() and operator==()
591 * are defined.
592 */
593 template <typename T>
594 class nsGenericHashKey : public PLDHashEntryHdr
595 {
596 public:
597 typedef const T& KeyType;
598 typedef const T* KeyTypePointer;
599
600 nsGenericHashKey(KeyTypePointer aKey) : mKey(*aKey) { }
601 nsGenericHashKey(const nsGenericHashKey<T>& aOther) : mKey(aOther.mKey) { }
602
603 KeyType GetKey() const { return mKey; }
604 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mKey; }
605
606 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
607 static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->Hash(); }
608 enum { ALLOW_MEMMOVE = true };
609
610 private:
611 T mKey;
612 };
613
614 #endif // nsTHashKeys_h__

mercurial