/gecko_api/include/nsTHashtable.h
C Header | 417 lines | 192 code | 52 blank | 173 comment | 4 complexity | 8cf9eb6444acbf86a49634a425936bd9 MD5 | raw file
- /* -*- 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"
- #include "nsDebug.h"
- #include NEW_H
- // helper function for nsTHashtable::Clear()
- NS_COM_GLUE PLDHashOperator
- PL_DHashStubEnumRemove(PLDHashTable *table,
- PLDHashEntryHdr *entry,
- PRUint32 ordinal,
- void *userArg);
- /**
- * 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. <code>EntryType</code> must extend the following declaration,
- * and <strong>must not declare any virtual functions or derive from classes
- * with virtual functions.</strong> Any vtable pointer would break the
- * PLDHashTable code.
- *<pre> class EntryType : public PLDHashEntryHdr
- * {
- * public: or friend nsTHashtable<EntryType>;
- * // 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 <code>const void*</code>
- * 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();
- *
- * // 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);
- *
- * // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
- * // to use the copy constructor?
- * enum { ALLOW_MEMMOVE = PR_(TRUE or FALSE) };
- * }</pre>
- *
- * @see nsInterfaceHashtable
- * @see nsDataHashtable
- * @see nsClassHashtable
- * @author "Benjamin Smedberg <bsmedberg@covad.net>"
- */
- template<class EntryType>
- class nsTHashtable
- {
- public:
- /**
- * A dummy constructor; you must call Init() before using this class.
- */
- nsTHashtable();
- /**
- * destructor, cleans up and deallocates
- */
- ~nsTHashtable();
- /**
- * Initialize the table. 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);
- /**
- * Check whether the table has been initialized. This can be useful for static hashtables.
- * @return the initialization state of the class.
- */
- PRBool IsInitialized() const { return !!mTable.entrySize; }
- /**
- * 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;
- /**
- * Return the number of entries in the table.
- * @return number of entries
- */
- PRUint32 Count() const { return mTable.entryCount; }
- /**
- * 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(KeyType aKey) const
- {
- NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
-
- EntryType* entry =
- reinterpret_cast<EntryType*>
- (PL_DHashTableOperate(
- const_cast<PLDHashTable*>(&mTable),
- EntryType::KeyToPointer(aKey),
- PL_DHASH_LOOKUP));
- return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nsnull;
- }
- /**
- * 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(KeyType aKey)
- {
- NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
-
- return static_cast<EntryType*>
- (PL_DHashTableOperate(
- &mTable,
- EntryType::KeyToPointer(aKey),
- PL_DHASH_ADD));
- }
- /**
- * Remove the entry associated with a key.
- * @param aKey of the entry to remove
- */
- void RemoveEntry(KeyType aKey)
- {
- NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
- PL_DHashTableOperate(&mTable,
- EntryType::KeyToPointer(aKey),
- PL_DHASH_REMOVE);
- }
- /**
- * Remove the entry associated with a key, but don't resize the hashtable.
- * This is a low-level method, and is not recommended unless you know what
- * you're doing and you need the extra performance. This method can be used
- * during enumeration, while RemoveEntry() cannot.
- * @param aEntry the entry-pointer to remove (obtained from GetEntry or
- * the enumerator
- */
- void RawRemoveEntry(EntryType* aEntry)
- {
- PL_DHashTableRawRemove(&mTable, aEntry);
- }
- /**
- * client must provide an <code>Enumerator</code> function for
- * EnumerateEntries
- * @param aEntry the entry being enumerated
- * @param userArg passed unchanged from <code>EnumerateEntries</code>
- * @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 (*PR_CALLBACK Enumerator)(EntryType* aEntry, void* userArg);
- /**
- * Enumerate all the entries of the function.
- * @param enumFunc the <code>Enumerator</code> function to call
- * @param userArg a pointer to pass to the
- * <code>Enumerator</code> function
- * @return the number of entries actually enumerated
- */
- PRUint32 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);
- }
- /**
- * remove all entries, return hashtable to "pristine" state ;)
- */
- void Clear()
- {
- NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
- PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
- }
- protected:
- PLDHashTable mTable;
- static const void* PR_CALLBACK s_GetKey(PLDHashTable *table,
- PLDHashEntryHdr *entry);
- static PLDHashNumber PR_CALLBACK s_HashKey(PLDHashTable *table,
- const void *key);
- static PRBool PR_CALLBACK s_MatchEntry(PLDHashTable *table,
- const PLDHashEntryHdr *entry,
- const void *key);
-
- static void PR_CALLBACK s_CopyEntry(PLDHashTable *table,
- const PLDHashEntryHdr *from,
- PLDHashEntryHdr *to);
-
- static void PR_CALLBACK s_ClearEntry(PLDHashTable *table,
- PLDHashEntryHdr *entry);
- static PRBool PR_CALLBACK 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 PR_CALLBACK s_EnumStub(PLDHashTable *table,
- PLDHashEntryHdr *entry,
- PRUint32 number,
- void *arg);
- private:
- // copy constructor, not implemented
- nsTHashtable(nsTHashtable<EntryType>& toCopy);
- // assignment operator, not implemented
- nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
- };
- //
- // template definitions
- //
- template<class EntryType>
- nsTHashtable<EntryType>::nsTHashtable()
- {
- // entrySize is our "I'm initialized" indicator
- mTable.entrySize = 0;
- }
- template<class EntryType>
- nsTHashtable<EntryType>::~nsTHashtable()
- {
- if (mTable.entrySize)
- PL_DHashTableFinish(&mTable);
- }
- template<class EntryType>
- PRBool
- nsTHashtable<EntryType>::Init(PRUint32 initSize)
- {
- if (mTable.entrySize)
- {
- NS_ERROR("nsTHashtable::Init() should not be called twice.");
- return PR_TRUE;
- }
- static PLDHashTableOps sOps =
- {
- ::PL_DHashAllocTable,
- ::PL_DHashFreeTable,
- s_HashKey,
- s_MatchEntry,
- ::PL_DHashMoveEntryStub,
- s_ClearEntry,
- ::PL_DHashFinalizeStub,
- s_InitEntry
- };
- if (!EntryType::ALLOW_MEMMOVE)
- {
- sOps.moveEntry = s_CopyEntry;
- }
-
- if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
- {
- // if failed, reset "flag"
- mTable.entrySize = 0;
- return PR_FALSE;
- }
- return PR_TRUE;
- }
- // static definitions
- template<class EntryType>
- PLDHashNumber
- nsTHashtable<EntryType>::s_HashKey(PLDHashTable *table,
- const void *key)
- {
- return EntryType::HashKey(reinterpret_cast<const KeyTypePointer>(key));
- }
- template<class EntryType>
- PRBool
- nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable *table,
- const PLDHashEntryHdr *entry,
- const void *key)
- {
- return ((const EntryType*) entry)->KeyEquals(
- reinterpret_cast<const KeyTypePointer>(key));
- }
- template<class EntryType>
- void
- nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable *table,
- const PLDHashEntryHdr *from,
- PLDHashEntryHdr *to)
- {
- EntryType* fromEntry =
- const_cast<EntryType*>(reinterpret_cast<const EntryType*>(from));
- new(to) EntryType(*fromEntry);
- fromEntry->~EntryType();
- }
- template<class EntryType>
- void
- nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable *table,
- PLDHashEntryHdr *entry)
- {
- reinterpret_cast<EntryType*>(entry)->~EntryType();
- }
- template<class EntryType>
- PRBool
- nsTHashtable<EntryType>::s_InitEntry(PLDHashTable *table,
- PLDHashEntryHdr *entry,
- const void *key)
- {
- new(entry) EntryType(reinterpret_cast<KeyTypePointer>(key));
- return PR_TRUE;
- }
- template<class EntryType>
- PLDHashOperator
- nsTHashtable<EntryType>::s_EnumStub(PLDHashTable *table,
- PLDHashEntryHdr *entry,
- PRUint32 number,
- void *arg)
- {
- // dereferences the function-pointer to the user's enumeration function
- return (* reinterpret_cast<s_EnumArgs*>(arg)->userFunc)(
- reinterpret_cast<EntryType*>(entry),
- reinterpret_cast<s_EnumArgs*>(arg)->userArg);
- }
- #endif // nsTHashtable_h__