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