1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxHashTable class
4 // Author: Julian Smart
5 // Modified by: VZ at 25.02.00: type safe hashes with WX_DECLARE_HASH()
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
15 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
16 #pragma interface "hash.h"
22 #include "wx/object.h"
25 class WXDLLIMPEXP_BASE wxObject
;
27 #if WXWIN_COMPATIBILITY_2_4
28 #include "wx/dynarray.h"
31 // the default size of the hash
32 #define wxHASH_SIZE_DEFAULT (1000)
35 * A hash table is an array of user-definable size with lists
36 * of data items hanging off the array positions. Usually there'll
37 * be a hit, so no search is required; otherwise we'll have to run down
38 * the list to find the desired item.
41 // ----------------------------------------------------------------------------
42 // this is the base class for object hashes: hash tables which contain
43 // pointers to objects
44 // ----------------------------------------------------------------------------
48 class WXDLLIMPEXP_BASE wxHashTableBase
: public wxObject
53 void Create(wxKeyType keyType
= wxKEY_INTEGER
,
54 size_t size
= wxHASH_SIZE_DEFAULT
);
57 size_t GetSize() const { return m_hashSize
; }
58 size_t GetCount() const { return m_count
; }
60 void DeleteContents(bool flag
);
63 // find the node for (key, value)
64 wxNodeBase
*GetNode(long key
, long value
) const;
66 // the array of lists in which we store the values for given key hash
67 wxListBase
**m_hashTable
;
69 // the size of m_lists array
72 // the type of indexing we use
75 // the total number of elements in the hash
78 // should we delete our data?
79 bool m_deleteContents
;
82 // no copy ctor/assignment operator (yet)
83 DECLARE_NO_COPY_CLASS(wxHashTableBase
)
88 #if !defined(wxENUM_KEY_TYPE_DEFINED)
89 #define wxENUM_KEY_TYPE_DEFINED
106 class WXDLLIMPEXP_BASE wxHashTableBase_Node
108 friend class WXDLLIMPEXP_BASE wxHashTableBase
;
109 typedef class WXDLLIMPEXP_BASE wxHashTableBase_Node _Node
;
111 wxHashTableBase_Node( long key
, void* value
,
112 wxHashTableBase
* table
);
113 wxHashTableBase_Node( const wxChar
* key
, void* value
,
114 wxHashTableBase
* table
);
115 ~wxHashTableBase_Node();
117 long GetKeyInteger() const { return m_key
.integer
; }
118 const wxChar
* GetKeyString() const { return m_key
.string
; }
120 void* GetData() const { return m_value
; }
121 void SetData( void* data
) { m_value
= data
; }
124 _Node
* GetNext() const { return m_next
; }
127 // next node in the chain
128 wxHashTableBase_Node
* m_next
;
131 wxHashKeyValue m_key
;
136 // pointer to the hash containing the node, used to remove the
137 // node from the hash when the user deletes the node iterating
139 // TODO: move it to wxHashTable_Node (only wxHashTable supports
141 wxHashTableBase
* m_hashPtr
;
144 class WXDLLIMPEXP_BASE wxHashTableBase
149 friend class WXDLLIMPEXP_BASE wxHashTableBase_Node
;
151 typedef wxHashTableBase_Node Node
;
154 virtual ~wxHashTableBase();
156 void Create( wxKeyType keyType
= wxKEY_INTEGER
,
157 size_t size
= wxHASH_SIZE_DEFAULT
);
161 size_t GetSize() const { return m_size
; }
162 size_t GetCount() const { return m_count
; }
164 void DeleteContents( bool flag
) { m_deleteContents
= flag
; }
166 static long MakeKey(const wxChar
*string
);
169 void DoPut( long key
, long hash
, void* data
);
170 void DoPut( const wxChar
* key
, long hash
, void* data
);
171 void* DoGet( long key
, long hash
) const;
172 void* DoGet( const wxChar
* key
, long hash
) const;
173 void* DoDelete( long key
, long hash
);
174 void* DoDelete( const wxChar
* key
, long hash
);
177 // Remove the node from the hash, *only called from
178 // ~wxHashTable*_Node destructor
179 void DoRemoveNode( wxHashTableBase_Node
* node
);
181 // destroys data contained in the node if appropriate:
182 // deletes the key if it is a string and destrys
183 // the value if m_deleteContents is true
184 void DoDestroyNode( wxHashTableBase_Node
* node
);
186 // inserts a node in the table (at the end of the chain)
187 void DoInsertNode( size_t bucket
, wxHashTableBase_Node
* node
);
189 // removes a node from the table (fiven a pointer to the previous
190 // but does not delete it (only deletes its contents)
191 void DoUnlinkNode( size_t bucket
, wxHashTableBase_Node
* node
,
192 wxHashTableBase_Node
* prev
);
194 // unconditionally deletes node value (invoking the
195 // correct destructor)
196 virtual void DoDeleteContents( wxHashTableBase_Node
* node
) = 0;
202 // number of nodes (key/value pairs)
208 // key typ (INTEGER/STRING)
211 // delete contents when hash is cleared
212 bool m_deleteContents
;
215 DECLARE_NO_COPY_CLASS(wxHashTableBase
)
222 #if WXWIN_COMPATIBILITY_2_4
224 // ----------------------------------------------------------------------------
225 // a hash table which stores longs
226 // ----------------------------------------------------------------------------
228 class WXDLLIMPEXP_BASE wxHashTableLong
: public wxObject
231 wxHashTableLong(size_t size
= wxHASH_SIZE_DEFAULT
)
233 virtual ~wxHashTableLong();
235 void Create(size_t size
= wxHASH_SIZE_DEFAULT
);
238 size_t GetSize() const { return m_hashSize
; }
239 size_t GetCount() const { return m_count
; }
241 void Put(long key
, long value
);
242 long Get(long key
) const;
243 long Delete(long key
);
246 void Init(size_t size
);
249 wxArrayLong
**m_values
,
252 // the size of array above
255 // the total number of elements in the hash
258 // not implemented yet
259 DECLARE_NO_COPY_CLASS(wxHashTableLong
)
262 // ----------------------------------------------------------------------------
263 // wxStringHashTable: a hash table which indexes strings with longs
264 // ----------------------------------------------------------------------------
266 class WXDLLIMPEXP_BASE wxStringHashTable
: public wxObject
269 wxStringHashTable(size_t sizeTable
= wxHASH_SIZE_DEFAULT
);
270 virtual ~wxStringHashTable();
272 // add a string associated with this key to the table
273 void Put(long key
, const wxString
& value
);
275 // get the string from the key: if not found, an empty string is returned
276 // and the wasFound is set to FALSE if not NULL
277 wxString
Get(long key
, bool *wasFound
= NULL
) const;
279 // remove the item, returning TRUE if the item was found and deleted
280 bool Delete(long key
) const;
286 wxArrayLong
**m_keys
;
287 wxArrayString
**m_values
;
289 // the size of array above
292 DECLARE_NO_COPY_CLASS(wxStringHashTable
)
295 #endif // WXWIN_COMPATIBILITY_2_4
299 // ----------------------------------------------------------------------------
300 // for compatibility only
301 // ----------------------------------------------------------------------------
305 class WXDLLIMPEXP_BASE wxHashTable_Node
: public wxHashTableBase_Node
307 friend class WXDLLIMPEXP_BASE wxHashTable
;
309 wxHashTable_Node( long key
, void* value
,
310 wxHashTableBase
* table
)
311 : wxHashTableBase_Node( key
, value
, table
) { }
312 wxHashTable_Node( const wxChar
* key
, void* value
,
313 wxHashTableBase
* table
)
314 : wxHashTableBase_Node( key
, value
, table
) { }
316 wxObject
* GetData() const
317 { return (wxObject
*)wxHashTableBase_Node::GetData(); }
318 void SetData( wxObject
* data
)
319 { wxHashTableBase_Node::SetData( data
); }
321 wxHashTable_Node
* GetNext() const
322 { return (wxHashTable_Node
*)wxHashTableBase_Node::GetNext(); }
325 // should inherit protectedly, but it is public for compatibility in
326 // order to publicly inherit from wxObject
327 class WXDLLIMPEXP_BASE wxHashTable
: public wxHashTableBase
329 typedef wxHashTableBase hash
;
331 typedef wxHashTable_Node Node
;
332 typedef wxHashTable_Node
* compatibility_iterator
;
334 wxHashTable( wxKeyType keyType
= wxKEY_INTEGER
,
335 size_t size
= wxHASH_SIZE_DEFAULT
)
336 : wxHashTableBase() { Create( keyType
, size
); BeginFind(); }
337 wxHashTable( const wxHashTable
& table
);
339 const wxHashTable
& operator=( const wxHashTable
& );
341 void Destroy() { Clear(); }
343 // key and value are the same
344 void Put(long value
, wxObject
*object
)
345 { DoPut( value
, value
, object
); }
346 void Put(long hash
, long value
, wxObject
*object
)
347 { DoPut( value
, hash
, object
); }
348 void Put(const wxChar
*value
, wxObject
*object
)
349 { DoPut( value
, MakeKey( value
), object
); }
350 void Put(long hash
, const wxChar
*value
, wxObject
*object
)
351 { DoPut( value
, hash
, object
); }
353 // key and value are the same
354 wxObject
*Get(long value
) const
355 { return (wxObject
*)DoGet( value
, value
); }
356 wxObject
*Get(long hash
, long value
) const
357 { return (wxObject
*)DoGet( value
, hash
); }
358 wxObject
*Get(const wxChar
*value
) const
359 { return (wxObject
*)DoGet( value
, MakeKey( value
) ); }
360 wxObject
*Get(long hash
, const wxChar
*value
) const
361 { return (wxObject
*)DoGet( value
, hash
); }
363 // Deletes entry and returns data if found
364 wxObject
*Delete(long key
)
365 { return (wxObject
*)DoDelete( key
, key
); }
366 wxObject
*Delete(long hash
, long key
)
367 { return (wxObject
*)DoDelete( key
, hash
); }
368 wxObject
*Delete(const wxChar
*key
)
369 { return (wxObject
*)DoDelete( key
, MakeKey( key
) ); }
370 wxObject
*Delete(long hash
, const wxChar
*key
)
371 { return (wxObject
*)DoDelete( key
, hash
); }
373 // Construct your own integer key from a string, e.g. in case
374 // you need to combine it with something
375 long MakeKey(const wxChar
*string
) const
376 { return wxHashTableBase::MakeKey(string
); }
378 // Way of iterating through whole hash table (e.g. to delete everything)
379 // Not necessary, of course, if you're only storing pointers to
380 // objects maintained separately
381 void BeginFind() { m_curr
= NULL
; m_currBucket
= 0; }
384 void Clear() { wxHashTableBase::Clear(); }
386 size_t GetCount() const { return wxHashTableBase::GetCount(); }
388 virtual void DoDeleteContents( wxHashTableBase_Node
* node
);
391 void DoCopy( const wxHashTable
& copy
);
393 // searches the next node starting from bucket bucketStart and sets
394 // m_curr to it and m_currBucket to its bucket
395 void GetNextNode( size_t bucketStart
);
400 // bucket the current node belongs to
404 #else // if !wxUSE_STL
406 class WXDLLIMPEXP_BASE wxHashTable
: public wxObject
410 typedef wxNode
* compatibility_iterator
;
413 int current_position
;
414 wxNode
*current_node
;
416 unsigned int key_type
;
419 wxHashTable(int the_key_type
= wxKEY_INTEGER
,
420 int size
= wxHASH_SIZE_DEFAULT
);
423 // copy ctor and assignment operator
424 wxHashTable(const wxHashTable
& table
) : wxObject()
426 wxHashTable
& operator=(const wxHashTable
& table
)
427 { Clear(); DoCopy(table
); return *this; }
429 void DoCopy(const wxHashTable
& table
);
433 bool Create(int the_key_type
= wxKEY_INTEGER
,
434 int size
= wxHASH_SIZE_DEFAULT
);
436 // Note that there are 2 forms of Put, Get.
437 // With a key and a value, the *value* will be checked
438 // when a collision is detected. Otherwise, if there are
439 // 2 items with a different value but the same key,
440 // we'll retrieve the WRONG ONE. So where possible,
441 // supply the required value along with the key.
442 // In fact, the value-only versions make a key, and still store
443 // the value. The use of an explicit key might be required
444 // e.g. when combining several values into one key.
445 // When doing that, it's highly likely we'll get a collision,
446 // e.g. 1 + 2 = 3, 2 + 1 = 3.
448 // key and value are NOT necessarily the same
449 void Put(long key
, long value
, wxObject
*object
);
450 void Put(long key
, const wxChar
*value
, wxObject
*object
);
452 // key and value are the same
453 void Put(long value
, wxObject
*object
);
454 void Put(const wxChar
*value
, wxObject
*object
);
456 // key and value not the same
457 wxObject
*Get(long key
, long value
) const;
458 wxObject
*Get(long key
, const wxChar
*value
) const;
460 // key and value are the same
461 wxObject
*Get(long value
) const;
462 wxObject
*Get(const wxChar
*value
) const;
464 // Deletes entry and returns data if found
465 wxObject
*Delete(long key
);
466 wxObject
*Delete(const wxChar
*key
);
468 wxObject
*Delete(long key
, int value
);
469 wxObject
*Delete(long key
, const wxChar
*value
);
471 // Construct your own integer key from a string, e.g. in case
472 // you need to combine it with something
473 long MakeKey(const wxChar
*string
) const;
475 // Way of iterating through whole hash table (e.g. to delete everything)
476 // Not necessary, of course, if you're only storing pointers to
477 // objects maintained separately
482 void DeleteContents(bool flag
);
485 // Returns number of nodes
486 size_t GetCount() const { return m_count
; }
489 size_t m_count
; // number of elements in the hashtable
490 bool m_deleteContents
;
492 DECLARE_DYNAMIC_CLASS(wxHashTable
)
499 // defines a new type safe hash table which stores the elements of type eltype
500 // in lists of class listclass
501 #define _WX_DECLARE_HASH(eltype, dummy, hashclass, classexp) \
502 classexp hashclass : public wxHashTableBase \
505 hashclass(wxKeyType keyType = wxKEY_INTEGER, \
506 size_t size = wxHASH_SIZE_DEFAULT) \
507 : wxHashTableBase() { Create(keyType, size); } \
509 ~hashclass() { Destroy(); } \
511 void Destroy() { Clear(); } \
512 void Put(long key, eltype *data) { DoPut(key, key, (void*)data); } \
513 void Put(long hash, long key, eltype *data) \
514 { DoPut(key, hash, (void*)data); } \
515 eltype *Get(long key) const { return (eltype*)DoGet(key, key); } \
516 eltype *Get(long hash, long key) const \
517 { return (eltype*)DoGet(key, hash); } \
518 eltype *Delete(long key) { return (eltype*)DoDelete(key, key); } \
519 eltype *Delete(long hash, long key) \
520 { return (eltype*)DoDelete(key, hash); } \
522 virtual void DoDeleteContents( wxHashTableBase_Node* node ) \
523 { delete (eltype*)node->GetData(); } \
525 DECLARE_NO_COPY_CLASS(hashclass) \
528 #else // if !wxUSE_STL
530 #define _WX_DECLARE_HASH(eltype, listclass, hashclass, classexp) \
531 classexp hashclass : public wxHashTableBase \
534 hashclass(wxKeyType keyType = wxKEY_INTEGER, \
535 size_t size = wxHASH_SIZE_DEFAULT) \
536 { Create(keyType, size); } \
538 ~hashclass() { Destroy(); } \
540 void Put(long key, long val, eltype *data) { DoPut(key, val, data); } \
541 void Put(long key, eltype *data) { DoPut(key, key, data); } \
543 eltype *Get(long key, long value) const \
545 wxNodeBase *node = GetNode(key, value); \
546 return node ? ((listclass::Node *)node)->GetData() : (eltype *)0; \
548 eltype *Get(long key) const { return Get(key, key); } \
550 eltype *Delete(long key, long value) \
554 wxNodeBase *node = GetNode(key, value); \
557 data = ((listclass::Node *)node)->GetData(); \
564 data = (eltype *)0; \
569 eltype *Delete(long key) { return Delete(key, key); } \
572 void DoPut(long key, long value, eltype *data) \
574 size_t slot = (size_t)abs((int)(key % (long)m_hashSize)); \
576 if ( !m_hashTable[slot] ) \
578 m_hashTable[slot] = new listclass(m_keyType); \
579 if ( m_deleteContents ) \
580 m_hashTable[slot]->DeleteContents(TRUE); \
583 ((listclass *)m_hashTable[slot])->Append(value, data); \
587 DECLARE_NO_COPY_CLASS(hashclass) \
592 // this macro is to be used in the user code
593 #define WX_DECLARE_HASH(el, list, hash) \
594 _WX_DECLARE_HASH(el, list, hash, class)
596 // and this one does exactly the same thing but should be used inside the
598 #define WX_DECLARE_EXPORTED_HASH(el, list, hash) \
599 _WX_DECLARE_HASH(el, list, hash, class WXDLLEXPORT)
601 #define WX_DECLARE_USER_EXPORTED_HASH(el, list, hash, usergoo) \
602 _WX_DECLARE_HASH(el, list, hash, class usergoo)
604 // delete all hash elements
606 // NB: the class declaration of the hash elements must be visible from the
607 // place where you use this macro, otherwise the proper destructor may not
608 // be called (a decent compiler should give a warning about it, but don't
610 #define WX_CLEAR_HASH_TABLE(hash) \
612 (hash).BeginFind(); \
613 wxHashTable::compatibility_iterator it = (hash).Next(); \
616 delete it->GetData(); \
617 it = (hash).Next(); \