Back to index

lightning-sunbird  0.9+nobinonly
nsHashtable.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK *****
00037  * This Original Code has been modified by IBM Corporation.
00038  * Modifications made by IBM described herein are
00039  * Copyright (c) International Business Machines
00040  * Corporation, 2000
00041  *
00042  * Modifications to Mozilla code or documentation
00043  * identified per MPL Section 3.3
00044  *
00045  * Date         Modified by     Description of modification
00046  * 04/20/2000   IBM Corp.       Added PR_CALLBACK for Optlink use in OS2
00047  */
00048 
00053 #ifndef nsHashtable_h__
00054 #define nsHashtable_h__
00055 
00056 #include "pldhash.h"
00057 #include "prlock.h"
00058 #include "nscore.h"
00059 #include "nsString.h"
00060 #include "nsISupportsBase.h"
00061 #include "nsTraceRefcnt.h"
00062 
00063 class nsIObjectInputStream;
00064 class nsIObjectOutputStream;
00065 
00066 class nsHashtable;
00067 class nsStringKey;
00068 
00069 class NS_COM nsHashKey {
00070   protected:
00071     nsHashKey(void) {
00072 #ifdef DEBUG
00073         mKeyType = UnknownKey;
00074 #endif
00075         MOZ_COUNT_CTOR(nsHashKey);
00076     }
00077 
00078 
00079   public:
00080     // Virtual destructor because all hash keys are |delete|d via a
00081     // nsHashKey pointer.
00082 
00083     virtual ~nsHashKey(void);
00084     virtual PRUint32 HashCode(void) const = 0;
00085     virtual PRBool Equals(const nsHashKey *aKey) const = 0;
00086     virtual nsHashKey *Clone() const = 0;
00087     virtual nsresult Write(nsIObjectOutputStream* aStream) const;
00088 
00089 #ifdef DEBUG
00090   public:
00091     // used for verification that we're casting to the correct key type
00092     enum nsHashKeyType {
00093         UnknownKey,
00094         SupportsKey,
00095         PRUint32Key,
00096         VoidKey,
00097         IDKey,
00098         CStringKey,
00099         StringKey
00100     };
00101     nsHashKeyType GetKeyType() const { return mKeyType; }
00102   protected:
00103     nsHashKeyType mKeyType;
00104 #endif
00105 };
00106 
00107 // Enumerator and Read/Write callback functions.
00108 
00109 // Return values for nsHashtableEnumFunc
00110 enum {
00111     kHashEnumerateStop      = PR_FALSE,
00112     kHashEnumerateNext      = PR_TRUE,
00113     kHashEnumerateRemove    = 2
00114 };
00115 
00116 typedef PRIntn
00117 (*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
00118 
00119 typedef nsresult
00120 (*PR_CALLBACK nsHashtableReadEntryFunc)(nsIObjectInputStream *aStream,
00121                                         nsHashKey **aKey,
00122                                         void **aData);
00123 
00124 // NB: may be called with null aKey or aData, to free just one of the two.
00125 typedef void
00126 (*PR_CALLBACK nsHashtableFreeEntryFunc)(nsIObjectInputStream *aStream,
00127                                         nsHashKey *aKey,
00128                                         void *aData);
00129 
00130 typedef nsresult
00131 (*PR_CALLBACK nsHashtableWriteDataFunc)(nsIObjectOutputStream *aStream,
00132                                         void *aData);
00133 
00134 class NS_COM nsHashtable {
00135   protected:
00136     // members  
00137     PRLock*         mLock;
00138     PLDHashTable    mHashtable;
00139     PRBool          mEnumerating;
00140 
00141   public:
00142     nsHashtable(PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE);
00143     virtual ~nsHashtable();
00144 
00145     PRInt32 Count(void) { return mHashtable.entryCount; }
00146     PRBool Exists(nsHashKey *aKey);
00147     void *Put(nsHashKey *aKey, void *aData);
00148     void *Get(nsHashKey *aKey);
00149     void *Remove(nsHashKey *aKey);
00150     nsHashtable *Clone();
00151     void Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure = NULL);
00152     void Reset();
00153     void Reset(nsHashtableEnumFunc destroyFunc, void* aClosure = NULL);
00154 
00155     nsHashtable(nsIObjectInputStream* aStream,
00156                 nsHashtableReadEntryFunc aReadEntryFunc,
00157                 nsHashtableFreeEntryFunc aFreeEntryFunc,
00158                 nsresult *aRetVal);
00159     nsresult Write(nsIObjectOutputStream* aStream,
00160                    nsHashtableWriteDataFunc aWriteDataFunc) const;
00161 };
00162 
00164 // nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
00165 // deleted
00166 
00167 typedef void* (*PR_CALLBACK nsHashtableCloneElementFunc)(nsHashKey *aKey, void *aData, void* aClosure);
00168 
00169 class NS_COM nsObjectHashtable : public nsHashtable {
00170   public:
00171     nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
00172                       void* cloneElementClosure,
00173                       nsHashtableEnumFunc destroyElementFun,
00174                       void* destroyElementClosure,
00175                       PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE);
00176     ~nsObjectHashtable();
00177 
00178     nsHashtable *Clone();
00179     void Reset();
00180     PRBool RemoveAndDelete(nsHashKey *aKey);
00181 
00182   protected:
00183     static PLDHashOperator PR_CALLBACK CopyElement(PLDHashTable* table,
00184                                                    PLDHashEntryHdr* hdr,
00185                                                    PRUint32 i, void *arg);
00186     
00187     nsHashtableCloneElementFunc mCloneElementFun;
00188     void*                       mCloneElementClosure;
00189     nsHashtableEnumFunc         mDestroyElementFun;
00190     void*                       mDestroyElementClosure;
00191 };
00192 
00194 // nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
00195 
00196 class nsISupports;
00197 
00198 class NS_COM nsSupportsHashtable
00199   : private nsHashtable
00200 {
00201   public:
00202     typedef PRBool (* PR_CALLBACK EnumFunc) (nsHashKey *aKey, void *aData, void* aClosure);
00203 
00204     nsSupportsHashtable(PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE)
00205       : nsHashtable(aSize, threadSafe) {}
00206     ~nsSupportsHashtable();
00207 
00208     PRInt32 Count(void) {
00209         return nsHashtable::Count();
00210     }
00211     PRBool Exists(nsHashKey *aKey) {
00212         return nsHashtable::Exists (aKey);
00213     }
00214     PRBool Put(nsHashKey *aKey,
00215                nsISupports *aData,
00216                nsISupports **value = nsnull);
00217     nsISupports* Get(nsHashKey *aKey);
00218     PRBool Remove(nsHashKey *aKey, nsISupports **value = nsnull);
00219     nsHashtable *Clone();
00220     void Enumerate(EnumFunc aEnumFunc, void* aClosure = NULL) {
00221         nsHashtable::Enumerate(aEnumFunc, aClosure);
00222     }
00223     void Reset();
00224 
00225   private:
00226     static PRBool PR_CALLBACK ReleaseElement(nsHashKey *, void *, void *);
00227     static PLDHashOperator PR_CALLBACK EnumerateCopy(PLDHashTable*,
00228                                                      PLDHashEntryHdr* hdr,
00229                                                      PRUint32 i, void *arg);
00230 };
00231 
00233 // nsISupportsKey: Where keys are nsISupports objects that get refcounted.
00234 
00235 #include "nsISupports.h"
00236 
00237 class NS_COM nsISupportsKey : public nsHashKey {
00238   protected:
00239     nsISupports* mKey;
00240     
00241   public:
00242     nsISupportsKey(const nsISupportsKey& aKey) : mKey(aKey.mKey) {
00243 #ifdef DEBUG
00244         mKeyType = SupportsKey;
00245 #endif
00246         NS_IF_ADDREF(mKey);
00247     }
00248 
00249     nsISupportsKey(nsISupports* key) {
00250 #ifdef DEBUG
00251         mKeyType = SupportsKey;
00252 #endif
00253         mKey = key;
00254         NS_IF_ADDREF(mKey);
00255     }
00256     
00257     ~nsISupportsKey(void) {
00258         NS_IF_RELEASE(mKey);
00259     }
00260     
00261     PRUint32 HashCode(void) const {
00262         return NS_PTR_TO_INT32(mKey);
00263     }
00264 
00265     PRBool Equals(const nsHashKey *aKey) const {
00266         NS_ASSERTION(aKey->GetKeyType() == SupportsKey, "mismatched key types");
00267         return (mKey == ((nsISupportsKey *) aKey)->mKey);
00268     }
00269 
00270     nsHashKey *Clone() const {
00271         return new nsISupportsKey(mKey);
00272     }
00273 
00274     nsISupportsKey(nsIObjectInputStream* aStream, nsresult *aResult);
00275     nsresult Write(nsIObjectOutputStream* aStream) const;
00276 };
00277 
00278 
00279 class nsPRUint32Key : public nsHashKey {
00280 protected:
00281     PRUint32 mKey;
00282 public:
00283     nsPRUint32Key(PRUint32 key) {
00284 #ifdef DEBUG
00285         mKeyType = PRUint32Key;
00286 #endif
00287         mKey = key;
00288     }
00289 
00290     PRUint32 HashCode(void) const {
00291         return mKey;
00292     }
00293 
00294     PRBool Equals(const nsHashKey *aKey) const {
00295         return mKey == ((const nsPRUint32Key *) aKey)->mKey;
00296     }
00297     nsHashKey *Clone() const {
00298         return new nsPRUint32Key(mKey);
00299     }
00300     PRUint32 GetValue() { return mKey; }
00301 };
00302 
00304 // nsVoidKey: Where keys are void* objects that don't get refcounted.
00305 
00306 class nsVoidKey : public nsHashKey {
00307   protected:
00308     void* mKey;
00309     
00310   public:
00311     nsVoidKey(const nsVoidKey& aKey) : mKey(aKey.mKey) {
00312 #ifdef DEBUG
00313         mKeyType = aKey.mKeyType;
00314 #endif
00315     }
00316 
00317     nsVoidKey(void* key) {
00318 #ifdef DEBUG
00319         mKeyType = VoidKey;
00320 #endif
00321         mKey = key;
00322     }
00323     
00324     PRUint32 HashCode(void) const {
00325         return NS_PTR_TO_INT32(mKey);
00326     }
00327 
00328     PRBool Equals(const nsHashKey *aKey) const {
00329         NS_ASSERTION(aKey->GetKeyType() == VoidKey, "mismatched key types");
00330         return (mKey == ((const nsVoidKey *) aKey)->mKey);
00331     }
00332 
00333     nsHashKey *Clone() const {
00334         return new nsVoidKey(mKey);
00335     }
00336 
00337     void* GetValue() { return mKey; }
00338 };
00339 
00341 // nsIDKey: Where keys are nsIDs (e.g. nsIID, nsCID).
00342 
00343 #include "nsID.h"
00344 
00345 class NS_COM nsIDKey : public nsHashKey {
00346   protected:
00347     nsID mID;
00348     
00349   public:
00350     nsIDKey(const nsIDKey& aKey) : mID(aKey.mID) {
00351 #ifdef DEBUG
00352           mKeyType = IDKey;
00353 #endif
00354     }
00355 
00356     nsIDKey(const nsID &aID) {
00357 #ifdef DEBUG
00358         mKeyType = IDKey;
00359 #endif
00360         mID = aID;
00361     }
00362     
00363     PRUint32 HashCode(void) const {
00364         return mID.m0;
00365     }
00366 
00367     PRBool Equals(const nsHashKey *aKey) const {
00368         NS_ASSERTION(aKey->GetKeyType() == IDKey, "mismatched key types");
00369         return (mID.Equals(((const nsIDKey *) aKey)->mID));
00370     }
00371 
00372     nsHashKey *Clone() const {
00373         return new nsIDKey(mID);
00374     }
00375 
00376     nsIDKey(nsIObjectInputStream* aStream, nsresult *aResult);
00377     nsresult Write(nsIObjectOutputStream* aStream) const;
00378 };
00379 
00381 
00382 #include "nsString.h"
00383 
00384 // for null-terminated c-strings
00385 class NS_COM nsCStringKey : public nsHashKey {
00386   public:
00387 
00388     // NB: when serializing, NEVER_OWN keys are deserialized as OWN.
00389     enum Ownership {
00390         NEVER_OWN,  // very long lived, even clones don't need to copy it.
00391         OWN_CLONE,  // as long lived as this key. But clones make a copy.
00392         OWN         // to be free'd in key dtor. Clones make their own copy.
00393     };
00394 
00395     nsCStringKey(const nsCStringKey& aStrKey);
00396     nsCStringKey(const char* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
00397     nsCStringKey(const nsAFlatCString& str);
00398     nsCStringKey(const nsACString& str);
00399     ~nsCStringKey(void);
00400 
00401     PRUint32 HashCode(void) const;
00402     PRBool Equals(const nsHashKey* aKey) const;
00403     nsHashKey* Clone() const;
00404     nsCStringKey(nsIObjectInputStream* aStream, nsresult *aResult);
00405     nsresult Write(nsIObjectOutputStream* aStream) const;
00406 
00407     // For when the owner of the hashtable wants to peek at the actual
00408     // string in the key. No copy is made, so be careful.
00409     const char* GetString() const { return mStr; }
00410     PRUint32 GetStringLength() const { return mStrLen; }
00411 
00412   protected:
00413     char*       mStr;
00414     PRUint32    mStrLen;
00415     Ownership   mOwnership;
00416 };
00417 
00418 // for null-terminated unicode strings
00419 class NS_COM nsStringKey : public nsHashKey {
00420   public:
00421 
00422     // NB: when serializing, NEVER_OWN keys are deserialized as OWN.
00423     enum Ownership {
00424         NEVER_OWN,  // very long lived, even clones don't need to copy it.
00425         OWN_CLONE,  // as long lived as this key. But clones make a copy.
00426         OWN         // to be free'd in key dtor. Clones make their own copy.
00427     };
00428 
00429     nsStringKey(const nsStringKey& aKey);
00430     nsStringKey(const PRUnichar* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
00431     nsStringKey(const nsAFlatString& str);
00432     nsStringKey(const nsAString& str);
00433     ~nsStringKey(void);
00434 
00435     PRUint32 HashCode(void) const;
00436     PRBool Equals(const nsHashKey* aKey) const;
00437     nsHashKey* Clone() const;
00438     nsStringKey(nsIObjectInputStream* aStream, nsresult *aResult);
00439     nsresult Write(nsIObjectOutputStream* aStream) const;
00440 
00441     // For when the owner of the hashtable wants to peek at the actual
00442     // string in the key. No copy is made, so be careful.
00443     const PRUnichar* GetString() const { return mStr; }
00444     PRUint32 GetStringLength() const { return mStrLen; }
00445 
00446   protected:
00447     PRUnichar*  mStr;
00448     PRUint32    mStrLen;
00449     Ownership   mOwnership;
00450 };
00451 
00453 
00454 #endif // nsHashtable_h__