]> git.saurik.com Git - wxWidgets.git/blame_incremental - include/wx/hash.h
MSVC 5 fix.
[wxWidgets.git] / include / wx / hash.h
... / ...
CommitLineData
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// RCS-ID: $Id$
8// Copyright: (c)
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifndef _WX_HASH_H__
13#define _WX_HASH_H__
14
15#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
16#pragma interface "hash.h"
17#endif
18
19#include "wx/defs.h"
20
21#if !wxUSE_STL
22 #include "wx/object.h"
23 #include "wx/list.h"
24#else
25 class WXDLLIMPEXP_BASE wxObject;
26#endif
27#if WXWIN_COMPATIBILITY_2_4
28 #include "wx/dynarray.h"
29#endif
30
31// the default size of the hash
32#define wxHASH_SIZE_DEFAULT (1000)
33
34/*
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.
39*/
40
41// ----------------------------------------------------------------------------
42// this is the base class for object hashes: hash tables which contain
43// pointers to objects
44// ----------------------------------------------------------------------------
45
46#if !wxUSE_STL
47
48class WXDLLIMPEXP_BASE wxHashTableBase : public wxObject
49{
50public:
51 wxHashTableBase();
52
53 void Create(wxKeyType keyType = wxKEY_INTEGER,
54 size_t size = wxHASH_SIZE_DEFAULT);
55 void Destroy();
56
57 size_t GetSize() const { return m_hashSize; }
58 size_t GetCount() const { return m_count; }
59
60 void DeleteContents(bool flag);
61
62protected:
63 // find the node for (key, value)
64 wxNodeBase *GetNode(long key, long value) const;
65
66 // the array of lists in which we store the values for given key hash
67 wxListBase **m_hashTable;
68
69 // the size of m_lists array
70 size_t m_hashSize;
71
72 // the type of indexing we use
73 wxKeyType m_keyType;
74
75 // the total number of elements in the hash
76 size_t m_count;
77
78 // should we delete our data?
79 bool m_deleteContents;
80
81private:
82 // no copy ctor/assignment operator (yet)
83 DECLARE_NO_COPY_CLASS(wxHashTableBase)
84};
85
86#else // if wxUSE_STL
87
88#if !defined(wxENUM_KEY_TYPE_DEFINED)
89#define wxENUM_KEY_TYPE_DEFINED
90
91enum wxKeyType
92{
93 wxKEY_NONE,
94 wxKEY_INTEGER,
95 wxKEY_STRING
96};
97
98#endif
99
100union wxHashKeyValue
101{
102 long integer;
103 wxChar *string;
104};
105
106class WXDLLIMPEXP_BASE wxHashTableBase_Node
107{
108 friend class WXDLLIMPEXP_BASE wxHashTableBase;
109 typedef class WXDLLIMPEXP_BASE wxHashTableBase_Node _Node;
110public:
111 wxHashTableBase_Node( long key, void* value,
112 wxHashTableBase* table );
113 wxHashTableBase_Node( const wxChar* key, void* value,
114 wxHashTableBase* table );
115 ~wxHashTableBase_Node();
116
117 long GetKeyInteger() const { return m_key.integer; }
118 const wxChar* GetKeyString() const { return m_key.string; }
119
120 void* GetData() const { return m_value; }
121 void SetData( void* data ) { m_value = data; }
122
123protected:
124 _Node* GetNext() const { return m_next; }
125
126protected:
127 // next node in the chain
128 wxHashTableBase_Node* m_next;
129
130 // key
131 wxHashKeyValue m_key;
132
133 // value
134 void* m_value;
135
136 // pointer to the hash containing the node, used to remove the
137 // node from the hash when the user deletes the node iterating
138 // through it
139 // TODO: move it to wxHashTable_Node (only wxHashTable supports
140 // iteration)
141 wxHashTableBase* m_hashPtr;
142};
143
144class WXDLLIMPEXP_BASE wxHashTableBase
145#if !wxUSE_STL
146 : public wxObject
147#endif
148{
149 friend class WXDLLIMPEXP_BASE wxHashTableBase_Node;
150public:
151 typedef wxHashTableBase_Node Node;
152
153 wxHashTableBase();
154 virtual ~wxHashTableBase();
155
156 void Create( wxKeyType keyType = wxKEY_INTEGER,
157 size_t size = wxHASH_SIZE_DEFAULT );
158 void Clear();
159 void Destroy();
160
161 size_t GetSize() const { return m_size; }
162 size_t GetCount() const { return m_count; }
163
164 void DeleteContents( bool flag ) { m_deleteContents = flag; }
165
166 static long MakeKey(const wxChar *string);
167
168protected:
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 );
175
176private:
177 // Remove the node from the hash, *only called from
178 // ~wxHashTable*_Node destructor
179 void DoRemoveNode( wxHashTableBase_Node* node );
180
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 );
185
186 // inserts a node in the table (at the end of the chain)
187 void DoInsertNode( size_t bucket, wxHashTableBase_Node* node );
188
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 );
193
194 // unconditionally deletes node value (invoking the
195 // correct destructor)
196 virtual void DoDeleteContents( wxHashTableBase_Node* node ) = 0;
197
198protected:
199 // number of buckets
200 size_t m_size;
201
202 // number of nodes (key/value pairs)
203 size_t m_count;
204
205 // table
206 Node** m_table;
207
208 // key typ (INTEGER/STRING)
209 wxKeyType m_keyType;
210
211 // delete contents when hash is cleared
212 bool m_deleteContents;
213
214private:
215 DECLARE_NO_COPY_CLASS(wxHashTableBase)
216};
217
218#endif // !wxUSE_STL
219
220#if !wxUSE_STL
221
222#if WXWIN_COMPATIBILITY_2_4
223
224// ----------------------------------------------------------------------------
225// a hash table which stores longs
226// ----------------------------------------------------------------------------
227
228class WXDLLIMPEXP_BASE wxHashTableLong : public wxObject
229{
230public:
231 wxHashTableLong(size_t size = wxHASH_SIZE_DEFAULT)
232 { Init(size); }
233 virtual ~wxHashTableLong();
234
235 void Create(size_t size = wxHASH_SIZE_DEFAULT);
236 void Destroy();
237
238 size_t GetSize() const { return m_hashSize; }
239 size_t GetCount() const { return m_count; }
240
241 void Put(long key, long value);
242 long Get(long key) const;
243 long Delete(long key);
244
245protected:
246 void Init(size_t size);
247
248private:
249 wxArrayLong **m_values,
250 **m_keys;
251
252 // the size of array above
253 size_t m_hashSize;
254
255 // the total number of elements in the hash
256 size_t m_count;
257
258 // not implemented yet
259 DECLARE_NO_COPY_CLASS(wxHashTableLong)
260};
261
262// ----------------------------------------------------------------------------
263// wxStringHashTable: a hash table which indexes strings with longs
264// ----------------------------------------------------------------------------
265
266class WXDLLIMPEXP_BASE wxStringHashTable : public wxObject
267{
268public:
269 wxStringHashTable(size_t sizeTable = wxHASH_SIZE_DEFAULT);
270 virtual ~wxStringHashTable();
271
272 // add a string associated with this key to the table
273 void Put(long key, const wxString& value);
274
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;
278
279 // remove the item, returning TRUE if the item was found and deleted
280 bool Delete(long key) const;
281
282 // clean up
283 void Destroy();
284
285private:
286 wxArrayLong **m_keys;
287 wxArrayString **m_values;
288
289 // the size of array above
290 size_t m_hashSize;
291
292 DECLARE_NO_COPY_CLASS(wxStringHashTable)
293};
294
295#endif // WXWIN_COMPATIBILITY_2_4
296
297#endif // !wxUSE_STL
298
299// ----------------------------------------------------------------------------
300// for compatibility only
301// ----------------------------------------------------------------------------
302
303#if wxUSE_STL
304
305class WXDLLIMPEXP_BASE wxHashTable_Node : public wxHashTableBase_Node
306{
307 friend class WXDLLIMPEXP_BASE wxHashTable;
308public:
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 ) { }
315
316 wxObject* GetData() const
317 { return (wxObject*)wxHashTableBase_Node::GetData(); }
318 void SetData( wxObject* data )
319 { wxHashTableBase_Node::SetData( data ); }
320
321 wxHashTable_Node* GetNext() const
322 { return (wxHashTable_Node*)wxHashTableBase_Node::GetNext(); }
323};
324
325// should inherit protectedly, but it is public for compatibility in
326// order to publicly inherit from wxObject
327class WXDLLIMPEXP_BASE wxHashTable : public wxHashTableBase
328{
329 typedef wxHashTableBase hash;
330public:
331 typedef wxHashTable_Node Node;
332 typedef wxHashTable_Node* compatibility_iterator;
333public:
334 wxHashTable( wxKeyType keyType = wxKEY_INTEGER,
335 size_t size = wxHASH_SIZE_DEFAULT )
336 : wxHashTableBase() { Create( keyType, size ); BeginFind(); }
337 wxHashTable( const wxHashTable& table );
338
339 const wxHashTable& operator=( const wxHashTable& );
340
341 void Destroy() { Clear(); }
342
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 ); }
352
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 ); }
362
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 ); }
372
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); }
377
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; }
382 Node* Next();
383
384 void Clear() { wxHashTableBase::Clear(); }
385
386 size_t GetCount() const { return wxHashTableBase::GetCount(); }
387protected:
388 virtual void DoDeleteContents( wxHashTableBase_Node* node );
389
390 // copy helper
391 void DoCopy( const wxHashTable& copy );
392
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 );
396private:
397 // current node
398 Node* m_curr;
399
400 // bucket the current node belongs to
401 size_t m_currBucket;
402};
403
404#else // if !wxUSE_STL
405
406class WXDLLIMPEXP_BASE wxHashTable : public wxObject
407{
408public:
409 typedef wxNode Node;
410 typedef wxNode* compatibility_iterator;
411
412 int n;
413 int current_position;
414 wxNode *current_node;
415
416 unsigned int key_type;
417 wxList **hash_table;
418
419 wxHashTable(int the_key_type = wxKEY_INTEGER,
420 int size = wxHASH_SIZE_DEFAULT);
421 ~wxHashTable();
422
423 // copy ctor and assignment operator
424 wxHashTable(const wxHashTable& table) : wxObject()
425 { DoCopy(table); }
426 wxHashTable& operator=(const wxHashTable& table)
427 { Clear(); DoCopy(table); return *this; }
428
429 void DoCopy(const wxHashTable& table);
430
431 void Destroy();
432
433 bool Create(int the_key_type = wxKEY_INTEGER,
434 int size = wxHASH_SIZE_DEFAULT);
435
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.
447
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);
451
452 // key and value are the same
453 void Put(long value, wxObject *object);
454 void Put(const wxChar *value, wxObject *object);
455
456 // key and value not the same
457 wxObject *Get(long key, long value) const;
458 wxObject *Get(long key, const wxChar *value) const;
459
460 // key and value are the same
461 wxObject *Get(long value) const;
462 wxObject *Get(const wxChar *value) const;
463
464 // Deletes entry and returns data if found
465 wxObject *Delete(long key);
466 wxObject *Delete(const wxChar *key);
467
468 wxObject *Delete(long key, int value);
469 wxObject *Delete(long key, const wxChar *value);
470
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;
474
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
478
479 void BeginFind();
480 Node* Next();
481
482 void DeleteContents(bool flag);
483 void Clear();
484
485 // Returns number of nodes
486 size_t GetCount() const { return m_count; }
487
488private:
489 size_t m_count; // number of elements in the hashtable
490 bool m_deleteContents;
491
492 DECLARE_DYNAMIC_CLASS(wxHashTable)
493};
494
495#endif
496
497#if wxUSE_STL
498
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 \
503 { \
504 public: \
505 hashclass(wxKeyType keyType = wxKEY_INTEGER, \
506 size_t size = wxHASH_SIZE_DEFAULT) \
507 : wxHashTableBase() { Create(keyType, size); } \
508 \
509 ~hashclass() { Destroy(); } \
510 \
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); } \
521 protected: \
522 virtual void DoDeleteContents( wxHashTableBase_Node* node ) \
523 { delete (eltype*)node->GetData(); } \
524 \
525 DECLARE_NO_COPY_CLASS(hashclass) \
526 }
527
528#else // if !wxUSE_STL
529
530#define _WX_DECLARE_HASH(eltype, listclass, hashclass, classexp) \
531 classexp hashclass : public wxHashTableBase \
532 { \
533 public: \
534 hashclass(wxKeyType keyType = wxKEY_INTEGER, \
535 size_t size = wxHASH_SIZE_DEFAULT) \
536 { Create(keyType, size); } \
537 \
538 ~hashclass() { Destroy(); } \
539 \
540 void Put(long key, long val, eltype *data) { DoPut(key, val, data); } \
541 void Put(long key, eltype *data) { DoPut(key, key, data); } \
542 \
543 eltype *Get(long key, long value) const \
544 { \
545 wxNodeBase *node = GetNode(key, value); \
546 return node ? ((listclass::Node *)node)->GetData() : (eltype *)0; \
547 } \
548 eltype *Get(long key) const { return Get(key, key); } \
549 \
550 eltype *Delete(long key, long value) \
551 { \
552 eltype *data; \
553 \
554 wxNodeBase *node = GetNode(key, value); \
555 if ( node ) \
556 { \
557 data = ((listclass::Node *)node)->GetData(); \
558 \
559 delete node; \
560 m_count--; \
561 } \
562 else \
563 { \
564 data = (eltype *)0; \
565 } \
566 \
567 return data; \
568 } \
569 eltype *Delete(long key) { return Delete(key, key); } \
570 \
571 protected: \
572 void DoPut(long key, long value, eltype *data) \
573 { \
574 size_t slot = (size_t)abs((int)(key % (long)m_hashSize)); \
575 \
576 if ( !m_hashTable[slot] ) \
577 { \
578 m_hashTable[slot] = new listclass(m_keyType); \
579 if ( m_deleteContents ) \
580 m_hashTable[slot]->DeleteContents(TRUE); \
581 } \
582 \
583 ((listclass *)m_hashTable[slot])->Append(value, data); \
584 m_count++; \
585 } \
586 \
587 DECLARE_NO_COPY_CLASS(hashclass) \
588 }
589
590#endif
591
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)
595
596// and this one does exactly the same thing but should be used inside the
597// library
598#define WX_DECLARE_EXPORTED_HASH(el, list, hash) \
599 _WX_DECLARE_HASH(el, list, hash, class WXDLLEXPORT)
600
601#define WX_DECLARE_USER_EXPORTED_HASH(el, list, hash, usergoo) \
602 _WX_DECLARE_HASH(el, list, hash, class usergoo)
603
604// delete all hash elements
605//
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
609// count on it)!
610#define WX_CLEAR_HASH_TABLE(hash) \
611 { \
612 (hash).BeginFind(); \
613 wxHashTable::compatibility_iterator it = (hash).Next(); \
614 while( it ) \
615 { \
616 delete it->GetData(); \
617 it = (hash).Next(); \
618 } \
619 (hash).Clear(); \
620 }
621
622#endif
623 // _WX_HASH_H__