/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Netscape 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/NPL/ * * 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 mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * This Original Code has been modified by IBM Corporation. * Modifications made by IBM described herein are * Copyright (c) International Business Machines * Corporation, 2000 * * Modifications to Mozilla code or documentation * identified per MPL Section 3.3 * * Date Modified by Description of modification * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2 */ #ifndef nsHashtable_h__ #define nsHashtable_h__ #include "plhash.h" #include "prlock.h" #include "nsCom.h" #include "nscore.h" #include "nsString.h" class nsHashtable; class nsStringKey; class NS_COM nsHashKey { protected: nsHashKey(void); public: virtual ~nsHashKey(void); virtual PRUint32 HashCode(void) const = 0; virtual PRBool Equals(const nsHashKey *aKey) const = 0; virtual nsHashKey *Clone() const = 0; #ifdef DEBUG public: // used for verification that we're casting to the correct key type enum nsHashKeyType { UnknownKey, SupportsKey, VoidKey, IDKey, CStringKey, StringKey, OpaqueKey }; nsHashKeyType GetKeyType() const { return mKeyType; } protected: nsHashKeyType mKeyType; #endif }; // Enumerator callback function. Use typedef PRBool (*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* closure); class NS_COM nsHashtable { protected: // members PRLock* mLock; PLHashTable mHashtable; PRBool mEnumerating; public: nsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE); virtual ~nsHashtable(); PRInt32 Count(void) { return mHashtable.nentries; } PRBool Exists(nsHashKey *aKey); void *Put(nsHashKey *aKey, void *aData); void *Get(nsHashKey *aKey); void *Remove(nsHashKey *aKey); nsHashtable *Clone(); void Enumerate(nsHashtableEnumFunc aEnumFunc, void* closure = NULL); void Reset(); void Reset(nsHashtableEnumFunc destroyFunc, void* closure = NULL); }; //////////////////////////////////////////////////////////////////////////////// // nsObjectHashtable: an nsHashtable where the elements are C++ objects to be // deleted typedef void* (*PR_CALLBACK nsHashtableCloneElementFunc)(nsHashKey *aKey, void *aData, void* closure); class NS_COM nsObjectHashtable : public nsHashtable { public: nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun, void* cloneElementClosure, nsHashtableEnumFunc destroyElementFun, void* destroyElementClosure, PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE); ~nsObjectHashtable(); nsHashtable *Clone(); void Reset(); PRBool RemoveAndDelete(nsHashKey *aKey); protected: static PRIntn PR_CALLBACK CopyElement(PLHashEntry *he, PRIntn i, void *arg); nsHashtableCloneElementFunc mCloneElementFun; void* mCloneElementClosure; nsHashtableEnumFunc mDestroyElementFun; void* mDestroyElementClosure; }; //////////////////////////////////////////////////////////////////////////////// // nsSupportsHashtable: an nsHashtable where the elements are nsISupports* class nsISupports; class NS_COM nsSupportsHashtable : private nsHashtable { public: typedef PRBool (* PR_CALLBACK EnumFunc) (nsHashKey *aKey, void *aData, void* closure); nsSupportsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE) : nsHashtable(aSize, threadSafe) {} ~nsSupportsHashtable(); PRInt32 Count (void) { return nsHashtable::Count(); } PRBool Exists (nsHashKey *aKey) { return nsHashtable::Exists (aKey); } PRBool Put (nsHashKey *aKey, nsISupports *aData, nsISupports **value = nsnull); nsISupports* Get (nsHashKey *aKey); PRBool Remove (nsHashKey *aKey, nsISupports **value = nsnull); nsHashtable *Clone(); void Enumerate (EnumFunc aEnumFunc, void* closure = NULL) { nsHashtable::Enumerate (aEnumFunc, closure); } void Reset(); private: static PRBool PR_CALLBACK ReleaseElement (nsHashKey *, void *, void *); static PRIntn PR_CALLBACK EnumerateCopy (PLHashEntry *, PRIntn, void *); }; //////////////////////////////////////////////////////////////////////////////// // nsISupportsKey: Where keys are nsISupports objects that get refcounted. #include "nsISupports.h" class nsISupportsKey : public nsHashKey { protected: nsISupports* mKey; public: nsISupportsKey(nsISupports* key) { #ifdef DEBUG mKeyType = SupportsKey; #endif mKey = key; NS_IF_ADDREF(mKey); } ~nsISupportsKey(void) { NS_IF_RELEASE(mKey); } PRUint32 HashCode(void) const { return (PRUint32)mKey; } PRBool Equals(const nsHashKey *aKey) const { NS_ASSERTION(aKey->GetKeyType() == SupportsKey, "mismatched key types"); return (mKey == ((nsISupportsKey *) aKey)->mKey); } nsHashKey *Clone() const { return new nsISupportsKey(mKey); } }; //////////////////////////////////////////////////////////////////////////////// // nsVoidKey: Where keys are void* objects that don't get refcounted. class nsVoidKey : public nsHashKey { protected: void* mKey; public: nsVoidKey(void* key) { #ifdef DEBUG mKeyType = VoidKey; #endif mKey = key; } PRUint32 HashCode(void) const { return (PRUint32)mKey; } PRBool Equals(const nsHashKey *aKey) const { NS_ASSERTION(aKey->GetKeyType() == VoidKey, "mismatched key types"); return (mKey == ((const nsVoidKey *) aKey)->mKey); } nsHashKey *Clone() const { return new nsVoidKey(mKey); } void* GetValue() { return mKey; } }; //////////////////////////////////////////////////////////////////////////////// // nsIDKey: Where keys are nsIDs (e.g. nsIID, nsCID). #include "nsID.h" class nsIDKey : public nsHashKey { protected: nsID mID; public: nsIDKey(const nsID &aID) { #ifdef DEBUG mKeyType = IDKey; #endif mID = aID; } PRUint32 HashCode(void) const { return mID.m0; } PRBool Equals(const nsHashKey *aKey) const { NS_ASSERTION(aKey->GetKeyType() == IDKey, "mismatched key types"); return (mID.Equals(((const nsIDKey *) aKey)->mID)); } nsHashKey *Clone() const { return new nsIDKey(mID); } }; //////////////////////////////////////////////////////////////////////////////// #include "nsString.h" // for null-terminated c-strings class NS_COM nsCStringKey : public nsHashKey { public: enum Ownership { NEVER_OWN, // 'str' is very long lived, even clones don't need to copy it. OWN_CLONE, // 'str' is as long lived as this key. But clones make a copy. OWN // 'str' to be free'd in key dtor. Clones make their own copy. }; nsCStringKey(const char* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE); nsCStringKey(const nsCString& str); ~nsCStringKey(void); PRUint32 HashCode(void) const; PRBool Equals(const nsHashKey* aKey) const; nsHashKey* Clone() const; // For when the owner of the hashtable wants to peek at the actual // string in the key. No copy is made, so be careful. const char* GetString() const { return mStr; } PRUint32 GetStringLength() const { return mStrLen; } protected: char* mStr; PRUint32 mStrLen; Ownership mOwnership; }; // for null-terminated unicode strings class NS_COM nsStringKey : public nsHashKey { public: enum Ownership { NEVER_OWN, // 'str' is very long lived, even clones don't need to copy it. OWN_CLONE, // 'str' is as long lived as this key. But clones make a copy. OWN // 'str' to be free'd in key dtor. Clones make their own copy. }; nsStringKey(const PRUnichar* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE); nsStringKey(const nsAReadableString& str); ~nsStringKey(void); PRUint32 HashCode(void) const; PRBool Equals(const nsHashKey* aKey) const; nsHashKey* Clone() const; // For when the owner of the hashtable wants to peek at the actual // string in the key. No copy is made, so be careful. const PRUnichar* GetString() const { return mStr; } PRUint32 GetStringLength() const { return mStrLen; } protected: PRUnichar* mStr; PRUint32 mStrLen; Ownership mOwnership; }; // for opaque buffers of data which may contain nulls class NS_COM nsOpaqueKey : public nsHashKey { public: enum Ownership { NEVER_OWN, // 'buf' is very long lived, even clones don't need to copy it. OWN_CLONE, // 'buf' is as long lived as this key. But clones make a copy. OWN // 'buf' to be free'd in key dtor. Clones make their own copy. }; nsOpaqueKey(const char* buf, PRUint32 bufLen, Ownership own = OWN_CLONE); ~nsOpaqueKey(void); PRUint32 HashCode(void) const; PRBool Equals(const nsHashKey* aKey) const; nsHashKey* Clone() const; // For when the owner of the hashtable wants to peek at the actual // string in the key. No copy is made, so be careful. const char* GetBuffer() const { return mBuf; } PRUint32 GetBufferLength() const { return mBufLen; } protected: char* mBuf; PRUint32 mBufLen; Ownership mOwnership; }; //////////////////////////////////////////////////////////////////////////////// #endif