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"
21 #if !wxUSE_STL && WXWIN_COMPATIBILITY_2_4
22 #define wxUSE_OLD_HASH_TABLE 1
24 #define wxUSE_OLD_HASH_TABLE 0
28 #include "wx/object.h"
30 class WXDLLIMPEXP_BASE wxObject
;
32 #if wxUSE_OLD_HASH_TABLE
35 #if WXWIN_COMPATIBILITY_2_4
36 #include "wx/dynarray.h"
39 // the default size of the hash
40 #define wxHASH_SIZE_DEFAULT (1000)
43 * A hash table is an array of user-definable size with lists
44 * of data items hanging off the array positions. Usually there'll
45 * be a hit, so no search is required; otherwise we'll have to run down
46 * the list to find the desired item.
49 // ----------------------------------------------------------------------------
50 // this is the base class for object hashes: hash tables which contain
51 // pointers to objects
52 // ----------------------------------------------------------------------------
54 #if wxUSE_OLD_HASH_TABLE
56 class WXDLLIMPEXP_BASE wxHashTableBase
: public wxObject
61 void Create(wxKeyType keyType
= wxKEY_INTEGER
,
62 size_t size
= wxHASH_SIZE_DEFAULT
);
65 size_t GetSize() const { return m_hashSize
; }
66 size_t GetCount() const { return m_count
; }
68 void DeleteContents(bool flag
);
71 // find the node for (key, value)
72 wxNodeBase
*GetNode(long key
, long value
) const;
74 // the array of lists in which we store the values for given key hash
75 wxListBase
**m_hashTable
;
77 // the size of m_lists array
80 // the type of indexing we use
83 // the total number of elements in the hash
86 // should we delete our data?
87 bool m_deleteContents
;
90 // no copy ctor/assignment operator (yet)
91 DECLARE_NO_COPY_CLASS(wxHashTableBase
)
94 #else // if !wxUSE_OLD_HASH_TABLE
96 #if !defined(wxENUM_KEY_TYPE_DEFINED)
97 #define wxENUM_KEY_TYPE_DEFINED
114 // for some compilers (AIX xlC), defining it as friend inside the class is not
115 // enough, so provide a real forward declaration
116 class WXDLLIMPEXP_BASE wxHashTableBase
;
118 class WXDLLIMPEXP_BASE wxHashTableBase_Node
120 friend class WXDLLIMPEXP_BASE wxHashTableBase
;
121 typedef class WXDLLIMPEXP_BASE wxHashTableBase_Node _Node
;
123 wxHashTableBase_Node( long key
, void* value
,
124 wxHashTableBase
* table
);
125 wxHashTableBase_Node( const wxChar
* key
, void* value
,
126 wxHashTableBase
* table
);
127 ~wxHashTableBase_Node();
129 long GetKeyInteger() const { return m_key
.integer
; }
130 const wxChar
* GetKeyString() const { return m_key
.string
; }
132 void* GetData() const { return m_value
; }
133 void SetData( void* data
) { m_value
= data
; }
136 _Node
* GetNext() const { return m_next
; }
139 // next node in the chain
140 wxHashTableBase_Node
* m_next
;
143 wxHashKeyValue m_key
;
148 // pointer to the hash containing the node, used to remove the
149 // node from the hash when the user deletes the node iterating
151 // TODO: move it to wxHashTable_Node (only wxHashTable supports
153 wxHashTableBase
* m_hashPtr
;
156 class WXDLLIMPEXP_BASE wxHashTableBase
161 friend class WXDLLIMPEXP_BASE wxHashTableBase_Node
;
163 typedef wxHashTableBase_Node Node
;
166 virtual ~wxHashTableBase() { };
168 void Create( wxKeyType keyType
= wxKEY_INTEGER
,
169 size_t size
= wxHASH_SIZE_DEFAULT
);
173 size_t GetSize() const { return m_size
; }
174 size_t GetCount() const { return m_count
; }
176 void DeleteContents( bool flag
) { m_deleteContents
= flag
; }
178 static long MakeKey(const wxChar
*string
);
181 void DoPut( long key
, long hash
, void* data
);
182 void DoPut( const wxChar
* key
, long hash
, void* data
);
183 void* DoGet( long key
, long hash
) const;
184 void* DoGet( const wxChar
* key
, long hash
) const;
185 void* DoDelete( long key
, long hash
);
186 void* DoDelete( const wxChar
* key
, long hash
);
189 // Remove the node from the hash, *only called from
190 // ~wxHashTable*_Node destructor
191 void DoRemoveNode( wxHashTableBase_Node
* node
);
193 // destroys data contained in the node if appropriate:
194 // deletes the key if it is a string and destrys
195 // the value if m_deleteContents is true
196 void DoDestroyNode( wxHashTableBase_Node
* node
);
198 // inserts a node in the table (at the end of the chain)
199 void DoInsertNode( size_t bucket
, wxHashTableBase_Node
* node
);
201 // removes a node from the table (fiven a pointer to the previous
202 // but does not delete it (only deletes its contents)
203 void DoUnlinkNode( size_t bucket
, wxHashTableBase_Node
* node
,
204 wxHashTableBase_Node
* prev
);
206 // unconditionally deletes node value (invoking the
207 // correct destructor)
208 virtual void DoDeleteContents( wxHashTableBase_Node
* node
) = 0;
214 // number of nodes (key/value pairs)
220 // key typ (INTEGER/STRING)
223 // delete contents when hash is cleared
224 bool m_deleteContents
;
227 DECLARE_NO_COPY_CLASS(wxHashTableBase
)
230 #endif // wxUSE_OLD_HASH_TABLE
234 #if WXWIN_COMPATIBILITY_2_4
236 // ----------------------------------------------------------------------------
237 // a hash table which stores longs
238 // ----------------------------------------------------------------------------
240 class WXDLLIMPEXP_BASE wxHashTableLong
: public wxObject
243 wxHashTableLong(size_t size
= wxHASH_SIZE_DEFAULT
)
245 virtual ~wxHashTableLong();
247 void Create(size_t size
= wxHASH_SIZE_DEFAULT
);
250 size_t GetSize() const { return m_hashSize
; }
251 size_t GetCount() const { return m_count
; }
253 void Put(long key
, long value
);
254 long Get(long key
) const;
255 long Delete(long key
);
258 void Init(size_t size
);
261 wxArrayLong
**m_values
,
264 // the size of array above
267 // the total number of elements in the hash
270 // not implemented yet
271 DECLARE_NO_COPY_CLASS(wxHashTableLong
)
274 // ----------------------------------------------------------------------------
275 // wxStringHashTable: a hash table which indexes strings with longs
276 // ----------------------------------------------------------------------------
278 class WXDLLIMPEXP_BASE wxStringHashTable
: public wxObject
281 wxStringHashTable(size_t sizeTable
= wxHASH_SIZE_DEFAULT
);
282 virtual ~wxStringHashTable();
284 // add a string associated with this key to the table
285 void Put(long key
, const wxString
& value
);
287 // get the string from the key: if not found, an empty string is returned
288 // and the wasFound is set to false if not NULL
289 wxString
Get(long key
, bool *wasFound
= NULL
) const;
291 // remove the item, returning true if the item was found and deleted
292 bool Delete(long key
) const;
298 wxArrayLong
**m_keys
;
299 wxArrayString
**m_values
;
301 // the size of array above
304 DECLARE_NO_COPY_CLASS(wxStringHashTable
)
307 #endif // WXWIN_COMPATIBILITY_2_4
311 // ----------------------------------------------------------------------------
312 // for compatibility only
313 // ----------------------------------------------------------------------------
315 #if !wxUSE_OLD_HASH_TABLE
317 class WXDLLIMPEXP_BASE wxHashTable_Node
: public wxHashTableBase_Node
319 friend class WXDLLIMPEXP_BASE wxHashTable
;
321 wxHashTable_Node( long key
, void* value
,
322 wxHashTableBase
* table
)
323 : wxHashTableBase_Node( key
, value
, table
) { }
324 wxHashTable_Node( const wxChar
* key
, void* value
,
325 wxHashTableBase
* table
)
326 : wxHashTableBase_Node( key
, value
, table
) { }
328 wxObject
* GetData() const
329 { return (wxObject
*)wxHashTableBase_Node::GetData(); }
330 void SetData( wxObject
* data
)
331 { wxHashTableBase_Node::SetData( data
); }
333 wxHashTable_Node
* GetNext() const
334 { return (wxHashTable_Node
*)wxHashTableBase_Node::GetNext(); }
337 // should inherit protectedly, but it is public for compatibility in
338 // order to publicly inherit from wxObject
339 class WXDLLIMPEXP_BASE wxHashTable
: public wxHashTableBase
341 typedef wxHashTableBase hash
;
343 typedef wxHashTable_Node Node
;
344 typedef wxHashTable_Node
* compatibility_iterator
;
346 wxHashTable( wxKeyType keyType
= wxKEY_INTEGER
,
347 size_t size
= wxHASH_SIZE_DEFAULT
)
348 : wxHashTableBase() { Create( keyType
, size
); BeginFind(); }
349 wxHashTable( const wxHashTable
& table
);
351 virtual ~wxHashTable() { Destroy(); }
353 const wxHashTable
& operator=( const wxHashTable
& );
355 // key and value are the same
356 void Put(long value
, wxObject
*object
)
357 { DoPut( value
, value
, object
); }
358 void Put(long hash
, long value
, wxObject
*object
)
359 { DoPut( value
, hash
, object
); }
360 void Put(const wxChar
*value
, wxObject
*object
)
361 { DoPut( value
, MakeKey( value
), object
); }
362 void Put(long hash
, const wxChar
*value
, wxObject
*object
)
363 { DoPut( value
, hash
, object
); }
365 // key and value are the same
366 wxObject
*Get(long value
) const
367 { return (wxObject
*)DoGet( value
, value
); }
368 wxObject
*Get(long hash
, long value
) const
369 { return (wxObject
*)DoGet( value
, hash
); }
370 wxObject
*Get(const wxChar
*value
) const
371 { return (wxObject
*)DoGet( value
, MakeKey( value
) ); }
372 wxObject
*Get(long hash
, const wxChar
*value
) const
373 { return (wxObject
*)DoGet( value
, hash
); }
375 // Deletes entry and returns data if found
376 wxObject
*Delete(long key
)
377 { return (wxObject
*)DoDelete( key
, key
); }
378 wxObject
*Delete(long hash
, long key
)
379 { return (wxObject
*)DoDelete( key
, hash
); }
380 wxObject
*Delete(const wxChar
*key
)
381 { return (wxObject
*)DoDelete( key
, MakeKey( key
) ); }
382 wxObject
*Delete(long hash
, const wxChar
*key
)
383 { return (wxObject
*)DoDelete( key
, hash
); }
385 // Construct your own integer key from a string, e.g. in case
386 // you need to combine it with something
387 long MakeKey(const wxChar
*string
) const
388 { return wxHashTableBase::MakeKey(string
); }
390 // Way of iterating through whole hash table (e.g. to delete everything)
391 // Not necessary, of course, if you're only storing pointers to
392 // objects maintained separately
393 void BeginFind() { m_curr
= NULL
; m_currBucket
= 0; }
396 void Clear() { wxHashTableBase::Clear(); }
398 size_t GetCount() const { return wxHashTableBase::GetCount(); }
400 virtual void DoDeleteContents( wxHashTableBase_Node
* node
);
403 void DoCopy( const wxHashTable
& copy
);
405 // searches the next node starting from bucket bucketStart and sets
406 // m_curr to it and m_currBucket to its bucket
407 void GetNextNode( size_t bucketStart
);
412 // bucket the current node belongs to
416 #else // if wxUSE_OLD_HASH_TABLE
418 class WXDLLIMPEXP_BASE wxHashTable
: public wxObject
422 typedef wxNode
* compatibility_iterator
;
425 int current_position
;
426 wxNode
*current_node
;
428 unsigned int key_type
;
431 wxHashTable(int the_key_type
= wxKEY_INTEGER
,
432 int size
= wxHASH_SIZE_DEFAULT
);
435 // copy ctor and assignment operator
436 wxHashTable(const wxHashTable
& table
) : wxObject()
438 wxHashTable
& operator=(const wxHashTable
& table
)
439 { Clear(); DoCopy(table
); return *this; }
441 void DoCopy(const wxHashTable
& table
);
445 bool Create(int the_key_type
= wxKEY_INTEGER
,
446 int size
= wxHASH_SIZE_DEFAULT
);
448 // Note that there are 2 forms of Put, Get.
449 // With a key and a value, the *value* will be checked
450 // when a collision is detected. Otherwise, if there are
451 // 2 items with a different value but the same key,
452 // we'll retrieve the WRONG ONE. So where possible,
453 // supply the required value along with the key.
454 // In fact, the value-only versions make a key, and still store
455 // the value. The use of an explicit key might be required
456 // e.g. when combining several values into one key.
457 // When doing that, it's highly likely we'll get a collision,
458 // e.g. 1 + 2 = 3, 2 + 1 = 3.
460 // key and value are NOT necessarily the same
461 void Put(long key
, long value
, wxObject
*object
);
462 void Put(long key
, const wxChar
*value
, wxObject
*object
);
464 // key and value are the same
465 void Put(long value
, wxObject
*object
);
466 void Put(const wxChar
*value
, wxObject
*object
);
468 // key and value not the same
469 wxObject
*Get(long key
, long value
) const;
470 wxObject
*Get(long key
, const wxChar
*value
) const;
472 // key and value are the same
473 wxObject
*Get(long value
) const;
474 wxObject
*Get(const wxChar
*value
) const;
476 // Deletes entry and returns data if found
477 wxObject
*Delete(long key
);
478 wxObject
*Delete(const wxChar
*key
);
480 wxObject
*Delete(long key
, int value
);
481 wxObject
*Delete(long key
, const wxChar
*value
);
483 // Construct your own integer key from a string, e.g. in case
484 // you need to combine it with something
485 long MakeKey(const wxChar
*string
) const;
487 // Way of iterating through whole hash table (e.g. to delete everything)
488 // Not necessary, of course, if you're only storing pointers to
489 // objects maintained separately
494 void DeleteContents(bool flag
);
497 // Returns number of nodes
498 size_t GetCount() const { return m_count
; }
501 size_t m_count
; // number of elements in the hashtable
502 bool m_deleteContents
;
504 DECLARE_DYNAMIC_CLASS(wxHashTable
)
507 #endif // wxUSE_OLD_HASH_TABLE
509 #if !wxUSE_OLD_HASH_TABLE
511 // defines a new type safe hash table which stores the elements of type eltype
512 // in lists of class listclass
513 #define _WX_DECLARE_HASH(eltype, dummy, hashclass, classexp) \
514 classexp hashclass : public wxHashTableBase \
517 hashclass(wxKeyType keyType = wxKEY_INTEGER, \
518 size_t size = wxHASH_SIZE_DEFAULT) \
519 : wxHashTableBase() { Create(keyType, size); } \
521 virtual ~hashclass() { Destroy(); } \
523 void Put(long key, eltype *data) { DoPut(key, key, (void*)data); } \
524 void Put(long hash, long key, eltype *data) \
525 { DoPut(key, hash, (void*)data); } \
526 eltype *Get(long key) const { return (eltype*)DoGet(key, key); } \
527 eltype *Get(long hash, long key) const \
528 { return (eltype*)DoGet(key, hash); } \
529 eltype *Delete(long key) { return (eltype*)DoDelete(key, key); } \
530 eltype *Delete(long hash, long key) \
531 { return (eltype*)DoDelete(key, hash); } \
533 virtual void DoDeleteContents( wxHashTableBase_Node* node ) \
534 { delete (eltype*)node->GetData(); } \
536 DECLARE_NO_COPY_CLASS(hashclass) \
539 #else // if wxUSE_OLD_HASH_TABLE
541 #define _WX_DECLARE_HASH(eltype, listclass, hashclass, classexp) \
542 classexp hashclass : public wxHashTableBase \
545 hashclass(wxKeyType keyType = wxKEY_INTEGER, \
546 size_t size = wxHASH_SIZE_DEFAULT) \
547 { Create(keyType, size); } \
549 ~hashclass() { Destroy(); } \
551 void Put(long key, long val, eltype *data) { DoPut(key, val, data); } \
552 void Put(long key, eltype *data) { DoPut(key, key, data); } \
554 eltype *Get(long key, long value) const \
556 wxNodeBase *node = GetNode(key, value); \
557 return node ? ((listclass::Node *)node)->GetData() : (eltype *)0; \
559 eltype *Get(long key) const { return Get(key, key); } \
561 eltype *Delete(long key, long value) \
565 wxNodeBase *node = GetNode(key, value); \
568 data = ((listclass::Node *)node)->GetData(); \
575 data = (eltype *)0; \
580 eltype *Delete(long key) { return Delete(key, key); } \
583 void DoPut(long key, long value, eltype *data) \
585 size_t slot = (size_t)abs((int)(key % (long)m_hashSize)); \
587 if ( !m_hashTable[slot] ) \
589 m_hashTable[slot] = new listclass(m_keyType); \
590 if ( m_deleteContents ) \
591 m_hashTable[slot]->DeleteContents(true); \
594 ((listclass *)m_hashTable[slot])->Append(value, data); \
598 DECLARE_NO_COPY_CLASS(hashclass) \
601 #endif // wxUSE_OLD_HASH_TABLE
603 // this macro is to be used in the user code
604 #define WX_DECLARE_HASH(el, list, hash) \
605 _WX_DECLARE_HASH(el, list, hash, class)
607 // and this one does exactly the same thing but should be used inside the
609 #define WX_DECLARE_EXPORTED_HASH(el, list, hash) \
610 _WX_DECLARE_HASH(el, list, hash, class WXDLLEXPORT)
612 #define WX_DECLARE_USER_EXPORTED_HASH(el, list, hash, usergoo) \
613 _WX_DECLARE_HASH(el, list, hash, class usergoo)
615 // delete all hash elements
617 // NB: the class declaration of the hash elements must be visible from the
618 // place where you use this macro, otherwise the proper destructor may not
619 // be called (a decent compiler should give a warning about it, but don't
621 #define WX_CLEAR_HASH_TABLE(hash) \
623 (hash).BeginFind(); \
624 wxHashTable::compatibility_iterator it = (hash).Next(); \
627 delete it->GetData(); \
628 it = (hash).Next(); \