]>
Commit | Line | Data |
---|---|---|
c801d85f | 1 | ///////////////////////////////////////////////////////////////////////////// |
bcaa23de | 2 | // Name: wx/hash.h |
c801d85f KB |
3 | // Purpose: wxHashTable class |
4 | // Author: Julian Smart | |
bcaa23de | 5 | // Modified by: VZ at 25.02.00: type safe hashes with WX_DECLARE_HASH() |
c801d85f KB |
6 | // Created: 01/02/97 |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) | |
bcaa23de | 9 | // Licence: wxWindows licence |
c801d85f KB |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
bcaa23de VZ |
12 | #ifndef _WX_HASH_H__ |
13 | #define _WX_HASH_H__ | |
c801d85f | 14 | |
af49c4b8 | 15 | #if defined(__GNUG__) && !defined(__APPLE__) |
c801d85f KB |
16 | #pragma interface "hash.h" |
17 | #endif | |
18 | ||
c801d85f | 19 | #include "wx/list.h" |
c2bb85e9 | 20 | #include "wx/dynarray.h" |
c801d85f | 21 | |
bcaa23de VZ |
22 | // the default size of the hash |
23 | #define wxHASH_SIZE_DEFAULT (1000) | |
24 | ||
c801d85f KB |
25 | /* |
26 | * A hash table is an array of user-definable size with lists | |
27 | * of data items hanging off the array positions. Usually there'll | |
28 | * be a hit, so no search is required; otherwise we'll have to run down | |
29 | * the list to find the desired item. | |
30 | */ | |
31 | ||
bcaa23de VZ |
32 | // ---------------------------------------------------------------------------- |
33 | // this is the base class for object hashes: hash tables which contain | |
34 | // pointers to objects | |
35 | // ---------------------------------------------------------------------------- | |
36 | ||
bddd7a8d | 37 | class WXDLLIMPEXP_BASE wxHashTableBase : public wxObject |
c801d85f | 38 | { |
bcaa23de VZ |
39 | public: |
40 | wxHashTableBase(); | |
41 | ||
42 | void Create(wxKeyType keyType = wxKEY_INTEGER, | |
43 | size_t size = wxHASH_SIZE_DEFAULT); | |
44 | void Destroy(); | |
45 | ||
46 | size_t GetSize() const { return m_hashSize; } | |
47 | size_t GetCount() const { return m_count; } | |
48 | ||
49 | void DeleteContents(bool flag); | |
50 | ||
51 | protected: | |
52 | // find the node for (key, value) | |
53 | wxNodeBase *GetNode(long key, long value) const; | |
54 | ||
55 | // the array of lists in which we store the values for given key hash | |
56 | wxListBase **m_hashTable; | |
57 | ||
58 | // the size of m_lists array | |
59 | size_t m_hashSize; | |
60 | ||
61 | // the type of indexing we use | |
62 | wxKeyType m_keyType; | |
63 | ||
64 | // the total number of elements in the hash | |
65 | size_t m_count; | |
66 | ||
67 | // should we delete our data? | |
68 | bool m_deleteContents; | |
69 | ||
70 | private: | |
71 | // no copy ctor/assignment operator (yet) | |
1a0d517e | 72 | DECLARE_NO_COPY_CLASS(wxHashTableBase) |
c801d85f KB |
73 | }; |
74 | ||
ba8c1601 MB |
75 | #if WXWIN_COMPATIBILITY_2_4 |
76 | ||
c2bb85e9 VZ |
77 | // ---------------------------------------------------------------------------- |
78 | // a hash table which stores longs | |
79 | // ---------------------------------------------------------------------------- | |
80 | ||
bddd7a8d | 81 | class WXDLLIMPEXP_BASE wxHashTableLong : public wxObject |
c2bb85e9 VZ |
82 | { |
83 | public: | |
d84afea9 GD |
84 | wxHashTableLong(size_t size = wxHASH_SIZE_DEFAULT) |
85 | { Init(size); } | |
a95e38c0 | 86 | virtual ~wxHashTableLong(); |
c2bb85e9 VZ |
87 | |
88 | void Create(size_t size = wxHASH_SIZE_DEFAULT); | |
89 | void Destroy(); | |
90 | ||
91 | size_t GetSize() const { return m_hashSize; } | |
92 | size_t GetCount() const { return m_count; } | |
93 | ||
94 | void Put(long key, long value); | |
95 | long Get(long key) const; | |
96 | long Delete(long key); | |
97 | ||
98 | protected: | |
99 | void Init(size_t size); | |
100 | ||
101 | private: | |
102 | wxArrayLong **m_values, | |
103 | **m_keys; | |
104 | ||
105 | // the size of array above | |
106 | size_t m_hashSize; | |
107 | ||
108 | // the total number of elements in the hash | |
109 | size_t m_count; | |
110 | ||
111 | // not implemented yet | |
1a0d517e | 112 | DECLARE_NO_COPY_CLASS(wxHashTableLong) |
c2bb85e9 VZ |
113 | }; |
114 | ||
bd83cb56 VZ |
115 | // ---------------------------------------------------------------------------- |
116 | // wxStringHashTable: a hash table which indexes strings with longs | |
117 | // ---------------------------------------------------------------------------- | |
118 | ||
bddd7a8d | 119 | class WXDLLIMPEXP_BASE wxStringHashTable : public wxObject |
bd83cb56 VZ |
120 | { |
121 | public: | |
122 | wxStringHashTable(size_t sizeTable = wxHASH_SIZE_DEFAULT); | |
123 | virtual ~wxStringHashTable(); | |
124 | ||
125 | // add a string associated with this key to the table | |
126 | void Put(long key, const wxString& value); | |
127 | ||
128 | // get the string from the key: if not found, an empty string is returned | |
129 | // and the wasFound is set to FALSE if not NULL | |
130 | wxString Get(long key, bool *wasFound = NULL) const; | |
131 | ||
53e112a0 JS |
132 | // remove the item, returning TRUE if the item was found and deleted |
133 | bool Delete(long key) const; | |
134 | ||
bd83cb56 VZ |
135 | // clean up |
136 | void Destroy(); | |
137 | ||
138 | private: | |
139 | wxArrayLong **m_keys; | |
140 | wxArrayString **m_values; | |
141 | ||
142 | // the size of array above | |
143 | size_t m_hashSize; | |
144 | ||
1a0d517e | 145 | DECLARE_NO_COPY_CLASS(wxStringHashTable) |
bd83cb56 VZ |
146 | }; |
147 | ||
ba8c1601 MB |
148 | #endif |
149 | ||
bcaa23de VZ |
150 | // ---------------------------------------------------------------------------- |
151 | // for compatibility only | |
152 | // ---------------------------------------------------------------------------- | |
153 | ||
bddd7a8d | 154 | class WXDLLIMPEXP_BASE wxHashTable : public wxObject |
bcaa23de VZ |
155 | { |
156 | public: | |
157 | int n; | |
158 | int current_position; | |
159 | wxNode *current_node; | |
160 | ||
161 | unsigned int key_type; | |
162 | wxList **hash_table; | |
163 | ||
164 | wxHashTable(int the_key_type = wxKEY_INTEGER, | |
165 | int size = wxHASH_SIZE_DEFAULT); | |
166 | ~wxHashTable(); | |
167 | ||
168 | // copy ctor and assignment operator | |
d84afea9 GD |
169 | wxHashTable(const wxHashTable& table) : wxObject() |
170 | { DoCopy(table); } | |
bcaa23de VZ |
171 | wxHashTable& operator=(const wxHashTable& table) |
172 | { Clear(); DoCopy(table); return *this; } | |
173 | ||
174 | void DoCopy(const wxHashTable& table); | |
175 | ||
176 | void Destroy(); | |
177 | ||
178 | bool Create(int the_key_type = wxKEY_INTEGER, | |
179 | int size = wxHASH_SIZE_DEFAULT); | |
180 | ||
181 | // Note that there are 2 forms of Put, Get. | |
182 | // With a key and a value, the *value* will be checked | |
183 | // when a collision is detected. Otherwise, if there are | |
184 | // 2 items with a different value but the same key, | |
185 | // we'll retrieve the WRONG ONE. So where possible, | |
186 | // supply the required value along with the key. | |
187 | // In fact, the value-only versions make a key, and still store | |
188 | // the value. The use of an explicit key might be required | |
189 | // e.g. when combining several values into one key. | |
190 | // When doing that, it's highly likely we'll get a collision, | |
191 | // e.g. 1 + 2 = 3, 2 + 1 = 3. | |
192 | ||
193 | // key and value are NOT necessarily the same | |
194 | void Put(long key, long value, wxObject *object); | |
195 | void Put(long key, const wxChar *value, wxObject *object); | |
196 | ||
197 | // key and value are the same | |
198 | void Put(long value, wxObject *object); | |
199 | void Put(const wxChar *value, wxObject *object); | |
200 | ||
201 | // key and value not the same | |
202 | wxObject *Get(long key, long value) const; | |
203 | wxObject *Get(long key, const wxChar *value) const; | |
204 | ||
205 | // key and value are the same | |
206 | wxObject *Get(long value) const; | |
207 | wxObject *Get(const wxChar *value) const; | |
208 | ||
209 | // Deletes entry and returns data if found | |
210 | wxObject *Delete(long key); | |
211 | wxObject *Delete(const wxChar *key); | |
212 | ||
213 | wxObject *Delete(long key, int value); | |
214 | wxObject *Delete(long key, const wxChar *value); | |
215 | ||
216 | // Construct your own integer key from a string, e.g. in case | |
217 | // you need to combine it with something | |
218 | long MakeKey(const wxChar *string) const; | |
219 | ||
220 | // Way of iterating through whole hash table (e.g. to delete everything) | |
221 | // Not necessary, of course, if you're only storing pointers to | |
222 | // objects maintained separately | |
223 | ||
224 | void BeginFind(); | |
225 | wxNode *Next(); | |
226 | ||
227 | void DeleteContents(bool flag); | |
228 | void Clear(); | |
229 | ||
230 | // Returns number of nodes | |
231 | size_t GetCount() const { return m_count; } | |
232 | ||
233 | private: | |
234 | size_t m_count; // number of elements in the hashtable | |
235 | bool m_deleteContents; | |
236 | ||
237 | DECLARE_DYNAMIC_CLASS(wxHashTable) | |
238 | }; | |
239 | ||
240 | // defines a new type safe hash table which stores the elements of type eltype | |
241 | // in lists of class listclass | |
f6bcfd97 BP |
242 | #define _WX_DECLARE_HASH(eltype, listclass, hashclass, classexp) \ |
243 | classexp hashclass : public wxHashTableBase \ | |
bcaa23de VZ |
244 | { \ |
245 | public: \ | |
246 | hashclass(wxKeyType keyType = wxKEY_INTEGER, \ | |
247 | size_t size = wxHASH_SIZE_DEFAULT) \ | |
248 | { Create(keyType, size); } \ | |
249 | \ | |
250 | ~hashclass() { Destroy(); } \ | |
251 | \ | |
252 | void Put(long key, long val, eltype *data) { DoPut(key, val, data); } \ | |
253 | void Put(long key, eltype *data) { DoPut(key, key, data); } \ | |
254 | \ | |
255 | eltype *Get(long key, long value) const \ | |
256 | { \ | |
257 | wxNodeBase *node = GetNode(key, value); \ | |
258 | return node ? ((listclass::Node *)node)->GetData() : (eltype *)0; \ | |
259 | } \ | |
260 | eltype *Get(long key) const { return Get(key, key); } \ | |
261 | \ | |
262 | eltype *Delete(long key, long value) \ | |
263 | { \ | |
264 | eltype *data; \ | |
265 | \ | |
266 | wxNodeBase *node = GetNode(key, value); \ | |
267 | if ( node ) \ | |
268 | { \ | |
269 | data = ((listclass::Node *)node)->GetData(); \ | |
270 | \ | |
271 | delete node; \ | |
272 | m_count--; \ | |
273 | } \ | |
274 | else \ | |
275 | { \ | |
276 | data = (eltype *)0; \ | |
277 | } \ | |
278 | \ | |
279 | return data; \ | |
280 | } \ | |
281 | eltype *Delete(long key) { return Delete(key, key); } \ | |
282 | \ | |
283 | protected: \ | |
284 | void DoPut(long key, long value, eltype *data) \ | |
285 | { \ | |
6a5391af | 286 | size_t slot = (size_t)abs((int)(key % (long)m_hashSize)); \ |
bcaa23de VZ |
287 | \ |
288 | if ( !m_hashTable[slot] ) \ | |
289 | { \ | |
290 | m_hashTable[slot] = new listclass(m_keyType); \ | |
291 | if ( m_deleteContents ) \ | |
292 | m_hashTable[slot]->DeleteContents(TRUE); \ | |
293 | } \ | |
294 | \ | |
295 | ((listclass *)m_hashTable[slot])->Append(value, data); \ | |
296 | m_count++; \ | |
297 | } \ | |
298 | } | |
299 | ||
f6bcfd97 BP |
300 | // this macro is to be used in the user code |
301 | #define WX_DECLARE_HASH(el, list, hash) \ | |
302 | _WX_DECLARE_HASH(el, list, hash, class) | |
303 | ||
304 | // and this one does exactly the same thing but should be used inside the | |
305 | // library | |
306 | #define WX_DECLARE_EXPORTED_HASH(el, list, hash) \ | |
307 | _WX_DECLARE_HASH(el, list, hash, class WXDLLEXPORT) | |
308 | ||
0b9ab0bd RL |
309 | #define WX_DECLARE_USER_EXPORTED_HASH(el, list, hash, usergoo) \ |
310 | _WX_DECLARE_HASH(el, list, hash, class usergoo) | |
311 | ||
ba8c1601 MB |
312 | // delete all hash elements |
313 | // | |
314 | // NB: the class declaration of the hash elements must be visible from the | |
315 | // place where you use this macro, otherwise the proper destructor may not | |
316 | // be called (a decent compiler should give a warning about it, but don't | |
317 | // count on it)! | |
318 | #define WX_CLEAR_HASH_TABLE(array) \ | |
319 | { \ | |
320 | (array).BeginFind(); \ | |
321 | wxNode* it = (array).Next(); \ | |
322 | while( it ) \ | |
323 | { \ | |
324 | delete it->GetData(); \ | |
325 | it = (array).Next(); \ | |
326 | } \ | |
327 | (array).Clear(); \ | |
328 | } | |
329 | ||
c801d85f | 330 | #endif |
bcaa23de | 331 | // _WX_HASH_H__ |