diff --git a/xpcom/build/dlldeps.cpp b/xpcom/build/dlldeps.cpp index e832d6843edd..366cbfa8ca92 100644 --- a/xpcom/build/dlldeps.cpp +++ b/xpcom/build/dlldeps.cpp @@ -84,6 +84,9 @@ #ifdef DEBUG #include "pure.h" #endif +#include "nsInterfaceHashtable.h" +#include "nsDataHashtable.h" +#include "nsHashKeys.h" #include "pldhash.h" #include "nsVariant.h" #include "nsEscape.h" @@ -138,6 +141,8 @@ void XXXNeverCalled() nsCWeakReferent(0); NS_GetWeakReference(NULL); nsCOMPtr dummyFoo(do_GetInterface(nsnull)); + nsInterfaceHashtable(); + nsDataHashtable(); NS_NewByteArrayInputStream(NULL, NULL, 0); NS_NewStorageStream(0,0, nsnull); nsString foo; diff --git a/xpcom/ds/MANIFEST b/xpcom/ds/MANIFEST index 786d4cc438a7..5e67f0f20e15 100644 --- a/xpcom/ds/MANIFEST +++ b/xpcom/ds/MANIFEST @@ -1,27 +1,37 @@ nsArray.h nsArrayEnumerator.h nsAtomService.h +nsBaseHashtable.h +nsBaseHashtableImpl.h nsCppSharedAllocator.h nsCOMArray.h nsCRT.h +nsDataHashtable.h nsDeque.h nsDoubleHashtable.h -nsHashSets.h nsCheapSets.h +nsClassHashtable.h +nsDataHashtable.h nsEnumeratorUtils.h nsFixedSizeAllocator.h +nsHashKeys.h +nsHashSets.h nsHashtable.h nsHashtableEnumerator.h nsIArena.h nsIByteBuffer.h nsIUnicharBuffer.h nsInt64.h +nsInterfaceHashtable.h +nsInterfaceHashtableImpl.h nsObserverService.h nsQuickSort.h nsStaticNameTable.h nsStatistics.h nsSupportsArray.h nsSupportsPrimitives.h +nsTHashtable.h +nsTHashtableImpl.h nsTime.h nsUnitConversion.h nsValueArray.h diff --git a/xpcom/ds/Makefile.in b/xpcom/ds/Makefile.in index 73dab9b5d34f..0d8eebc3a571 100644 --- a/xpcom/ds/Makefile.in +++ b/xpcom/ds/Makefile.in @@ -68,6 +68,7 @@ CPPSRCS = \ nsSupportsArray.cpp \ nsSupportsArrayEnumerator.cpp \ nsSupportsPrimitives.cpp \ + nsTHashtable.cpp \ nsUnicharBuffer.cpp \ nsVariant.cpp \ nsVoidArray.cpp \ @@ -81,20 +82,27 @@ CPPSRCS = \ EXPORTS = \ nsAtomService.h \ + nsBaseHashtable.h \ + nsBaseHashtableImpl.h \ nsCheapSets.h \ + nsClassHashtable.h \ nsCppSharedAllocator.h \ nsCRT.h \ + nsDataHashtable.h \ nsDeque.h \ nsDoubleHashtable.h \ nsEnumeratorUtils.h \ nsFixedSizeAllocator.h \ nsHashSets.h \ + nsHashKeys.h \ nsHashtable.h \ nsHashtableEnumerator.h \ nsIArena.h \ nsIByteBuffer.h \ nsIUnicharBuffer.h \ nsInt64.h \ + nsInterfaceHashtable.h \ + nsInterfaceHashtableImpl.h \ nsObserverService.h \ nsQuickSort.h \ nsRecyclingAllocator.h \ @@ -102,6 +110,8 @@ EXPORTS = \ nsStaticAtom.h \ nsSupportsArray.h \ nsSupportsPrimitives.h \ + nsTHashtable.h \ + nsTHashtableImpl.h \ nsTime.h \ nsUnitConversion.h \ nsVariant.h \ diff --git a/xpcom/ds/nsBaseHashtable.h b/xpcom/ds/nsBaseHashtable.h new file mode 100644 index 000000000000..d7172f2e71db --- /dev/null +++ b/xpcom/ds/nsBaseHashtable.h @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsBaseHashtable_h__ +#define nsBaseHashtable_h__ + +#include "nsTHashtable.h" +#include NEW_H +typedef struct PRRWLock PRRWLock; + +template +class nsBaseHashtable; // forward declaration + +/** + * the private nsTHashtable::EntryType class used by nsBaseHashtable + * @see nsTHashtable for the specification of this class + * @see nsBaseHashtable for template parameters + */ +template +class nsBaseHashtableET : public KeyClass +{ +public: + DataType mData; + friend class nsTHashtable< nsBaseHashtableET >; + +private: + typedef typename KeyClass::KeyType KeyType; + typedef typename KeyClass::KeyTypePointer KeyTypePointer; + + nsBaseHashtableET(KeyTypePointer aKey); + nsBaseHashtableET(const nsBaseHashtableET& toCopy); + ~nsBaseHashtableET(); +}; + +/** + * templated hashtable for simple data types + * This class manages simple data types that do not need construction or + * destruction. Thread-safety is optional, via a flag in Init() + * + * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h + * for a complete specification. + * @param DataType the datatype stored in the hashtable, + * for example, PRUint32 or nsCOMPtr. If UserDataType is not the same, + * DataType must implicitly cast to UserDataType + * @param UserDataType the user sees, for example PRUint32 or nsISupports* + */ +template +class nsBaseHashtable : + protected nsTHashtable< nsBaseHashtableET > +{ +public: + typedef typename KeyClass::KeyType KeyType; + typedef nsBaseHashtableET EntryType; + + /** + * The constructor does not initialize, you must call Init() after + * construction. + */ + nsBaseHashtable(); + + /** + * destructor finalizes and deallocates hashtable + */ + ~nsBaseHashtable(); + + /** + * Initialize the object. + * @param initSize the initial number of buckets in the hashtable, + default 16 + * @param threadSafe whether to provide read/write + * locking on all class methods + * @return PR_TRUE if the object was initialized properly. + */ + PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE, + PRBool threadSafe = PR_FALSE); + + /** + * retrieve the value for a key. + * @param aKey the key to retreive + * @param pData data associated with this key will be placed at this + * pointer. If you only need to check if the key exists, pData + * may be null. + * @return PR_TRUE if the key exists. If key does not exist, pData is not + * modified. + */ + PRBool Get(KeyType aKey, UserDataType* pData) const; + + /** + * put a new value for the associated key + * @param aKey the key to put + * @param aData the new data + * @return always PR_TRUE, unless memory allocation failed + */ + PRBool Put(KeyType aKey, UserDataType aData); + + /** + * remove the data for the associated key + * @param aKey the key to remove from the hashtable + */ + void Remove(KeyType aKey); + + /** + * function type provided by the application for enumeration. + * currently, only "read" enumeration is supported. If you need to change + * or remove entries during enumeration, it might could be arranged. + * @param aKey the key being enumerated + * @param aData data being enumerated + * @parm userArg passed unchanged from Enumerate + * @return either + * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or + * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink + */ + typedef PLDHashOperator + (*PR_CALLBACK EnumReadFunction)(KeyType aKey, + DataType aData, + void* userArg); + + /** + * enumerate entries in the hashtable, without allowing changes + * this function read-locks the hashtable, so other threads may read keys + * at the same time in multi-thread environments. + * @param enumFunc enumeration callback + * @param userArg passed unchanged to the EnumReadFunction + */ + void EnumerateRead(EnumReadFunction enumFunc, void* userArg) const; + + /** + * reset the hashtable, removing all entries + */ + void Clear(); + +protected: + PRRWLock* mLock; + + /** + * used internally during EnumerateRead. Allocated on the stack. + * @param func the enumerator passed to EnumerateRead + * @param userArg the userArg passed to EnumerateRead + */ + struct s_EnumReadArgs + { + EnumReadFunction func; + void* userArg; + }; + + static PLDHashOperator s_EnumReadStub(PLDHashTable *table, + PLDHashEntryHdr *hdr, + PRUint32 number, + void *arg); +}; + +#ifndef HAVE_CPP_EXTERN_INSTANTIATION + #include "nsBaseHashtableImpl.h" +#endif + +#endif // nsBaseHashtable_h__ diff --git a/xpcom/ds/nsBaseHashtableImpl.h b/xpcom/ds/nsBaseHashtableImpl.h new file mode 100644 index 000000000000..c4df9e39ffdd --- /dev/null +++ b/xpcom/ds/nsBaseHashtableImpl.h @@ -0,0 +1,224 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsBaseHashtableImpl_h__ +#define nsBaseHashtableImpl_h__ + +#ifndef nsBaseHashtable_h__ +#include "nsBaseHashtable.h" +#endif + +#ifndef nsTHashtableImpl_h__ +#include "nsTHashtableImpl.h" +#endif + +#include "prrwlock.h" +#include "nsDebug.h" + +/* nsBaseHashtableET definitions */ + +template +nsBaseHashtableET::nsBaseHashtableET(KeyTypePointer aKey) : + KeyClass(aKey) +{ } + +template +nsBaseHashtableET::nsBaseHashtableET + (const nsBaseHashtableET& toCopy) : + KeyClass(toCopy), + mData(toCopy.mData) +{ } + +template +nsBaseHashtableET::~nsBaseHashtableET() +{ } + +/* nsBaseHashtable definitions */ + +template +nsBaseHashtable::nsBaseHashtable() +{ } + +template +nsBaseHashtable::~nsBaseHashtable() +{ + if (mLock) + PR_DestroyRWLock(mLock); +} + +template +PRBool +nsBaseHashtable::Init(PRUint32 initSize, + PRBool threadSafe) +{ + if (!nsTHashtable::Init(initSize)) + return PR_FALSE; + + if (!threadSafe) + { + mLock = nsnull; + return PR_TRUE; + } + + mLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "nsBaseHashtable"); + + NS_WARN_IF_FALSE(mLock, "Error creating lock during nsBaseHashtable::Init()"); + + if (!mLock) + return PR_FALSE; + + return PR_TRUE; +} + +template +PRBool +nsBaseHashtable::Get(KeyType aKey, + UserDataType* pData) const +{ + if (mLock) + PR_RWLock_Rlock(mLock); + + EntryType* ent = GetEntry(KeyClass::KeyToPointer(aKey)); + + if (ent) + { + if (pData) + *pData = ent->mData; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; + } + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; +} + +template +PRBool +nsBaseHashtable::Put(KeyType aKey, + UserDataType aData) +{ + if (mLock) + PR_RWLock_Wlock(mLock); + + EntryType* ent = PutEntry(KeyClass::KeyToPointer(aKey)); + + if (!ent) + { + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; + } + + ent->mData = aData; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; +} + +template +void +nsBaseHashtable::Remove(KeyType aKey) +{ + if (mLock) + PR_RWLock_Wlock(mLock); + + RemoveEntry(KeyClass::KeyToPointer(aKey)); + + if (mLock) + PR_RWLock_Unlock(mLock); +} + +template +void +nsBaseHashtable::EnumerateRead + (EnumReadFunction fEnumCall, void* userArg) const +{ + NS_ASSERTION(mTable.entrySize, + "nsBaseHashtable was not initialized properly."); + + if (mLock) + PR_RWLock_Rlock(mLock); + + s_EnumReadArgs enumData = { fEnumCall, userArg }; + PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*,&mTable), + s_EnumStub, + &enumData); + + if (mLock) + PR_RWLock_Unlock(mLock); +} + +template +void nsBaseHashtable::Clear() +{ + if (mLock) + PR_RWLock_Wlock(mLock); + + nsTHashtable::Clear(); + + if (mLock) + PR_RWLock_Unlock(mLock); +} + +template +PLDHashOperator +nsBaseHashtable::s_EnumReadStub + (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg) +{ + EntryType* ent = (EntryType*) hdr; + s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg; + + PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg); + + NS_ASSERTION( !(res & PL_DHASH_REMOVE ), + "PL_DHASH_REMOVE return during const enumeration; ignoring."); + + if (res & PL_DHASH_STOP) + return PL_DHASH_STOP; + + return PL_DHASH_NEXT; +} + +#endif // nsBaseHashtableImpl_h__ diff --git a/xpcom/ds/nsClassHashtable.h b/xpcom/ds/nsClassHashtable.h new file mode 100644 index 000000000000..9a0eab2442e8 --- /dev/null +++ b/xpcom/ds/nsClassHashtable.h @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsClassHashtable_h__ +#define nsClassHashtable_h__ + +#include "nsBaseHashtable.h" +#include "nsHashKeys.h" + +/** + * templated hashtable class maps keys to C++ object pointers. + * See nsBaseHashtable for complete declaration. + * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h + * for a complete specification. + * @param Class the class-type being wrapped + * @see nsInterfaceHashtable, nsClassHashtable + */ +template +class nsClassHashtable : + public nsBaseHashtable,T*> +{ +public: + typedef typename KeyClass::KeyType KeyType; + typedef typename T* UserDataType; + + /** + * @copydoc nsBaseHashtable::nsBaseHashtable + */ + nsClassHashtable() { } + + /** + * destructor, cleans up properly + */ + ~nsClassHashtable() { } + + /** + * @copydoc nsBaseHashtable::Get + * @param pData if the key doesn't exist, pData will be set to nsnull. + */ + PRBool Get(KeyType aKey, UserDataType* pData) const; +}; + +/* + * this class doesn't have any predefined instances; implementations are + * included here + */ + +#ifndef nsTHashtableImpl_h__ +#include "nsTHashtableImpl.h" +#endif + +template +PRBool +nsClassHashtable::Get(KeyType aKey, T** retVal) const +{ + if (mLock) + PR_RWLock_Rlock(mLock); + + typename nsBaseHashtable,T*>::EntryType* ent = + GetEntry(KeyClass::KeyToPointer(aKey)); + + if (ent) + { + if (retVal) + *retVal = ent->mData; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; + } + + *retVal = nsnull; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; +}; + +#endif // nsClassHashtable_h__ diff --git a/xpcom/ds/nsDataHashtable.h b/xpcom/ds/nsDataHashtable.h new file mode 100644 index 000000000000..7da278d7e267 --- /dev/null +++ b/xpcom/ds/nsDataHashtable.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsDataHashtable_h__ +#define nsDataHashtable_h__ + +#include "nsHashKeys.h" +#include "nsBaseHashtable.h" + +/** + * templated hashtable class maps keys to simple datatypes. + * See nsBaseHashtable for complete declaration + * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h + * for a complete specification. + * @param DataType the simple datatype being wrapped + * @see nsInterfaceHashtable, nsClassHashtable + */ +template +class nsDataHashtable : + public nsBaseHashtable +{ }; + +/** + * declare shared-linkage for common usages of nsDataHashtable. + * + * To avoid including this code in multiple translation units, common usages + * are predeclared with external linkage. To add to this list, include the + * declarations here, definitions in nsTHashtable.cpp and dlldeps.cpp . This + * only works if the configure-test HAVE_CPP_EXTERN_INSTANTIATION succeeds. + */ +#ifndef HAVE_CPP_EXTERN_INSTANTIATION + #include "nsBaseHashtableImpl.h" +#else + #ifndef NO_THASHTABLE_EXTERN_DECL + extern template class NS_COM nsBaseHashtableET; + extern template class NS_COM nsTHashtable< nsBaseHashtableET >; + extern template class NS_COM nsBaseHashtable; + extern template class NS_COM nsDataHashtable; + #else + #include "nsBaseHashtableImpl.h" + #endif +#endif + +#endif // nsDataHashtable_h__ diff --git a/xpcom/ds/nsDoubleHashtable.h b/xpcom/ds/nsDoubleHashtable.h index b29409f1ceb0..08d64ef84921 100644 --- a/xpcom/ds/nsDoubleHashtable.h +++ b/xpcom/ds/nsDoubleHashtable.h @@ -36,6 +36,10 @@ * * ***** END LICENSE BLOCK ***** */ +/** + * nsDoubleHashtable.h is OBSOLETE. Use nsTHashtable or a derivative instead. + */ + #ifndef __nsDoubleHashtable_h__ #define __nsDoubleHashtable_h__ diff --git a/xpcom/ds/nsHashKeys.h b/xpcom/ds/nsHashKeys.h new file mode 100644 index 000000000000..a079dbbfc489 --- /dev/null +++ b/xpcom/ds/nsHashKeys.h @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsTHashKeys_h__ +#define nsTHashKeys_h__ + +#include "nsAString.h" +#include "nsString.h" +#include "nsID.h" +#include "nsCRT.h" +#include "nsReadableUtils.h" +#include "nsISupports.h" +#include "nsCOMPtr.h" +#include "pldhash.h" +#include NEW_H + +/** @file nsHashKeys.h + * standard HashKey classes for nsDataHashtable and relatives. Each of these + * classes follows the nsTHashtable::EntryType specification + * + * Lightweight keytypes are provided here: + * nsStringHashKey + * nsCStringHashKey + * nsUint32HashKey + * nsISupportsHashKey + * nsIDHashKey + * + * Use these keytypes if possible; the templates are already instantiated + * for them, and they can be dynamically linked and therefore reduce code + * size! + */ + +/** + * hashkey wrapper using nsAString KeyType + * + * @see nsTHashtable::EntryType for specification + */ +class NS_COM nsStringHashKey : protected PLDHashEntryHdr +{ +public: + typedef const nsAString& KeyType; + typedef const nsAString* KeyTypePointer; + + nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) { } + nsStringHashKey(const nsStringHashKey& toCopy) : mStr(toCopy.mStr) { } + ~nsStringHashKey() { } + + KeyType GetKey() const { return mStr; } + KeyTypePointer GetKeyPointer() const { return &mStr; } + PRBool KeyEquals(const KeyTypePointer aKey) const + { + return mStr.Equals(*aKey); + } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } + static PLDHashNumber HashKey(const KeyTypePointer aKey) + { + return HashString(*aKey); + } + static PRBool AllowMemMove() { return PR_TRUE; } + +private: + const nsString mStr; +}; + +/** + * hashkey wrapper using nsACString KeyType + * + * @see nsTHashtable::EntryType for specification + */ +class NS_COM nsCStringHashKey : protected PLDHashEntryHdr +{ +public: + typedef const nsACString& KeyType; + typedef const nsACString* KeyTypePointer; + + nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) { } + nsCStringHashKey(const nsCStringHashKey& toCopy) : mStr(toCopy.mStr) { } + ~nsCStringHashKey() { } + + KeyType GetKey() const { return mStr; } + KeyTypePointer GetKeyPointer() const { return &mStr; } + + PRBool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } + static PLDHashNumber HashKey(KeyTypePointer aKey) + { + return HashString(*aKey); + } + static PRBool AllowMemMove() { return PR_TRUE; } + +private: + const nsCString mStr; +}; + +/** + * hashkey wrapper using PRUint32 KeyType + * + * @see nsTHashtable::EntryType for specification + */ +class NS_COM nsUint32HashKey : protected PLDHashEntryHdr +{ +public: + typedef PRUint32 KeyType; + typedef const PRUint32* KeyTypePointer; + + nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) { } + nsUint32HashKey(const nsUint32HashKey& toCopy) : mValue(toCopy.mValue) { } + ~nsUint32HashKey() { } + + KeyType GetKey() const { return mValue; } + KeyTypePointer GetKeyPointer() const { return &mValue; } + PRBool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } + static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; } + static PRBool AllowMemMove() { return PR_TRUE; } + +private: + const PRUint32 mValue; +}; + +/** + * hashkey wrapper using nsISupports* KeyType + * + * @see nsTHashtable::EntryType for specification + */ +class NS_COM nsISupportsHashKey : protected PLDHashEntryHdr +{ +public: + typedef nsISupports* KeyType; + typedef const nsISupports* KeyTypePointer; + + nsISupportsHashKey(nsISupports* key) : mSupports(key) { } + nsISupportsHashKey(const nsISupportsHashKey& toCopy) : + mSupports(toCopy.mSupports) { } + ~nsISupportsHashKey() { } + + KeyType GetKey() const { return mSupports; } + KeyTypePointer GetKeyPointer() const { return mSupports; } + + PRBool KeyEquals(KeyTypePointer aKey) const { return aKey == mSupports; } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; } + static PLDHashNumber HashKey(KeyTypePointer aKey) + { + return NS_PTR_TO_INT32(aKey) >>2; + } + static PRBool AllowMemMove() { return PR_TRUE; } + +private: + const nsCOMPtr mSupports; +}; + +/** + * hashkey wrapper using nsID KeyType + * + * @see nsTHashtable::EntryType for specification + */ +class NS_COM nsIDHashKey : protected PLDHashEntryHdr +{ +public: + typedef const nsID& KeyType; + typedef const nsID* KeyTypePointer; + + nsIDHashKey(const nsID* id) : mID(*id) { } + nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { } + ~nsIDHashKey() { } + + KeyType GetKey() const { return mID; } + KeyTypePointer GetKeyPointer() const { return &mID; } + PRBool operator==(KeyTypePointer aKey) const { return aKey->Equals(mID); } + + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } + static PLDHashNumber HashKey(KeyTypePointer aKey); + static PRBool AllowMemMove() { return PR_TRUE; } + +private: + const nsID mID; +}; + +#endif // nsTHashKeys_h__ diff --git a/xpcom/ds/nsHashtable.h b/xpcom/ds/nsHashtable.h index be0062722d2f..27353be386d6 100644 --- a/xpcom/ds/nsHashtable.h +++ b/xpcom/ds/nsHashtable.h @@ -30,6 +30,10 @@ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2 */ +/** + * nsHashtable is OBSOLETE. Use nsTHashtable or a derivative instead. + */ + #ifndef nsHashtable_h__ #define nsHashtable_h__ diff --git a/xpcom/ds/nsInterfaceHashtable.h b/xpcom/ds/nsInterfaceHashtable.h new file mode 100644 index 000000000000..8a5fe61b1c4b --- /dev/null +++ b/xpcom/ds/nsInterfaceHashtable.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsInterfaceHashtable_h__ +#define nsInterfaceHashtable_h__ + +#include "nsBaseHashtable.h" +#include "nsHashKeys.h" +#include "nsCOMPtr.h" + +/** + * templated hashtable class maps keys to interface pointers. + * See nsBaseHashtable for complete declaration. + * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h + * for a complete specification. + * @param Interface the interface-type being wrapped + * @see nsDataHashtable, nsClassHashtable + */ +template +class nsInterfaceHashtable : + public nsBaseHashtable< KeyClass, nsCOMPtr , Interface* > +{ +public: + typedef typename KeyClass::KeyType KeyType; + typedef Interface* UserDataType; + /** + * @copydoc nsBaseHashtable::nsBaseHashtable + */ + nsInterfaceHashtable() { } + + /** + * destructor, cleans up properly + */ + ~nsInterfaceHashtable() { } + + /** + * @copydoc nsBaseHashtable::Get + * @param pData This is an XPCOM getter, so pData is already_addrefed. + * If the key doesn't exist, pData will be set to nsnull. + */ + PRBool Get(KeyType aKey, UserDataType* pData) const; +}; + +/** + * declare shared-linkage for common usages of nsDataHashtable. + * + * To avoid including this code in multiple translation units, common usages + * are predeclared with external linkage. To add to this list, include the + * declarations here, definitions in nsTHashtable.cpp and dlldeps.cpp . This + * only works if the configure-test HAVE_CPP_EXTERN_INSTANTIATION succeeds. + */ +#ifndef HAVE_CPP_EXTERN_INSTANTIATION + #include "nsInterfaceHashtableImpl.h" +#else + #ifndef NO_THASHTABLE_EXTERN_DECL + extern template class NS_COM nsBaseHashtableET >; + extern template class NS_COM nsTHashtable< nsBaseHashtableET > >; + extern template class NS_COM nsBaseHashtable, nsISupports*>; + extern template class NS_COM nsInterfaceHashtable; + #else + #include "nsInterfaceHashtableImpl.h" + #endif +#endif + +#endif // nsInterfaceHashtable_h__ diff --git a/xpcom/ds/nsInterfaceHashtableImpl.h b/xpcom/ds/nsInterfaceHashtableImpl.h new file mode 100644 index 000000000000..c075b08c2434 --- /dev/null +++ b/xpcom/ds/nsInterfaceHashtableImpl.h @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsInterfaceHashtableImpl_h__ +#define nsInterfaceHashtableImpl_h__ + +#ifndef nsInterfaceHashtable_h__ +#include "nsInterfaceHashtable.h" +#endif + +#ifndef nsBaseHashtableImpl_h__ +#include "nsBaseHashtableImpl.h" +#endif + +/* nsInterfaceHashtable definitions */ + +template +PRBool +nsInterfaceHashtable::Get + (KeyType aKey, UserDataType* pInterface) const +{ + if (mLock) + PR_RWLock_Rlock(mLock); + + typename nsBaseHashtable, Interface*>::EntryType* ent = + GetEntry(KeyClass::KeyToPointer(aKey)); + + if (ent) + { + if (pInterface) + { + *pInterface = ent->mData; + + NS_IF_ADDREF(*pInterface); + } + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_TRUE; + } + + // if the key doesn't exist, set *pInterface to null + // so that it is a valid XPCOM getter + if (pInterface) + *pInterface = nsnull; + + if (mLock) + PR_RWLock_Unlock(mLock); + + return PR_FALSE; +} + +#endif // nsInterfaceHashtableImpl_h__ diff --git a/xpcom/ds/nsTHashtable.cpp b/xpcom/ds/nsTHashtable.cpp new file mode 100644 index 000000000000..b0460f8cb243 --- /dev/null +++ b/xpcom/ds/nsTHashtable.cpp @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#define NO_THASHTABLE_EXTERN_DECL + +#include "nsTHashtable.h" +#include "nsTHashtableImpl.h" +#include "nsInterfaceHashtable.h" +#include "nsInterfaceHashtableImpl.h" +#include "nsDataHashtable.h" +#include "nsHashKeys.h" + +PLDHashOperator PL_DHashStubEnumRemove(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 ordinal, + void *userarg) +{ + return PL_DHASH_REMOVE; +} + +PRUint32 nsIDHashKey::HashKey(const nsID* id) +{ + PRUint32 h = id->m0; + PRUint32 i; + + h = (h>>28) ^ (h<<4) ^ id->m1; + h = (h>>28) ^ (h<<4) ^ id->m2; + + for (i = 0; i < 8; i++) + h = (h>>28) ^ (h<<4) ^ id->m3[i]; + + return h; +} + +// explicit instantiation of templates +#ifdef HAVE_CPP_EXTERN_INSTANTIATION + /* instantiate common nsInterfaceHashtable uses */ + template class NS_EXPORT nsBaseHashtableET >; + template class NS_EXPORT nsTHashtable< nsBaseHashtableET > >; + template class NS_EXPORT nsBaseHashtable,nsISupports*>; + template class NS_EXPORT nsInterfaceHashtable; + + /* instantiate common nsDataHashtable uses */ + template class NS_EXPORT nsBaseHashtableET; + template class NS_EXPORT nsTHashtable< nsBaseHashtableET >; + template class NS_EXPORT nsBaseHashtable; + template class NS_EXPORT nsDataHashtable; +#endif // HAVE_CPP_EXTERN_INSTANTIATION diff --git a/xpcom/ds/nsTHashtable.h b/xpcom/ds/nsTHashtable.h new file mode 100644 index 000000000000..a747c09f58d1 --- /dev/null +++ b/xpcom/ds/nsTHashtable.h @@ -0,0 +1,241 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsTHashtable_h__ +#define nsTHashtable_h__ + +#include "nscore.h" +#include "pldhash.h" + +#ifdef _MSC_VER +#pragma warning( disable: 4231 ) // 'extern template' nonstandard C++ extension +#endif + +/** + * a base class for templated hashtables. + * + * Clients will rarely need to use this class directly. Check the derived + * classes first, to see if they will meet your needs. + * + * @param EntryType the templated entry-type class that is managed by the + * hashtable. EntryType must extend the following declaration, + * and must not declare any virtual functions or derive from classes + * with virtual functions. Any vtable pointer would break the + * PLDHashTable code. + *
   class EntryType : PLDHashEntryHdr
