PageRenderTime 33ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/gecko_api/include/nsTHashtable.h

http://firefox-mac-pdf.googlecode.com/
C Header | 417 lines | 192 code | 52 blank | 173 comment | 4 complexity | 8cf9eb6444acbf86a49634a425936bd9 MD5 | raw file
  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
  4. *
  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/
  9. *
  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.
  14. *
  15. * The Original Code is C++ hashtable templates.
  16. *
  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.
  21. *
  22. * Contributor(s):
  23. *
  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.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. #ifndef nsTHashtable_h__
  38. #define nsTHashtable_h__
  39. #include "nscore.h"
  40. #include "pldhash.h"
  41. #include "nsDebug.h"
  42. #include NEW_H
  43. // helper function for nsTHashtable::Clear()
  44. NS_COM_GLUE PLDHashOperator
  45. PL_DHashStubEnumRemove(PLDHashTable *table,
  46. PLDHashEntryHdr *entry,
  47. PRUint32 ordinal,
  48. void *userArg);
  49. /**
  50. * a base class for templated hashtables.
  51. *
  52. * Clients will rarely need to use this class directly. Check the derived
  53. * classes first, to see if they will meet your needs.
  54. *
  55. * @param EntryType the templated entry-type class that is managed by the
  56. * hashtable. <code>EntryType</code> must extend the following declaration,
  57. * and <strong>must not declare any virtual functions or derive from classes
  58. * with virtual functions.</strong> Any vtable pointer would break the
  59. * PLDHashTable code.
  60. *<pre> class EntryType : public PLDHashEntryHdr
  61. * {
  62. * public: or friend nsTHashtable<EntryType>;
  63. * // KeyType is what we use when Get()ing or Put()ing this entry
  64. * // this should either be a simple datatype (PRUint32, nsISupports*) or
  65. * // a const reference (const nsAString&)
  66. * typedef something KeyType;
  67. * // KeyTypePointer is the pointer-version of KeyType, because pldhash.h
  68. * // requires keys to cast to <code>const void*</code>
  69. * typedef const something* KeyTypePointer;
  70. *
  71. * EntryType(KeyTypePointer aKey);
  72. *
  73. * // the copy constructor must be defined, even if AllowMemMove() == true
  74. * // or you will cause link errors!
  75. * EntryType(const EntryType& aEnt);
  76. *
  77. * // the destructor must be defined... or you will cause link errors!
  78. * ~EntryType();
  79. *
  80. * // KeyEquals(): does this entry match this key?
  81. * PRBool KeyEquals(KeyTypePointer aKey) const;
  82. *
  83. * // KeyToPointer(): Convert KeyType to KeyTypePointer
  84. * static KeyTypePointer KeyToPointer(KeyType aKey);
  85. *
  86. * // HashKey(): calculate the hash number
  87. * static PLDHashNumber HashKey(KeyTypePointer aKey);
  88. *
  89. * // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
  90. * // to use the copy constructor?
  91. * enum { ALLOW_MEMMOVE = PR_(TRUE or FALSE) };
  92. * }</pre>
  93. *
  94. * @see nsInterfaceHashtable
  95. * @see nsDataHashtable
  96. * @see nsClassHashtable
  97. * @author "Benjamin Smedberg <bsmedberg@covad.net>"
  98. */
  99. template<class EntryType>
  100. class nsTHashtable
  101. {
  102. public:
  103. /**
  104. * A dummy constructor; you must call Init() before using this class.
  105. */
  106. nsTHashtable();
  107. /**
  108. * destructor, cleans up and deallocates
  109. */
  110. ~nsTHashtable();
  111. /**
  112. * Initialize the table. This function must be called before any other
  113. * class operations. This can fail due to OOM conditions.
  114. * @param initSize the initial number of buckets in the hashtable, default 16
  115. * @return PR_TRUE if the class was initialized properly.
  116. */
  117. PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
  118. /**
  119. * Check whether the table has been initialized. This can be useful for static hashtables.
  120. * @return the initialization state of the class.
  121. */
  122. PRBool IsInitialized() const { return !!mTable.entrySize; }
  123. /**
  124. * KeyType is typedef'ed for ease of use.
  125. */
  126. typedef typename EntryType::KeyType KeyType;
  127. /**
  128. * KeyTypePointer is typedef'ed for ease of use.
  129. */
  130. typedef typename EntryType::KeyTypePointer KeyTypePointer;
  131. /**
  132. * Return the number of entries in the table.
  133. * @return number of entries
  134. */
  135. PRUint32 Count() const { return mTable.entryCount; }
  136. /**
  137. * Get the entry associated with a key.
  138. * @param aKey the key to retrieve
  139. * @return pointer to the entry class, if the key exists; nsnull if the
  140. * key doesn't exist
  141. */
  142. EntryType* GetEntry(KeyType aKey) const
  143. {
  144. NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
  145. EntryType* entry =
  146. reinterpret_cast<EntryType*>
  147. (PL_DHashTableOperate(
  148. const_cast<PLDHashTable*>(&mTable),
  149. EntryType::KeyToPointer(aKey),
  150. PL_DHASH_LOOKUP));
  151. return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nsnull;
  152. }
  153. /**
  154. * Get the entry associated with a key, or create a new entry,
  155. * @param aKey the key to retrieve
  156. * @return pointer to the entry class retreived; nsnull only if memory
  157. can't be allocated
  158. */
  159. EntryType* PutEntry(KeyType aKey)
  160. {
  161. NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
  162. return static_cast<EntryType*>
  163. (PL_DHashTableOperate(
  164. &mTable,
  165. EntryType::KeyToPointer(aKey),
  166. PL_DHASH_ADD));
  167. }
  168. /**
  169. * Remove the entry associated with a key.
  170. * @param aKey of the entry to remove
  171. */
  172. void RemoveEntry(KeyType aKey)
  173. {
  174. NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
  175. PL_DHashTableOperate(&mTable,
  176. EntryType::KeyToPointer(aKey),
  177. PL_DHASH_REMOVE);
  178. }
  179. /**
  180. * Remove the entry associated with a key, but don't resize the hashtable.
  181. * This is a low-level method, and is not recommended unless you know what
  182. * you're doing and you need the extra performance. This method can be used
  183. * during enumeration, while RemoveEntry() cannot.
  184. * @param aEntry the entry-pointer to remove (obtained from GetEntry or
  185. * the enumerator
  186. */
  187. void RawRemoveEntry(EntryType* aEntry)
  188. {
  189. PL_DHashTableRawRemove(&mTable, aEntry);
  190. }
  191. /**
  192. * client must provide an <code>Enumerator</code> function for
  193. * EnumerateEntries
  194. * @param aEntry the entry being enumerated
  195. * @param userArg passed unchanged from <code>EnumerateEntries</code>
  196. * @return combination of flags
  197. * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink ,
  198. * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink ,
  199. * @link PLDHashOperator::PL_DHASH_REMOVE PL_DHASH_REMOVE @endlink
  200. */
  201. typedef PLDHashOperator (*PR_CALLBACK Enumerator)(EntryType* aEntry, void* userArg);
  202. /**
  203. * Enumerate all the entries of the function.
  204. * @param enumFunc the <code>Enumerator</code> function to call
  205. * @param userArg a pointer to pass to the
  206. * <code>Enumerator</code> function
  207. * @return the number of entries actually enumerated
  208. */
  209. PRUint32 EnumerateEntries(Enumerator enumFunc, void* userArg)
  210. {
  211. NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
  212. s_EnumArgs args = { enumFunc, userArg };
  213. return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args);
  214. }
  215. /**
  216. * remove all entries, return hashtable to "pristine" state ;)
  217. */
  218. void Clear()
  219. {
  220. NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
  221. PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
  222. }
  223. protected:
  224. PLDHashTable mTable;
  225. static const void* PR_CALLBACK s_GetKey(PLDHashTable *table,
  226. PLDHashEntryHdr *entry);
  227. static PLDHashNumber PR_CALLBACK s_HashKey(PLDHashTable *table,
  228. const void *key);
  229. static PRBool PR_CALLBACK s_MatchEntry(PLDHashTable *table,
  230. const PLDHashEntryHdr *entry,
  231. const void *key);
  232. static void PR_CALLBACK s_CopyEntry(PLDHashTable *table,
  233. const PLDHashEntryHdr *from,
  234. PLDHashEntryHdr *to);
  235. static void PR_CALLBACK s_ClearEntry(PLDHashTable *table,
  236. PLDHashEntryHdr *entry);
  237. static PRBool PR_CALLBACK s_InitEntry(PLDHashTable *table,
  238. PLDHashEntryHdr *entry,
  239. const void *key);
  240. /**
  241. * passed internally during enumeration. Allocated on the stack.
  242. *
  243. * @param userFunc the Enumerator function passed to
  244. * EnumerateEntries by the client
  245. * @param userArg the userArg passed unaltered
  246. */
  247. struct s_EnumArgs
  248. {
  249. Enumerator userFunc;
  250. void* userArg;
  251. };
  252. static PLDHashOperator PR_CALLBACK s_EnumStub(PLDHashTable *table,
  253. PLDHashEntryHdr *entry,
  254. PRUint32 number,
  255. void *arg);
  256. private:
  257. // copy constructor, not implemented
  258. nsTHashtable(nsTHashtable<EntryType>& toCopy);
  259. // assignment operator, not implemented
  260. nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
  261. };
  262. //
  263. // template definitions
  264. //
  265. template<class EntryType>
  266. nsTHashtable<EntryType>::nsTHashtable()
  267. {
  268. // entrySize is our "I'm initialized" indicator
  269. mTable.entrySize = 0;
  270. }
  271. template<class EntryType>
  272. nsTHashtable<EntryType>::~nsTHashtable()
  273. {
  274. if (mTable.entrySize)
  275. PL_DHashTableFinish(&mTable);
  276. }
  277. template<class EntryType>
  278. PRBool
  279. nsTHashtable<EntryType>::Init(PRUint32 initSize)
  280. {
  281. if (mTable.entrySize)
  282. {
  283. NS_ERROR("nsTHashtable::Init() should not be called twice.");
  284. return PR_TRUE;
  285. }
  286. static PLDHashTableOps sOps =
  287. {
  288. ::PL_DHashAllocTable,
  289. ::PL_DHashFreeTable,
  290. s_HashKey,
  291. s_MatchEntry,
  292. ::PL_DHashMoveEntryStub,
  293. s_ClearEntry,
  294. ::PL_DHashFinalizeStub,
  295. s_InitEntry
  296. };
  297. if (!EntryType::ALLOW_MEMMOVE)
  298. {
  299. sOps.moveEntry = s_CopyEntry;
  300. }
  301. if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
  302. {
  303. // if failed, reset "flag"
  304. mTable.entrySize = 0;
  305. return PR_FALSE;
  306. }
  307. return PR_TRUE;
  308. }
  309. // static definitions
  310. template<class EntryType>
  311. PLDHashNumber
  312. nsTHashtable<EntryType>::s_HashKey(PLDHashTable *table,
  313. const void *key)
  314. {
  315. return EntryType::HashKey(reinterpret_cast<const KeyTypePointer>(key));
  316. }
  317. template<class EntryType>
  318. PRBool
  319. nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable *table,
  320. const PLDHashEntryHdr *entry,
  321. const void *key)
  322. {
  323. return ((const EntryType*) entry)->KeyEquals(
  324. reinterpret_cast<const KeyTypePointer>(key));
  325. }
  326. template<class EntryType>
  327. void
  328. nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable *table,
  329. const PLDHashEntryHdr *from,
  330. PLDHashEntryHdr *to)
  331. {
  332. EntryType* fromEntry =
  333. const_cast<EntryType*>(reinterpret_cast<const EntryType*>(from));
  334. new(to) EntryType(*fromEntry);
  335. fromEntry->~EntryType();
  336. }
  337. template<class EntryType>
  338. void
  339. nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable *table,
  340. PLDHashEntryHdr *entry)
  341. {
  342. reinterpret_cast<EntryType*>(entry)->~EntryType();
  343. }
  344. template<class EntryType>
  345. PRBool
  346. nsTHashtable<EntryType>::s_InitEntry(PLDHashTable *table,
  347. PLDHashEntryHdr *entry,
  348. const void *key)
  349. {
  350. new(entry) EntryType(reinterpret_cast<KeyTypePointer>(key));
  351. return PR_TRUE;
  352. }
  353. template<class EntryType>
  354. PLDHashOperator
  355. nsTHashtable<EntryType>::s_EnumStub(PLDHashTable *table,
  356. PLDHashEntryHdr *entry,
  357. PRUint32 number,
  358. void *arg)
  359. {
  360. // dereferences the function-pointer to the user's enumeration function
  361. return (* reinterpret_cast<s_EnumArgs*>(arg)->userFunc)(
  362. reinterpret_cast<EntryType*>(entry),
  363. reinterpret_cast<s_EnumArgs*>(arg)->userArg);
  364. }
  365. #endif // nsTHashtable_h__