1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3
* The contents of this file are subject to the Netscape Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/NPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is mozilla.org code.
15
* The Initial Developer of the Original Code is Netscape
16
* Communications Corporation. Portions created by Netscape are
17
* Copyright (C) 1998 Netscape Communications Corporation. All
21
* This Original Code has been modified by IBM Corporation.
22
* Modifications made by IBM described herein are
23
* Copyright (c) International Business Machines
26
* Modifications to Mozilla code or documentation
27
* identified per MPL Section 3.3
29
* Date Modified by Description of modification
30
* 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
36
#include "nsHashtable.h"
37
#include "nsReadableUtils.h"
38
#include "nsIObjectInputStream.h"
39
#include "nsIObjectOutputStream.h"
42
struct HTEntry : PLDHashEntryHdr
52
PR_STATIC_CALLBACK(PRBool)
53
matchKeyEntry(PLDHashTable*, const PLDHashEntryHdr* entry,
56
const HTEntry* hashEntry =
57
NS_STATIC_CAST(const HTEntry*, entry);
59
if (hashEntry->key == key)
62
const nsHashKey* otherKey = NS_REINTERPRET_CAST(const nsHashKey*, key);
63
return otherKey->Equals(hashEntry->key);
66
PR_STATIC_CALLBACK(PLDHashNumber)
67
hashKey(PLDHashTable* table, const void* key)
69
const nsHashKey* hashKey = NS_STATIC_CAST(const nsHashKey*, key);
71
return hashKey->HashCode();
74
PR_STATIC_CALLBACK(void)
75
clearHashEntry(PLDHashTable* table, PLDHashEntryHdr* entry)
77
HTEntry* hashEntry = NS_STATIC_CAST(HTEntry*, entry);
79
// leave it up to the nsHashKey destructor to free the "value"
80
delete hashEntry->key;
81
hashEntry->key = nsnull;
82
hashEntry->value = nsnull; // probably not necessary, but for
87
static const PLDHashTableOps hashtableOps = {
93
PL_DHashMoveEntryStub,
101
// Enumerator callback
104
struct _HashEnumerateArgs {
105
nsHashtableEnumFunc fn;
109
PR_STATIC_CALLBACK(PLDHashOperator)
110
hashEnumerate(PLDHashTable* table, PLDHashEntryHdr* hdr, PRUint32 i, void *arg)
112
_HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
113
HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
115
switch (thunk->fn(entry->key, entry->value, thunk->arg)) {
116
case kHashEnumerateNext:
117
return PL_DHASH_NEXT;
118
case kHashEnumerateRemove:
119
return PL_DHASH_REMOVE;
121
return PL_DHASH_STOP;
128
nsHashKey::~nsHashKey(void)
130
MOZ_COUNT_DTOR(nsHashKey);
134
nsHashKey::Write(nsIObjectOutputStream* aStream) const
136
NS_NOTREACHED("oops");
137
return NS_ERROR_NOT_IMPLEMENTED;
140
MOZ_DECL_CTOR_COUNTER(nsHashtable)
142
nsHashtable::nsHashtable(PRUint32 aInitSize, PRBool threadSafe)
143
: mLock(NULL), mEnumerating(PR_FALSE)
145
MOZ_COUNT_CTOR(nsHashtable);
147
PRBool result = PL_DHashTableInit(&mHashtable, &hashtableOps, nsnull,
148
sizeof(HTEntry), aInitSize);
150
NS_ASSERTION(result, "Hashtable failed to initialize");
152
// make sure we detect this later
154
mHashtable.ops = nsnull;
157
mLock = PR_NewLock();
159
// Cannot create a lock. If running on a multiprocessing system
160
// we are sure to die.
161
PR_ASSERT(mLock != NULL);
167
nsHashtable::~nsHashtable() {
168
MOZ_COUNT_DTOR(nsHashtable);
170
PL_DHashTableFinish(&mHashtable);
171
if (mLock) PR_DestroyLock(mLock);
174
PRBool nsHashtable::Exists(nsHashKey *aKey)
176
if (mLock) PR_Lock(mLock);
181
PLDHashEntryHdr *entry =
182
PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP);
184
PRBool exists = PL_DHASH_ENTRY_IS_BUSY(entry);
186
if (mLock) PR_Unlock(mLock);
191
void *nsHashtable::Put(nsHashKey *aKey, void *aData)
195
if (!mHashtable.ops) return nsnull;
197
if (mLock) PR_Lock(mLock);
199
// shouldn't be adding an item during enumeration
200
PR_ASSERT(!mEnumerating);
203
NS_STATIC_CAST(HTEntry*,
204
PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_ADD));
206
if (entry) { // don't return early, or you'll be locked!
208
// existing entry, need to boot the old value
210
entry->value = aData;
212
// new entry (leave res == null)
213
entry->key = aKey->Clone();
214
entry->value = aData;
218
if (mLock) PR_Unlock(mLock);
223
void *nsHashtable::Get(nsHashKey *aKey)
225
if (!mHashtable.ops) return nsnull;
227
if (mLock) PR_Lock(mLock);
230
NS_STATIC_CAST(HTEntry*,
231
PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP));
232
void *ret = PL_DHASH_ENTRY_IS_BUSY(entry) ? entry->value : nsnull;
234
if (mLock) PR_Unlock(mLock);
239
void *nsHashtable::Remove(nsHashKey *aKey)
241
if (!mHashtable.ops) return nsnull;
243
if (mLock) PR_Lock(mLock);
245
// shouldn't be adding an item during enumeration
246
PR_ASSERT(!mEnumerating);
249
// need to see if the entry is actually there, in order to get the
250
// old value for the result
252
NS_STATIC_CAST(HTEntry*,
253
PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP));
256
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
257
// value wasn't in the table anyway
261
PL_DHashTableRawRemove(&mHashtable, entry);
264
if (mLock) PR_Unlock(mLock);
269
// XXX This method was called _hashEnumerateCopy, but it didn't copy the element!
270
// I don't know how this was supposed to work since the elements are neither copied
272
PR_STATIC_CALLBACK(PLDHashOperator)
273
hashEnumerateShare(PLDHashTable *table, PLDHashEntryHdr *hdr,
274
PRUint32 i, void *arg)
276
nsHashtable *newHashtable = (nsHashtable *)arg;
277
HTEntry * entry = NS_STATIC_CAST(HTEntry*, hdr);
279
newHashtable->Put(entry->key, entry->value);
280
return PL_DHASH_NEXT;
283
nsHashtable * nsHashtable::Clone()
285
if (!mHashtable.ops) return nsnull;
287
PRBool threadSafe = (mLock != nsnull);
288
nsHashtable *newHashTable = new nsHashtable(mHashtable.entryCount, threadSafe);
290
PL_DHashTableEnumerate(&mHashtable, hashEnumerateShare, newHashTable);
294
void nsHashtable::Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure)
296
if (!mHashtable.ops) return;
298
PRBool wasEnumerating = mEnumerating;
299
mEnumerating = PR_TRUE;
300
_HashEnumerateArgs thunk;
301
thunk.fn = aEnumFunc;
302
thunk.arg = aClosure;
303
PL_DHashTableEnumerate(&mHashtable, hashEnumerate, &thunk);
304
mEnumerating = wasEnumerating;
307
PR_STATIC_CALLBACK(PLDHashOperator)
308
hashEnumerateRemove(PLDHashTable*, PLDHashEntryHdr* hdr, PRUint32 i, void *arg)
310
HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
311
_HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
313
return thunk->fn(entry->key, entry->value, thunk->arg)
317
return PL_DHASH_REMOVE;
320
void nsHashtable::Reset() {
324
void nsHashtable::Reset(nsHashtableEnumFunc destroyFunc, void* aClosure)
326
if (!mHashtable.ops) return;
328
_HashEnumerateArgs thunk, *thunkp;
333
thunk.fn = destroyFunc;
334
thunk.arg = aClosure;
336
PL_DHashTableEnumerate(&mHashtable, hashEnumerateRemove, thunkp);
339
// nsISerializable helpers
341
nsHashtable::nsHashtable(nsIObjectInputStream* aStream,
342
nsHashtableReadEntryFunc aReadEntryFunc,
343
nsHashtableFreeEntryFunc aFreeEntryFunc,
346
mEnumerating(PR_FALSE)
348
MOZ_COUNT_CTOR(nsHashtable);
351
nsresult rv = aStream->ReadBoolean(&threadSafe);
352
if (NS_SUCCEEDED(rv)) {
354
mLock = PR_NewLock();
356
rv = NS_ERROR_OUT_OF_MEMORY;
359
if (NS_SUCCEEDED(rv)) {
361
rv = aStream->Read32(&count);
363
if (NS_SUCCEEDED(rv)) {
365
PL_DHashTableInit(&mHashtable, &hashtableOps,
366
nsnull, sizeof(HTEntry), count);
368
mHashtable.ops = nsnull;
369
rv = NS_ERROR_OUT_OF_MEMORY;
371
for (PRUint32 i = 0; i < count; i++) {
375
rv = aReadEntryFunc(aStream, &key, &data);
376
if (NS_SUCCEEDED(rv)) {
377
if (!Put(key, data)) {
378
rv = NS_ERROR_OUT_OF_MEMORY;
379
aFreeEntryFunc(aStream, key, data);
381
// XXXbe must we clone key? can't we hand off
382
aFreeEntryFunc(aStream, key, nsnull);
395
struct WriteEntryArgs {
396
nsIObjectOutputStream* mStream;
397
nsHashtableWriteDataFunc mWriteDataFunc;
401
PR_STATIC_CALLBACK(PRBool)
402
WriteEntry(nsHashKey *aKey, void *aData, void* aClosure)
404
WriteEntryArgs* args = (WriteEntryArgs*) aClosure;
405
nsIObjectOutputStream* stream = args->mStream;
407
nsresult rv = aKey->Write(stream);
408
if (NS_SUCCEEDED(rv))
409
rv = args->mWriteDataFunc(stream, aData);
416
nsHashtable::Write(nsIObjectOutputStream* aStream,
417
nsHashtableWriteDataFunc aWriteDataFunc) const
420
return NS_ERROR_OUT_OF_MEMORY;
421
PRBool threadSafe = (mLock != nsnull);
422
nsresult rv = aStream->WriteBoolean(threadSafe);
423
if (NS_FAILED(rv)) return rv;
425
// Write the entry count first, so we know how many key/value pairs to read.
426
PRUint32 count = mHashtable.entryCount;
427
rv = aStream->Write32(count);
428
if (NS_FAILED(rv)) return rv;
430
// Write all key/value pairs in the table.
431
WriteEntryArgs args = {aStream, aWriteDataFunc};
432
NS_CONST_CAST(nsHashtable*, this)->Enumerate(WriteEntry, (void*) &args);
436
////////////////////////////////////////////////////////////////////////////////
438
nsISupportsKey::nsISupportsKey(nsIObjectInputStream* aStream, nsresult *aResult)
442
nsresult rv = aStream->ReadBoolean(&nonnull);
443
if (NS_SUCCEEDED(rv) && nonnull)
444
rv = aStream->ReadObject(PR_TRUE, &mKey);
449
nsISupportsKey::Write(nsIObjectOutputStream* aStream) const
451
PRBool nonnull = (mKey != nsnull);
452
nsresult rv = aStream->WriteBoolean(nonnull);
453
if (NS_SUCCEEDED(rv) && nonnull)
454
rv = aStream->WriteObject(mKey, PR_TRUE);
458
nsIDKey::nsIDKey(nsIObjectInputStream* aStream, nsresult *aResult)
460
*aResult = aStream->ReadID(&mID);
463
nsresult nsIDKey::Write(nsIObjectOutputStream* aStream) const
465
return aStream->WriteID(mID);
468
////////////////////////////////////////////////////////////////////////////////
471
// We need to free mStr if the object is passed with mOwnership as OWN. As the
472
// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
474
nsCStringKey::nsCStringKey(const nsCStringKey& aKey)
475
: mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
477
if (mOwnership != NEVER_OWN) {
478
PRUint32 len = mStrLen * sizeof(char);
479
char* str = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(len + sizeof(char)));
481
// Pray we don't dangle!
482
mOwnership = NEVER_OWN;
484
// Use memcpy in case there are embedded NULs.
485
memcpy(str, mStr, len);
492
mKeyType = CStringKey;
494
MOZ_COUNT_CTOR(nsCStringKey);
497
nsCStringKey::nsCStringKey(const nsAFlatCString& str)
498
: mStr(NS_CONST_CAST(char*, str.get())),
499
mStrLen(str.Length()),
500
mOwnership(OWN_CLONE)
502
NS_ASSERTION(mStr, "null string key");
504
mKeyType = CStringKey;
506
MOZ_COUNT_CTOR(nsCStringKey);
509
nsCStringKey::nsCStringKey(const nsACString& str)
510
: mStr(ToNewCString(str)),
511
mStrLen(str.Length()),
514
NS_ASSERTION(mStr, "null string key");
516
mKeyType = CStringKey;
518
MOZ_COUNT_CTOR(nsCStringKey);
521
nsCStringKey::nsCStringKey(const char* str, PRInt32 strLen, Ownership own)
522
: mStr((char*)str), mStrLen(strLen), mOwnership(own)
524
NS_ASSERTION(mStr, "null string key");
525
if (mStrLen == PRUint32(-1))
526
mStrLen = strlen(str);
528
mKeyType = CStringKey;
530
MOZ_COUNT_CTOR(nsCStringKey);
533
nsCStringKey::~nsCStringKey(void)
535
if (mOwnership == OWN)
536
nsMemory::Free(mStr);
537
MOZ_COUNT_DTOR(nsCStringKey);
541
nsCStringKey::HashCode(void) const
543
return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
547
nsCStringKey::Equals(const nsHashKey* aKey) const
549
NS_ASSERTION(aKey->GetKeyType() == CStringKey, "mismatched key types");
550
nsCStringKey* other = (nsCStringKey*)aKey;
551
NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
552
NS_ASSERTION(other->mStrLen != PRUint32(-1), "never called HashCode");
553
if (mStrLen != other->mStrLen)
555
return memcmp(mStr, other->mStr, mStrLen * sizeof(char)) == 0;
559
nsCStringKey::Clone() const
561
if (mOwnership == NEVER_OWN)
562
return new nsCStringKey(mStr, mStrLen, NEVER_OWN);
564
// Since this might hold binary data OR a string, we ensure that the
565
// clone string is zero terminated, but don't assume that the source
566
// string was so terminated.
568
PRUint32 len = mStrLen * sizeof(char);
569
char* str = (char*)nsMemory::Alloc(len + sizeof(char));
572
memcpy(str, mStr, len);
574
return new nsCStringKey(str, mStrLen, OWN);
577
nsCStringKey::nsCStringKey(nsIObjectInputStream* aStream, nsresult *aResult)
578
: mStr(nsnull), mStrLen(0), mOwnership(OWN)
581
nsresult rv = aStream->ReadCString(str);
582
mStr = ToNewCString(str);
583
if (NS_SUCCEEDED(rv))
584
mStrLen = str.Length();
586
MOZ_COUNT_CTOR(nsCStringKey);
590
nsCStringKey::Write(nsIObjectOutputStream* aStream) const
592
return aStream->WriteStringZ(mStr);
595
////////////////////////////////////////////////////////////////////////////////
598
// We need to free mStr if the object is passed with mOwnership as OWN. As the
599
// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
601
nsStringKey::nsStringKey(const nsStringKey& aKey)
602
: mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
604
if (mOwnership != NEVER_OWN) {
605
PRUint32 len = mStrLen * sizeof(PRUnichar);
606
PRUnichar* str = NS_REINTERPRET_CAST(PRUnichar*, nsMemory::Alloc(len + sizeof(PRUnichar)));
608
// Pray we don't dangle!
609
mOwnership = NEVER_OWN;
611
// Use memcpy in case there are embedded NULs.
612
memcpy(str, mStr, len);
619
mKeyType = StringKey;
621
MOZ_COUNT_CTOR(nsStringKey);
624
nsStringKey::nsStringKey(const nsAFlatString& str)
625
: mStr(NS_CONST_CAST(PRUnichar*, str.get())),
626
mStrLen(str.Length()),
627
mOwnership(OWN_CLONE)
629
NS_ASSERTION(mStr, "null string key");
631
mKeyType = StringKey;
633
MOZ_COUNT_CTOR(nsStringKey);
636
nsStringKey::nsStringKey(const nsAString& str)
637
: mStr(ToNewUnicode(str)),
638
mStrLen(str.Length()),
641
NS_ASSERTION(mStr, "null string key");
643
mKeyType = StringKey;
645
MOZ_COUNT_CTOR(nsStringKey);
648
nsStringKey::nsStringKey(const PRUnichar* str, PRInt32 strLen, Ownership own)
649
: mStr((PRUnichar*)str), mStrLen(strLen), mOwnership(own)
651
NS_ASSERTION(mStr, "null string key");
652
if (mStrLen == PRUint32(-1))
653
mStrLen = nsCRT::strlen(str);
655
mKeyType = StringKey;
657
MOZ_COUNT_CTOR(nsStringKey);
660
nsStringKey::~nsStringKey(void)
662
if (mOwnership == OWN)
663
nsMemory::Free(mStr);
664
MOZ_COUNT_DTOR(nsStringKey);
668
nsStringKey::HashCode(void) const
670
return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
674
nsStringKey::Equals(const nsHashKey* aKey) const
676
NS_ASSERTION(aKey->GetKeyType() == StringKey, "mismatched key types");
677
nsStringKey* other = (nsStringKey*)aKey;
678
NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
679
NS_ASSERTION(other->mStrLen != PRUint32(-1), "never called HashCode");
680
if (mStrLen != other->mStrLen)
682
return memcmp(mStr, other->mStr, mStrLen * sizeof(PRUnichar)) == 0;
686
nsStringKey::Clone() const
688
if (mOwnership == NEVER_OWN)
689
return new nsStringKey(mStr, mStrLen, NEVER_OWN);
691
PRUint32 len = (mStrLen+1) * sizeof(PRUnichar);
692
PRUnichar* str = (PRUnichar*)nsMemory::Alloc(len);
695
memcpy(str, mStr, len);
696
return new nsStringKey(str, mStrLen, OWN);
699
nsStringKey::nsStringKey(nsIObjectInputStream* aStream, nsresult *aResult)
700
: mStr(nsnull), mStrLen(0), mOwnership(OWN)
703
nsresult rv = aStream->ReadString(str);
704
mStr = ToNewUnicode(str);
705
if (NS_SUCCEEDED(rv))
706
mStrLen = str.Length();
708
MOZ_COUNT_CTOR(nsStringKey);
712
nsStringKey::Write(nsIObjectOutputStream* aStream) const
714
return aStream->WriteWStringZ(mStr);
717
////////////////////////////////////////////////////////////////////////////////
718
// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
721
nsObjectHashtable::nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
722
void* cloneElementClosure,
723
nsHashtableEnumFunc destroyElementFun,
724
void* destroyElementClosure,
725
PRUint32 aSize, PRBool threadSafe)
726
: nsHashtable(aSize, threadSafe),
727
mCloneElementFun(cloneElementFun),
728
mCloneElementClosure(cloneElementClosure),
729
mDestroyElementFun(destroyElementFun),
730
mDestroyElementClosure(destroyElementClosure)
734
nsObjectHashtable::~nsObjectHashtable()
740
PLDHashOperator PR_CALLBACK
741
nsObjectHashtable::CopyElement(PLDHashTable* table,
742
PLDHashEntryHdr* hdr,
743
PRUint32 i, void *arg)
745
nsObjectHashtable *newHashtable = (nsObjectHashtable *)arg;
746
HTEntry *entry = NS_STATIC_CAST(HTEntry*, hdr);
749
newHashtable->mCloneElementFun(entry->key, entry->value,
750
newHashtable->mCloneElementClosure);
751
if (newElement == nsnull)
752
return PL_DHASH_STOP;
753
newHashtable->Put(entry->key, newElement);
754
return PL_DHASH_NEXT;
758
nsObjectHashtable::Clone()
760
if (!mHashtable.ops) return nsnull;
762
PRBool threadSafe = PR_FALSE;
764
threadSafe = PR_TRUE;
765
nsObjectHashtable* newHashTable =
766
new nsObjectHashtable(mCloneElementFun, mCloneElementClosure,
767
mDestroyElementFun, mDestroyElementClosure,
768
mHashtable.entryCount, threadSafe);
770
PL_DHashTableEnumerate(&mHashtable, CopyElement, newHashTable);
775
nsObjectHashtable::Reset()
777
nsHashtable::Reset(mDestroyElementFun, mDestroyElementClosure);
781
nsObjectHashtable::RemoveAndDelete(nsHashKey *aKey)
783
void *value = Remove(aKey);
784
if (value && mDestroyElementFun)
785
return (*mDestroyElementFun)(aKey, value, mDestroyElementClosure);
789
////////////////////////////////////////////////////////////////////////////////
790
// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
793
nsSupportsHashtable::ReleaseElement(nsHashKey *aKey, void *aData, void* aClosure)
795
nsISupports* element = NS_STATIC_CAST(nsISupports*, aData);
796
NS_IF_RELEASE(element);
800
nsSupportsHashtable::~nsSupportsHashtable()
802
Enumerate(ReleaseElement, nsnull);
805
// Return true if we overwrote something
808
nsSupportsHashtable::Put(nsHashKey *aKey, nsISupports* aData, nsISupports **value)
811
void *prev = nsHashtable::Put(aKey, aData);
812
nsISupports *old = NS_REINTERPRET_CAST(nsISupports *, prev);
813
if (value) // pass own the ownership to the caller
815
else // the caller doesn't care, we do
817
return prev != nsnull;
821
nsSupportsHashtable::Get(nsHashKey *aKey)
823
void* data = nsHashtable::Get(aKey);
826
nsISupports* element = NS_REINTERPRET_CAST(nsISupports*, data);
827
NS_IF_ADDREF(element);
831
// Return true if we found something (useful for checks)
834
nsSupportsHashtable::Remove(nsHashKey *aKey, nsISupports **value)
836
void* data = nsHashtable::Remove(aKey);
837
nsISupports* element = NS_STATIC_CAST(nsISupports*, data);
838
if (value) // caller wants it
840
else // caller doesn't care, we do
841
NS_IF_RELEASE(element);
842
return data != nsnull;
845
PLDHashOperator PR_CALLBACK
846
nsSupportsHashtable::EnumerateCopy(PLDHashTable*,
847
PLDHashEntryHdr* hdr,
848
PRUint32 i, void *arg)
850
nsHashtable *newHashtable = (nsHashtable *)arg;
851
HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
853
nsISupports* element = NS_STATIC_CAST(nsISupports*, entry->value);
854
NS_IF_ADDREF(element);
855
newHashtable->Put(entry->key, entry->value);
856
return PL_DHASH_NEXT;
860
nsSupportsHashtable::Clone()
862
if (!mHashtable.ops) return nsnull;
864
PRBool threadSafe = (mLock != nsnull);
865
nsSupportsHashtable* newHashTable =
866
new nsSupportsHashtable(mHashtable.entryCount, threadSafe);
868
PL_DHashTableEnumerate(&mHashtable, EnumerateCopy, newHashTable);
873
nsSupportsHashtable::Reset()
875
Enumerate(ReleaseElement, nsnull);
876
nsHashtable::Reset();
879
////////////////////////////////////////////////////////////////////////////////