Back to index

lightning-sunbird  0.9+nobinonly
nsTHashtable.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 C++ hashtable templates.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Benjamin Smedberg.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
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 the GNU General Public License Version 2 or later (the "GPL"), or
00026  * 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 
00038 #ifndef nsTHashtable_h__
00039 #define nsTHashtable_h__
00040 
00041 #include "nscore.h"
00042 #include "pldhash.h"
00043 #include "nsDebug.h"
00044 #include NEW_H
00045 
00046 // helper function for nsTHashtable::Clear()
00047 PR_EXTERN(PLDHashOperator) PR_CALLBACK
00048 PL_DHashStubEnumRemove(PLDHashTable    *table,
00049                        PLDHashEntryHdr *entry,
00050                        PRUint32         ordinal,
00051                        void            *userArg);
00052 
00053 
00108 template<class EntryType>
00109 class nsTHashtable
00110 {
00111 public:
00115   nsTHashtable();
00116 
00120   ~nsTHashtable();
00121 
00128   PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
00129 
00134   PRBool IsInitialized() const { return mTable.entrySize; }
00135 
00139   typedef typename EntryType::KeyType KeyType;
00140 
00144   typedef typename EntryType::KeyTypePointer KeyTypePointer;
00145 
00150   PRUint32 Count() const { return mTable.entryCount; }
00151 
00158   EntryType* GetEntry(KeyType aKey) const
00159   {
00160     NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
00161   
00162     EntryType* entry =
00163       NS_REINTERPRET_CAST(EntryType*,
00164                           PL_DHashTableOperate(
00165                             NS_CONST_CAST(PLDHashTable*,&mTable),
00166                             EntryType::KeyToPointer(aKey),
00167                             PL_DHASH_LOOKUP));
00168     return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nsnull;
00169   }
00170 
00177   EntryType* PutEntry(KeyType aKey)
00178   {
00179     NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
00180     
00181     return NS_STATIC_CAST(EntryType*,
00182                           PL_DHashTableOperate(
00183                             &mTable,
00184                             EntryType::KeyToPointer(aKey),
00185                             PL_DHASH_ADD));
00186   }
00187 
00192   void RemoveEntry(KeyType aKey)
00193   {
00194     NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
00195 
00196     PL_DHashTableOperate(&mTable,
00197                          EntryType::KeyToPointer(aKey),
00198                          PL_DHASH_REMOVE);
00199   }
00200 
00209   void RawRemoveEntry(EntryType* aEntry)
00210   {
00211     PL_DHashTableRawRemove(&mTable, aEntry);
00212   }
00213 
00224   typedef PLDHashOperator (*PR_CALLBACK Enumerator)(EntryType* aEntry, void* userArg);
00225 
00233   PRUint32 EnumerateEntries(Enumerator enumFunc, void* userArg)
00234   {
00235     NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
00236     
00237     s_EnumArgs args = { enumFunc, userArg };
00238     return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args);
00239   }
00240 
00244   void Clear()
00245   {
00246     NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
00247 
00248     PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
00249   }
00250 
00251 protected:
00252   PLDHashTable mTable;
00253 
00254   static const void* PR_CALLBACK s_GetKey(PLDHashTable    *table,
00255                                           PLDHashEntryHdr *entry);
00256 
00257   static PLDHashNumber PR_CALLBACK s_HashKey(PLDHashTable *table,
00258                                              const void   *key);
00259 
00260   static PRBool PR_CALLBACK s_MatchEntry(PLDHashTable           *table,
00261                                          const PLDHashEntryHdr  *entry,
00262                                          const void             *key);
00263   
00264   static void PR_CALLBACK s_CopyEntry(PLDHashTable          *table,
00265                                       const PLDHashEntryHdr *from,
00266                                       PLDHashEntryHdr       *to);
00267   
00268   static void PR_CALLBACK s_ClearEntry(PLDHashTable *table,
00269                                        PLDHashEntryHdr *entry);
00270 
00271   static PRBool PR_CALLBACK s_InitEntry(PLDHashTable     *table,
00272                                         PLDHashEntryHdr  *entry,
00273                                         const void       *key);
00274 
00282   struct s_EnumArgs
00283   {
00284     Enumerator userFunc;
00285     void* userArg;
00286   };
00287   
00288   static PLDHashOperator PR_CALLBACK s_EnumStub(PLDHashTable    *table,
00289                                                 PLDHashEntryHdr *entry,
00290                                                 PRUint32         number,
00291                                                 void            *arg);
00292 private:
00293   // copy constructor, not implemented
00294   nsTHashtable(nsTHashtable<EntryType>& toCopy);
00295 
00296   // assignment operator, not implemented
00297   nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
00298 };
00299 
00300 //
00301 // template definitions
00302 //
00303 
00304 template<class EntryType>
00305 nsTHashtable<EntryType>::nsTHashtable()
00306 {
00307   // entrySize is our "I'm initialized" indicator
00308   mTable.entrySize = 0;
00309 }
00310 
00311 template<class EntryType>
00312 nsTHashtable<EntryType>::~nsTHashtable()
00313 {
00314   if (mTable.entrySize)
00315     PL_DHashTableFinish(&mTable);
00316 }
00317 
00318 template<class EntryType>
00319 PRBool
00320 nsTHashtable<EntryType>::Init(PRUint32 initSize)
00321 {
00322   if (mTable.entrySize)
00323   {
00324     NS_ERROR("nsTHashtable::Init() should not be called twice.");
00325     return PR_TRUE;
00326   }
00327 
00328   static PLDHashTableOps sOps = 
00329   {
00330     ::PL_DHashAllocTable,
00331     ::PL_DHashFreeTable,
00332     s_GetKey,
00333     s_HashKey,
00334     s_MatchEntry,
00335     ::PL_DHashMoveEntryStub,
00336     s_ClearEntry,
00337     ::PL_DHashFinalizeStub,
00338     s_InitEntry
00339   };
00340 
00341   if (!EntryType::ALLOW_MEMMOVE)
00342   {
00343     sOps.moveEntry = s_CopyEntry;
00344   }
00345   
00346   if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
00347   {
00348     // if failed, reset "flag"
00349     mTable.entrySize = 0;
00350     return PR_FALSE;
00351   }
00352 
00353   return PR_TRUE;
00354 }
00355 
00356 // static definitions
00357 
00358 template<class EntryType>
00359 const void*
00360 nsTHashtable<EntryType>::s_GetKey(PLDHashTable    *table,
00361                                   PLDHashEntryHdr *entry)
00362 {
00363   return ((EntryType*) entry)->GetKeyPointer();
00364 }
00365 
00366 template<class EntryType>
00367 PLDHashNumber
00368 nsTHashtable<EntryType>::s_HashKey(PLDHashTable  *table,
00369                                    const void    *key)
00370 {
00371   return EntryType::HashKey(NS_REINTERPRET_CAST(const KeyTypePointer, key));
00372 }
00373 
00374 template<class EntryType>
00375 PRBool
00376 nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable          *table,
00377                                       const PLDHashEntryHdr *entry,
00378                                       const void            *key)
00379 {
00380   return ((const EntryType*) entry)->KeyEquals(
00381     NS_REINTERPRET_CAST(const KeyTypePointer, key));
00382 }
00383 
00384 template<class EntryType>
00385 void
00386 nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable          *table,
00387                                      const PLDHashEntryHdr *from,
00388                                      PLDHashEntryHdr       *to)
00389 {
00390   EntryType* fromEntry =
00391     NS_CONST_CAST(EntryType*, NS_REINTERPRET_CAST(const EntryType*, from));
00392 
00393   new(to) EntryType(*fromEntry);
00394 
00395   fromEntry->~EntryType();
00396 }
00397 
00398 template<class EntryType>
00399 void
00400 nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable    *table,
00401                                       PLDHashEntryHdr *entry)
00402 {
00403   NS_REINTERPRET_CAST(EntryType*,entry)->~EntryType();
00404 }
00405 
00406 template<class EntryType>
00407 PRBool
00408 nsTHashtable<EntryType>::s_InitEntry(PLDHashTable    *table,
00409                                      PLDHashEntryHdr *entry,
00410                                      const void      *key)
00411 {
00412   new(entry) EntryType(NS_REINTERPRET_CAST(KeyTypePointer,key));
00413   return PR_TRUE;
00414 }
00415 
00416 template<class EntryType>
00417 PLDHashOperator
00418 nsTHashtable<EntryType>::s_EnumStub(PLDHashTable    *table,
00419                                     PLDHashEntryHdr *entry,
00420                                     PRUint32         number,
00421                                     void            *arg)
00422 {
00423   // dereferences the function-pointer to the user's enumeration function
00424   return (* NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userFunc)(
00425     NS_REINTERPRET_CAST(EntryType*,entry),
00426     NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userArg);
00427 }
00428 
00429 #endif // nsTHashtable_h__