+ *   {
+ *   public: or friend nsTHashtable;
+ *     // KeyType is what we use when Get()ing or Put()ing this entry
+ *     // this should either be a simple datatype (PRUint32, nsISupports*) or
+ *     // a const reference (const nsAString&)
+ *     typedef something KeyType;
+ *     // KeyTypePointer is the pointer-version of KeyType, because pldhash.h
+ *     // requires keys to cast to const void*
+ *     typedef const something* KeyTypePointer;
+ *
+ *     EntryType(KeyTypePointer aKey);
+ *
+ *     // the copy constructor must be defined, even if AllowMemMove() == true
+ *     // or you will cause link errors!
+ *     EntryType(const EntryType& aEnt);
+ *
+ *     // the destructor must be defined... or you will cause link errors!
+ *     ~EntryType();
+ *
+ *     // return the key of this entry
+ *     const KeyTypePointer GetKeyPointer() const;
+ *
+ *     // KeyEquals(): does this entry match this key?
+ *     PRBool KeyEquals(KeyTypePointer aKey) const;
+ *
+ *     // KeyToPointer(): Convert KeyType to KeyTypePointer
+ *     static KeyTypePointer KeyToPointer(KeyType aKey);
+ *
+ *     // HashKey(): calculate the hash number
+ *     static PLDHashNumber HashKey(KeyTypePointer aKey);
+ *
+ *     // AllowMemMove(): can we move this class with memmove(), or do we have
+ *     // to use the copy constructor?
+ *     static PRBool AllowMemMove();
+ *   }
+ * + * @see nsInterfaceHashtable + * @see nsDataHashtable + * @see nsClassHashtable + * @author "Benjamin Smedberg " + */ + +template +class nsTHashtable +{ +public: + /** + * A dummy constructor; you must call Init() before using this class. + */ + nsTHashtable(); + + /** + * destructor, cleans up and deallocates + */ + ~nsTHashtable(); + + /** + * Initialize the class. This function must be called before any other + * class operations. This can fail due to OOM conditions. + * @param initSize the initial number of buckets in the hashtable, default 16 + * @return PR_TRUE if the class was initialized properly. + */ + PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE); + + /** + * KeyType is typedef'ed for ease of use. + */ + typedef typename EntryType::KeyType KeyType; + + /** + * KeyTypePointer is typedef'ed for ease of use. + */ + typedef typename EntryType::KeyTypePointer KeyTypePointer; + + /** + * Get the entry associated with a key. + * @param aKey the key to retrieve + * @return pointer to the entry class, if the key exists; nsnull if the + * key doesn't exist + */ + EntryType* GetEntry(KeyTypePointer aKey) const; + + /** + * Get the entry associated with a key, or create a new entry, + * @param aKey the key to retrieve + * @return pointer to the entry class retreived; nsnull only if memory + can't be allocated + */ + EntryType* PutEntry(KeyTypePointer aKey); + + /** + * Remove the entry associated with a key. + * @param aKey of the entry to remove + */ + void RemoveEntry(KeyTypePointer aKey); + + /** + * client must provide an Enumerator function for + * EnumerateEntries + * @param aEntry the entry being enumerated + * @param userArg passed unchanged from EnumerateEntries + * @return combination of flags + * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink , + * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink , + * @link PLDHashOperator::PL_DHASH_REMOVE PL_DHASH_REMOVE @endlink + */ + typedef PLDHashOperator (*Enumerator)(EntryType* aEntry, void* userArg); + + /** + * Enumerate all the entries of the function. + * @param enumFunc the Enumerator function to call + * @param userArg a pointer to pass to the + * Enumerator function + * @return the number of entries actually enumerated + */ + PRUint32 EnumerateEntries(Enumerator enumFunc, void* userArg); + + /** + * remove all entries, return hashtable to "pristine" state ;) + */ + void Clear(); + +protected: + PLDHashTable mTable; + + static PLDHashTableOps sOps; + + static const void* s_GetKey(PLDHashTable *table, + PLDHashEntryHdr *entry); + + static PLDHashNumber s_HashKey(PLDHashTable *table, + const void *key); + + static PRBool s_MatchEntry(PLDHashTable *table, + const PLDHashEntryHdr *entry, + const void *key); + + static void s_CopyEntry(PLDHashTable *table, + const PLDHashEntryHdr *from, + PLDHashEntryHdr *to); + + static void s_ClearEntry(PLDHashTable *table, + PLDHashEntryHdr *entry); + + static void s_InitEntry(PLDHashTable *table, + PLDHashEntryHdr *entry, + const void *key); + + /** + * passed internally during enumeration. Allocated on the stack. + * + * @param userFunc the Enumerator function passed to + * EnumerateEntries by the client + * @param userArg the userArg passed unaltered + */ + struct s_EnumArgs + { + Enumerator userFunc; + void* userArg; + }; + + static PLDHashOperator s_EnumStub(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 number, + void *arg); +}; + +// helper function for Reset() +PLDHashOperator PL_DHashStubEnumRemove(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 ordinal, + void *userArg); + +/** + * if we can't declare external linkage for templates, we need to include the + * implementation header. + */ +#ifndef HAVE_CPP_EXTERN_INSTANTIATION +#include "nsTHashtableImpl.h" +#endif + +#endif // nsTHashtable_h__ diff --git a/xpcom/ds/nsTHashtableImpl.h b/xpcom/ds/nsTHashtableImpl.h new file mode 100644 index 000000000000..92a546071464 --- /dev/null +++ b/xpcom/ds/nsTHashtableImpl.h @@ -0,0 +1,218 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is C++ hashtable templates. + * + * The Initial Developer of the Original Code is + * Benjamin Smedberg. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsTHashtableImpl_h__ +#define nsTHashtableImpl_h__ + +#ifndef nsTHashtable_h__ +#include "nsTHashtable.h" +#endif + +#include "nsDebug.h" + +template +nsTHashtable::nsTHashtable() +{ + // entrySize is our "I'm initialized" indicator + mTable.entrySize = 0; +} + +template +nsTHashtable::~nsTHashtable() +{ + if (mTable.entrySize) + PL_DHashTableFinish(&mTable); +} + +template +PRBool +nsTHashtable::Init(PRUint32 initSize) +{ + if (mTable.entrySize) + { + NS_ERROR("nsTHashtable::Init() should not be called twice."); + return PR_FALSE; + } + + if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize)) + { + // if failed, reset "flag" + mTable.entrySize = 0; + return PR_FALSE; + } + + return PR_TRUE; +} + +template +EntryType* +nsTHashtable::GetEntry(KeyTypePointer aKey) const +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + return NS_REINTERPRET_CAST(EntryType*, + PL_DHashTableOperate( + NS_CONST_CAST(PLDHashTable*,&mTable), + aKey, + PL_DHASH_LOOKUP)); +} + +template +EntryType* +nsTHashtable::PutEntry(KeyTypePointer aKey) +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + return (EntryType*) PL_DHashTableOperate(&mTable, aKey, PL_DHASH_ADD); +} + +template +void +nsTHashtable::RemoveEntry(KeyTypePointer aKey) +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + PL_DHashTableOperate(&mTable, aKey, PL_DHASH_REMOVE); + + return; +} + +template +PRUint32 +nsTHashtable::EnumerateEntries(Enumerator enumFunc, void* userArg) +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + s_EnumArgs args = { enumFunc, userArg }; + + return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args); +} + +template +void +nsTHashtable::Clear() +{ + NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly."); + + PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull); +} + +// static definitions + +template +PLDHashTableOps +nsTHashtable::sOps = +{ + ::PL_DHashAllocTable, + ::PL_DHashFreeTable, + s_GetKey, + s_HashKey, + s_MatchEntry, + EntryType::AllowMemMove() ? ::PL_DHashMoveEntryStub : s_CopyEntry, + s_ClearEntry, + ::PL_DHashFinalizeStub, + s_InitEntry +}; + +template +const void* +nsTHashtable::s_GetKey(PLDHashTable *table, + PLDHashEntryHdr *entry) +{ + return ((EntryType*) entry)->GetKeyPointer(); +} + +template +PLDHashNumber +nsTHashtable::s_HashKey(PLDHashTable *table, + const void *key) +{ + return EntryType::HashKey(NS_REINTERPRET_CAST(const KeyTypePointer, key)); +} + +template +PRBool +nsTHashtable::s_MatchEntry(PLDHashTable *table, + const PLDHashEntryHdr *entry, + const void *key) +{ + return ((const EntryType*) entry)->KeyEquals( + NS_REINTERPRET_CAST(const KeyTypePointer, key)); +} + +template +void +nsTHashtable::s_CopyEntry(PLDHashTable *table, + const PLDHashEntryHdr *from, + PLDHashEntryHdr *to) +{ + new(to) EntryType(* NS_REINTERPRET_CAST(const EntryType*,from)); + + NS_CONST_CAST(EntryType*,NS_REINTERPRET_CAST(const EntryType*,from))->~EntryType(); +} + +template +void +nsTHashtable::s_ClearEntry(PLDHashTable *table, + PLDHashEntryHdr *entry) +{ + NS_REINTERPRET_CAST(EntryType*,entry)->~EntryType(); +} + +template +void +nsTHashtable::s_InitEntry(PLDHashTable *table, + PLDHashEntryHdr *entry, + const void *key) +{ + new(entry) EntryType(NS_REINTERPRET_CAST(KeyTypePointer,key)); +} + +template +PLDHashOperator +nsTHashtable::s_EnumStub(PLDHashTable *table, + PLDHashEntryHdr *entry, + PRUint32 number, + void *arg) +{ + // dereferences the function-pointer to the user's enumeration function + return (* NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userFunc)( + NS_REINTERPRET_CAST(EntryType*,entry), + NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userArg); +} + +#endif // nsTHashtableImpl_h__ diff --git a/xpcom/macbuild/xpcomPPC.xml b/xpcom/macbuild/xpcomPPC.xml index 473488e10b05..3a329ffcb362 100644 --- a/xpcom/macbuild/xpcomPPC.xml +++ b/xpcom/macbuild/xpcomPPC.xml @@ -1044,6 +1044,13 @@ Text Debug + + Name + nsTHashtable.cpp + MacOS + Text + Debug + Name nsDebug.cpp @@ -1941,6 +1948,11 @@ nsHashtable.cpp MacOS + + Name + nsTHashtable.cpp + MacOS + Name nsDebug.cpp @@ -3549,6 +3561,13 @@ Text Debug + + Name + nsTHashtable.cpp + MacOS + Text + Debug + Name nsDebug.cpp @@ -4458,6 +4477,11 @@ nsHashtable.cpp MacOS + + Name + nsTHashtable.cpp + MacOS + Name nsDebug.cpp @@ -5320,6 +5344,12 @@ nsHashtable.cpp MacOS + + xpcom.shlb + Name + nsTHashtable.cpp + MacOS + xpcom.shlb Name