Merge tracemonkey and mozilla-central. (a=blockers)
[mozilla-central.git] / xpcom / glue / nsTHashtable.h
blob686a087536157ee47247accc19182be3a44adba8
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is C++ hashtable templates.
17 * The Initial Developer of the Original Code is
18 * Benjamin Smedberg.
19 * Portions created by the Initial Developer are Copyright (C) 2002
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nsTHashtable_h__
39 #define nsTHashtable_h__
41 #include "nscore.h"
42 #include "pldhash.h"
43 #include "nsDebug.h"
44 #include NEW_H
46 // helper function for nsTHashtable::Clear()
47 NS_COM_GLUE PLDHashOperator
48 PL_DHashStubEnumRemove(PLDHashTable *table,
49 PLDHashEntryHdr *entry,
50 PRUint32 ordinal,
51 void *userArg);
54 /**
55 * a base class for templated hashtables.
57 * Clients will rarely need to use this class directly. Check the derived
58 * classes first, to see if they will meet your needs.
60 * @param EntryType the templated entry-type class that is managed by the
61 * hashtable. <code>EntryType</code> must extend the following declaration,
62 * and <strong>must not declare any virtual functions or derive from classes
63 * with virtual functions.</strong> Any vtable pointer would break the
64 * PLDHashTable code.
65 *<pre> class EntryType : public PLDHashEntryHdr
66 * {
67 * public: or friend nsTHashtable<EntryType>;
68 * // KeyType is what we use when Get()ing or Put()ing this entry
69 * // this should either be a simple datatype (PRUint32, nsISupports*) or
70 * // a const reference (const nsAString&)
71 * typedef something KeyType;
72 * // KeyTypePointer is the pointer-version of KeyType, because pldhash.h
73 * // requires keys to cast to <code>const void*</code>
74 * typedef const something* KeyTypePointer;
76 * EntryType(KeyTypePointer aKey);
78 * // the copy constructor must be defined, even if AllowMemMove() == true
79 * // or you will cause link errors!
80 * EntryType(const EntryType& aEnt);
82 * // the destructor must be defined... or you will cause link errors!
83 * ~EntryType();
85 * // KeyEquals(): does this entry match this key?
86 * PRBool KeyEquals(KeyTypePointer aKey) const;
88 * // KeyToPointer(): Convert KeyType to KeyTypePointer
89 * static KeyTypePointer KeyToPointer(KeyType aKey);
91 * // HashKey(): calculate the hash number
92 * static PLDHashNumber HashKey(KeyTypePointer aKey);
94 * // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
95 * // to use the copy constructor?
96 * enum { ALLOW_MEMMOVE = PR_(TRUE or FALSE) };
97 * }</pre>
99 * @see nsInterfaceHashtable
100 * @see nsDataHashtable
101 * @see nsClassHashtable
102 * @author "Benjamin Smedberg <bsmedberg@covad.net>"
105 template<class EntryType>
106 class nsTHashtable
108 public:
110 * A dummy constructor; you must call Init() before using this class.
112 nsTHashtable();
115 * destructor, cleans up and deallocates
117 ~nsTHashtable();
120 * Initialize the table. This function must be called before any other
121 * class operations. This can fail due to OOM conditions.
122 * @param initSize the initial number of buckets in the hashtable, default 16
123 * @return PR_TRUE if the class was initialized properly.
125 PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
128 * Check whether the table has been initialized. This can be useful for static hashtables.
129 * @return the initialization state of the class.
131 PRBool IsInitialized() const { return !!mTable.entrySize; }
134 * Return the generation number for the table. This increments whenever
135 * the table data items are moved.
137 PRUint32 GetGeneration() const { return mTable.generation; }
140 * KeyType is typedef'ed for ease of use.
142 typedef typename EntryType::KeyType KeyType;
145 * KeyTypePointer is typedef'ed for ease of use.
147 typedef typename EntryType::KeyTypePointer KeyTypePointer;
150 * Return the number of entries in the table.
151 * @return number of entries
153 PRUint32 Count() const { return mTable.entryCount; }
156 * Get the entry associated with a key.
157 * @param aKey the key to retrieve
158 * @return pointer to the entry class, if the key exists; nsnull if the
159 * key doesn't exist
161 EntryType* GetEntry(KeyType aKey) const
163 NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
165 EntryType* entry =
166 reinterpret_cast<EntryType*>
167 (PL_DHashTableOperate(
168 const_cast<PLDHashTable*>(&mTable),
169 EntryType::KeyToPointer(aKey),
170 PL_DHASH_LOOKUP));
171 return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nsnull;
175 * Get the entry associated with a key, or create a new entry,
176 * @param aKey the key to retrieve
177 * @return pointer to the entry class retreived; nsnull only if memory
178 can't be allocated
180 EntryType* PutEntry(KeyType aKey)
182 NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
184 return static_cast<EntryType*>
185 (PL_DHashTableOperate(
186 &mTable,
187 EntryType::KeyToPointer(aKey),
188 PL_DHASH_ADD));
192 * Remove the entry associated with a key.
193 * @param aKey of the entry to remove
195 void RemoveEntry(KeyType aKey)
197 NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
199 PL_DHashTableOperate(&mTable,
200 EntryType::KeyToPointer(aKey),
201 PL_DHASH_REMOVE);
205 * Remove the entry associated with a key, but don't resize the hashtable.
206 * This is a low-level method, and is not recommended unless you know what
207 * you're doing and you need the extra performance. This method can be used
208 * during enumeration, while RemoveEntry() cannot.
209 * @param aEntry the entry-pointer to remove (obtained from GetEntry or
210 * the enumerator
212 void RawRemoveEntry(EntryType* aEntry)
214 PL_DHashTableRawRemove(&mTable, aEntry);
218 * client must provide an <code>Enumerator</code> function for
219 * EnumerateEntries
220 * @param aEntry the entry being enumerated
221 * @param userArg passed unchanged from <code>EnumerateEntries</code>
222 * @return combination of flags
223 * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink ,
224 * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink ,
225 * @link PLDHashOperator::PL_DHASH_REMOVE PL_DHASH_REMOVE @endlink
227 typedef PLDHashOperator (* Enumerator)(EntryType* aEntry, void* userArg);
230 * Enumerate all the entries of the function.
231 * @param enumFunc the <code>Enumerator</code> function to call
232 * @param userArg a pointer to pass to the
233 * <code>Enumerator</code> function
234 * @return the number of entries actually enumerated
236 PRUint32 EnumerateEntries(Enumerator enumFunc, void* userArg)
238 NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
240 s_EnumArgs args = { enumFunc, userArg };
241 return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args);
245 * remove all entries, return hashtable to "pristine" state ;)
247 void Clear()
249 NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
251 PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
254 protected:
255 PLDHashTable mTable;
257 static const void* s_GetKey(PLDHashTable *table,
258 PLDHashEntryHdr *entry);
260 static PLDHashNumber s_HashKey(PLDHashTable *table,
261 const void *key);
263 static PRBool s_MatchEntry(PLDHashTable *table,
264 const PLDHashEntryHdr *entry,
265 const void *key);
267 static void s_CopyEntry(PLDHashTable *table,
268 const PLDHashEntryHdr *from,
269 PLDHashEntryHdr *to);
271 static void s_ClearEntry(PLDHashTable *table,
272 PLDHashEntryHdr *entry);
274 static PRBool s_InitEntry(PLDHashTable *table,
275 PLDHashEntryHdr *entry,
276 const void *key);
279 * passed internally during enumeration. Allocated on the stack.
281 * @param userFunc the Enumerator function passed to
282 * EnumerateEntries by the client
283 * @param userArg the userArg passed unaltered
285 struct s_EnumArgs
287 Enumerator userFunc;
288 void* userArg;
291 static PLDHashOperator s_EnumStub(PLDHashTable *table,
292 PLDHashEntryHdr *entry,
293 PRUint32 number,
294 void *arg);
295 private:
296 // copy constructor, not implemented
297 nsTHashtable(nsTHashtable<EntryType>& toCopy);
299 // assignment operator, not implemented
300 nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
304 // template definitions
307 template<class EntryType>
308 nsTHashtable<EntryType>::nsTHashtable()
310 // entrySize is our "I'm initialized" indicator
311 mTable.entrySize = 0;
314 template<class EntryType>
315 nsTHashtable<EntryType>::~nsTHashtable()
317 if (mTable.entrySize)
318 PL_DHashTableFinish(&mTable);
321 template<class EntryType>
322 PRBool
323 nsTHashtable<EntryType>::Init(PRUint32 initSize)
325 if (mTable.entrySize)
327 NS_ERROR("nsTHashtable::Init() should not be called twice.");
328 return PR_TRUE;
331 static PLDHashTableOps sOps =
333 ::PL_DHashAllocTable,
334 ::PL_DHashFreeTable,
335 s_HashKey,
336 s_MatchEntry,
337 ::PL_DHashMoveEntryStub,
338 s_ClearEntry,
339 ::PL_DHashFinalizeStub,
340 s_InitEntry
343 if (!EntryType::ALLOW_MEMMOVE)
345 sOps.moveEntry = s_CopyEntry;
348 if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
350 // if failed, reset "flag"
351 mTable.entrySize = 0;
352 return PR_FALSE;
355 return PR_TRUE;
358 // static definitions
360 template<class EntryType>
361 PLDHashNumber
362 nsTHashtable<EntryType>::s_HashKey(PLDHashTable *table,
363 const void *key)
365 return EntryType::HashKey(reinterpret_cast<const KeyTypePointer>(key));
368 template<class EntryType>
369 PRBool
370 nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable *table,
371 const PLDHashEntryHdr *entry,
372 const void *key)
374 return ((const EntryType*) entry)->KeyEquals(
375 reinterpret_cast<const KeyTypePointer>(key));
378 template<class EntryType>
379 void
380 nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable *table,
381 const PLDHashEntryHdr *from,
382 PLDHashEntryHdr *to)
384 EntryType* fromEntry =
385 const_cast<EntryType*>(reinterpret_cast<const EntryType*>(from));
387 new(to) EntryType(*fromEntry);
389 fromEntry->~EntryType();
392 template<class EntryType>
393 void
394 nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable *table,
395 PLDHashEntryHdr *entry)
397 reinterpret_cast<EntryType*>(entry)->~EntryType();
400 template<class EntryType>
401 PRBool
402 nsTHashtable<EntryType>::s_InitEntry(PLDHashTable *table,
403 PLDHashEntryHdr *entry,
404 const void *key)
406 new(entry) EntryType(reinterpret_cast<KeyTypePointer>(key));
407 return PR_TRUE;
410 template<class EntryType>
411 PLDHashOperator
412 nsTHashtable<EntryType>::s_EnumStub(PLDHashTable *table,
413 PLDHashEntryHdr *entry,
414 PRUint32 number,
415 void *arg)
417 // dereferences the function-pointer to the user's enumeration function
418 return (* reinterpret_cast<s_EnumArgs*>(arg)->userFunc)(
419 reinterpret_cast<EntryType*>(entry),
420 reinterpret_cast<s_EnumArgs*>(arg)->userArg);
423 #endif // nsTHashtable_h__