hash.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/hash.h
  3. // Purpose: wxHashTable class
  4. // Author: Julian Smart
  5. // Modified by: VZ at 25.02.00: type safe hashes with WX_DECLARE_HASH()
  6. // Created: 01/02/97
  7. // Copyright: (c) Julian Smart
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. #ifndef _WX_HASH_H__
  11. #define _WX_HASH_H__
  12. #include "wx/defs.h"
  13. #include "wx/string.h"
  14. #if !wxUSE_STD_CONTAINERS
  15. #include "wx/object.h"
  16. #else
  17. class WXDLLIMPEXP_FWD_BASE wxObject;
  18. #endif
  19. // the default size of the hash
  20. #define wxHASH_SIZE_DEFAULT (1000)
  21. /*
  22. * A hash table is an array of user-definable size with lists
  23. * of data items hanging off the array positions. Usually there'll
  24. * be a hit, so no search is required; otherwise we'll have to run down
  25. * the list to find the desired item.
  26. */
  27. union wxHashKeyValue
  28. {
  29. long integer;
  30. wxString *string;
  31. };
  32. // for some compilers (AIX xlC), defining it as friend inside the class is not
  33. // enough, so provide a real forward declaration
  34. class WXDLLIMPEXP_FWD_BASE wxHashTableBase;
  35. class WXDLLIMPEXP_BASE wxHashTableBase_Node
  36. {
  37. friend class WXDLLIMPEXP_FWD_BASE wxHashTableBase;
  38. typedef class WXDLLIMPEXP_FWD_BASE wxHashTableBase_Node _Node;
  39. public:
  40. wxHashTableBase_Node( long key, void* value,
  41. wxHashTableBase* table );
  42. wxHashTableBase_Node( const wxString& key, void* value,
  43. wxHashTableBase* table );
  44. ~wxHashTableBase_Node();
  45. long GetKeyInteger() const { return m_key.integer; }
  46. const wxString& GetKeyString() const { return *m_key.string; }
  47. void* GetData() const { return m_value; }
  48. void SetData( void* data ) { m_value = data; }
  49. protected:
  50. _Node* GetNext() const { return m_next; }
  51. protected:
  52. // next node in the chain
  53. wxHashTableBase_Node* m_next;
  54. // key
  55. wxHashKeyValue m_key;
  56. // value
  57. void* m_value;
  58. // pointer to the hash containing the node, used to remove the
  59. // node from the hash when the user deletes the node iterating
  60. // through it
  61. // TODO: move it to wxHashTable_Node (only wxHashTable supports
  62. // iteration)
  63. wxHashTableBase* m_hashPtr;
  64. };
  65. class WXDLLIMPEXP_BASE wxHashTableBase
  66. #if !wxUSE_STD_CONTAINERS
  67. : public wxObject
  68. #endif
  69. {
  70. friend class WXDLLIMPEXP_FWD_BASE wxHashTableBase_Node;
  71. public:
  72. typedef wxHashTableBase_Node Node;
  73. wxHashTableBase();
  74. virtual ~wxHashTableBase() { }
  75. void Create( wxKeyType keyType = wxKEY_INTEGER,
  76. size_t size = wxHASH_SIZE_DEFAULT );
  77. void Clear();
  78. void Destroy();
  79. size_t GetSize() const { return m_size; }
  80. size_t GetCount() const { return m_count; }
  81. void DeleteContents( bool flag ) { m_deleteContents = flag; }
  82. static long MakeKey(const wxString& string);
  83. protected:
  84. void DoPut( long key, long hash, void* data );
  85. void DoPut( const wxString& key, long hash, void* data );
  86. void* DoGet( long key, long hash ) const;
  87. void* DoGet( const wxString& key, long hash ) const;
  88. void* DoDelete( long key, long hash );
  89. void* DoDelete( const wxString& key, long hash );
  90. private:
  91. // Remove the node from the hash, *only called from
  92. // ~wxHashTable*_Node destructor
  93. void DoRemoveNode( wxHashTableBase_Node* node );
  94. // destroys data contained in the node if appropriate:
  95. // deletes the key if it is a string and destrys
  96. // the value if m_deleteContents is true
  97. void DoDestroyNode( wxHashTableBase_Node* node );
  98. // inserts a node in the table (at the end of the chain)
  99. void DoInsertNode( size_t bucket, wxHashTableBase_Node* node );
  100. // removes a node from the table (fiven a pointer to the previous
  101. // but does not delete it (only deletes its contents)
  102. void DoUnlinkNode( size_t bucket, wxHashTableBase_Node* node,
  103. wxHashTableBase_Node* prev );
  104. // unconditionally deletes node value (invoking the
  105. // correct destructor)
  106. virtual void DoDeleteContents( wxHashTableBase_Node* node ) = 0;
  107. protected:
  108. // number of buckets
  109. size_t m_size;
  110. // number of nodes (key/value pairs)
  111. size_t m_count;
  112. // table
  113. Node** m_table;
  114. // key typ (INTEGER/STRING)
  115. wxKeyType m_keyType;
  116. // delete contents when hash is cleared
  117. bool m_deleteContents;
  118. private:
  119. wxDECLARE_NO_COPY_CLASS(wxHashTableBase);
  120. };
  121. // ----------------------------------------------------------------------------
  122. // for compatibility only
  123. // ----------------------------------------------------------------------------
  124. class WXDLLIMPEXP_BASE wxHashTable_Node : public wxHashTableBase_Node
  125. {
  126. friend class WXDLLIMPEXP_FWD_BASE wxHashTable;
  127. public:
  128. wxHashTable_Node( long key, void* value,
  129. wxHashTableBase* table )
  130. : wxHashTableBase_Node( key, value, table ) { }
  131. wxHashTable_Node( const wxString& key, void* value,
  132. wxHashTableBase* table )
  133. : wxHashTableBase_Node( key, value, table ) { }
  134. wxObject* GetData() const
  135. { return (wxObject*)wxHashTableBase_Node::GetData(); }
  136. void SetData( wxObject* data )
  137. { wxHashTableBase_Node::SetData( data ); }
  138. wxHashTable_Node* GetNext() const
  139. { return (wxHashTable_Node*)wxHashTableBase_Node::GetNext(); }
  140. };
  141. // should inherit protectedly, but it is public for compatibility in
  142. // order to publicly inherit from wxObject
  143. class WXDLLIMPEXP_BASE wxHashTable : public wxHashTableBase
  144. {
  145. typedef wxHashTableBase hash;
  146. public:
  147. typedef wxHashTable_Node Node;
  148. typedef wxHashTable_Node* compatibility_iterator;
  149. public:
  150. wxHashTable( wxKeyType keyType = wxKEY_INTEGER,
  151. size_t size = wxHASH_SIZE_DEFAULT )
  152. : wxHashTableBase() { Create( keyType, size ); BeginFind(); }
  153. wxHashTable( const wxHashTable& table );
  154. virtual ~wxHashTable() { Destroy(); }
  155. const wxHashTable& operator=( const wxHashTable& );
  156. // key and value are the same
  157. void Put(long value, wxObject *object)
  158. { DoPut( value, value, object ); }
  159. void Put(long lhash, long value, wxObject *object)
  160. { DoPut( value, lhash, object ); }
  161. void Put(const wxString& value, wxObject *object)
  162. { DoPut( value, MakeKey( value ), object ); }
  163. void Put(long lhash, const wxString& value, wxObject *object)
  164. { DoPut( value, lhash, object ); }
  165. // key and value are the same
  166. wxObject *Get(long value) const
  167. { return (wxObject*)DoGet( value, value ); }
  168. wxObject *Get(long lhash, long value) const
  169. { return (wxObject*)DoGet( value, lhash ); }
  170. wxObject *Get(const wxString& value) const
  171. { return (wxObject*)DoGet( value, MakeKey( value ) ); }
  172. wxObject *Get(long lhash, const wxString& value) const
  173. { return (wxObject*)DoGet( value, lhash ); }
  174. // Deletes entry and returns data if found
  175. wxObject *Delete(long key)
  176. { return (wxObject*)DoDelete( key, key ); }
  177. wxObject *Delete(long lhash, long key)
  178. { return (wxObject*)DoDelete( key, lhash ); }
  179. wxObject *Delete(const wxString& key)
  180. { return (wxObject*)DoDelete( key, MakeKey( key ) ); }
  181. wxObject *Delete(long lhash, const wxString& key)
  182. { return (wxObject*)DoDelete( key, lhash ); }
  183. // Way of iterating through whole hash table (e.g. to delete everything)
  184. // Not necessary, of course, if you're only storing pointers to
  185. // objects maintained separately
  186. void BeginFind() { m_curr = NULL; m_currBucket = 0; }
  187. Node* Next();
  188. void Clear() { wxHashTableBase::Clear(); }
  189. size_t GetCount() const { return wxHashTableBase::GetCount(); }
  190. protected:
  191. // copy helper
  192. void DoCopy( const wxHashTable& copy );
  193. // searches the next node starting from bucket bucketStart and sets
  194. // m_curr to it and m_currBucket to its bucket
  195. void GetNextNode( size_t bucketStart );
  196. private:
  197. virtual void DoDeleteContents( wxHashTableBase_Node* node );
  198. // current node
  199. Node* m_curr;
  200. // bucket the current node belongs to
  201. size_t m_currBucket;
  202. };
  203. // defines a new type safe hash table which stores the elements of type eltype
  204. // in lists of class listclass
  205. #define _WX_DECLARE_HASH(eltype, dummy, hashclass, classexp) \
  206. classexp hashclass : public wxHashTableBase \
  207. { \
  208. public: \
  209. hashclass(wxKeyType keyType = wxKEY_INTEGER, \
  210. size_t size = wxHASH_SIZE_DEFAULT) \
  211. : wxHashTableBase() { Create(keyType, size); } \
  212. \
  213. virtual ~hashclass() { Destroy(); } \
  214. \
  215. void Put(long key, eltype *data) { DoPut(key, key, (void*)data); } \
  216. void Put(long lhash, long key, eltype *data) \
  217. { DoPut(key, lhash, (void*)data); } \
  218. eltype *Get(long key) const { return (eltype*)DoGet(key, key); } \
  219. eltype *Get(long lhash, long key) const \
  220. { return (eltype*)DoGet(key, lhash); } \
  221. eltype *Delete(long key) { return (eltype*)DoDelete(key, key); } \
  222. eltype *Delete(long lhash, long key) \
  223. { return (eltype*)DoDelete(key, lhash); } \
  224. private: \
  225. virtual void DoDeleteContents( wxHashTableBase_Node* node ) \
  226. { delete (eltype*)node->GetData(); } \
  227. \
  228. DECLARE_NO_COPY_CLASS(hashclass) \
  229. }
  230. // this macro is to be used in the user code
  231. #define WX_DECLARE_HASH(el, list, hash) \
  232. _WX_DECLARE_HASH(el, list, hash, class)
  233. // and this one does exactly the same thing but should be used inside the
  234. // library
  235. #define WX_DECLARE_EXPORTED_HASH(el, list, hash) \
  236. _WX_DECLARE_HASH(el, list, hash, class WXDLLIMPEXP_CORE)
  237. #define WX_DECLARE_USER_EXPORTED_HASH(el, list, hash, usergoo) \
  238. _WX_DECLARE_HASH(el, list, hash, class usergoo)
  239. // delete all hash elements
  240. //
  241. // NB: the class declaration of the hash elements must be visible from the
  242. // place where you use this macro, otherwise the proper destructor may not
  243. // be called (a decent compiler should give a warning about it, but don't
  244. // count on it)!
  245. #define WX_CLEAR_HASH_TABLE(hash) \
  246. { \
  247. (hash).BeginFind(); \
  248. wxHashTable::compatibility_iterator it = (hash).Next(); \
  249. while( it ) \
  250. { \
  251. delete it->GetData(); \
  252. it = (hash).Next(); \
  253. } \
  254. (hash).Clear(); \
  255. }
  256. #endif // _WX_HASH_H__