]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/hash.cpp
made wxGetTimeOfDay() public
[wxWidgets.git] / src / common / hash.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/hash.cpp
3// Purpose: wxHashTable implementation
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) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/list.h"
29 #include "wx/hash.h"
30#endif
31
32#if wxUSE_OLD_HASH_TABLE
33
34#include <string.h>
35#include <stdarg.h>
36
37// ----------------------------------------------------------------------------
38// wxWin macros
39// ----------------------------------------------------------------------------
40
41IMPLEMENT_DYNAMIC_CLASS(wxHashTable, wxObject)
42
43// ============================================================================
44// implementation
45// ============================================================================
46
47// ----------------------------------------------------------------------------
48// wxHashTablleBase for working with "void *" data
49// ----------------------------------------------------------------------------
50
51wxHashTableBase::wxHashTableBase()
52{
53 m_deleteContents = false;
54 m_hashTable = (wxListBase **)NULL;
55 m_hashSize = 0;
56 m_count = 0;
57 m_keyType = wxKEY_NONE;
58}
59
60void wxHashTableBase::Create(wxKeyType keyType, size_t size)
61{
62 Destroy();
63
64 m_hashSize = size;
65 m_keyType = keyType;
66 m_hashTable = new wxListBase *[size];
67 for ( size_t n = 0; n < m_hashSize; n++ )
68 {
69 m_hashTable[n] = (wxListBase *) NULL;
70 }
71}
72
73void wxHashTableBase::Destroy()
74{
75 if ( m_hashTable )
76 {
77 for ( size_t n = 0; n < m_hashSize; n++ )
78 {
79 delete m_hashTable[n];
80 }
81
82 delete [] m_hashTable;
83
84 m_hashTable = (wxListBase **)NULL;
85
86 m_count = 0;
87 }
88}
89
90void wxHashTableBase::DeleteContents(bool flag)
91{
92 m_deleteContents = flag;
93 for ( size_t n = 0; n < m_hashSize; n++ )
94 {
95 if ( m_hashTable[n] )
96 {
97 m_hashTable[n]->DeleteContents(flag);
98 }
99 }
100}
101
102wxNodeBase *wxHashTableBase::GetNode(long key, long value) const
103{
104 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
105
106 wxNodeBase *node;
107 if ( m_hashTable[slot] )
108 {
109 node = m_hashTable[slot]->Find(wxListKey(value));
110 }
111 else
112 {
113 node = (wxNodeBase *)NULL;
114 }
115
116 return node;
117}
118
119// ----------------------------------------------------------------------------
120// old not type safe wxHashTable
121// ----------------------------------------------------------------------------
122
123wxHashTable::wxHashTable (int the_key_type, int size)
124{
125 n = 0;
126 hash_table = (wxList**) NULL;
127 Create(the_key_type, size);
128 m_count = 0;
129 m_deleteContents = false;
130/*
131 n = size;
132 current_position = -1;
133 current_node = (wxNode *) NULL;
134
135 key_type = the_key_type;
136 hash_table = new wxList *[size];
137 int i;
138 for (i = 0; i < size; i++)
139 hash_table[i] = (wxList *) NULL;
140*/
141}
142
143wxHashTable::~wxHashTable ()
144{
145 Destroy();
146}
147
148void wxHashTable::Destroy()
149{
150 if (!hash_table) return;
151 int i;
152 for (i = 0; i < n; i++)
153 if (hash_table[i])
154 delete hash_table[i];
155 delete[] hash_table;
156 hash_table = NULL;
157}
158
159bool wxHashTable::Create(int the_key_type, int size)
160{
161 Destroy();
162
163 n = size;
164 current_position = -1;
165 current_node = (wxNode *) NULL;
166
167 key_type = the_key_type;
168 hash_table = new wxList *[size];
169 int i;
170 for (i = 0; i < size; i++)
171 hash_table[i] = (wxList *) NULL;
172 return true;
173}
174
175
176void wxHashTable::DoCopy(const wxHashTable& table)
177{
178 n = table.n;
179 m_count = table.m_count;
180 current_position = table.current_position;
181 current_node = NULL; // doesn't matter - Next() will reconstruct it
182 key_type = table.key_type;
183
184 hash_table = new wxList *[n];
185 for (int i = 0; i < n; i++) {
186 if (table.hash_table[i] == NULL)
187 hash_table[i] = NULL;
188 else {
189 hash_table[i] = new wxList(key_type);
190 *(hash_table[i]) = *(table.hash_table[i]);
191 }
192 }
193}
194
195void wxHashTable::Put (long key, long value, wxObject * object)
196{
197 // Should NEVER be
198 long k = (long) key;
199
200 int position = (int) (k % n);
201 if (position < 0) position = -position;
202
203 if (!hash_table[position])
204 {
205 hash_table[position] = new wxList (wxKEY_INTEGER);
206 if (m_deleteContents) hash_table[position]->DeleteContents(true);
207 }
208
209 hash_table[position]->Append (value, object);
210 m_count++;
211}
212
213void wxHashTable::Put (long key, const wxChar *value, wxObject * object)
214{
215 // Should NEVER be
216 long k = (long) key;
217
218 int position = (int) (k % n);
219 if (position < 0) position = -position;
220
221 if (!hash_table[position])
222 {
223 hash_table[position] = new wxList (wxKEY_STRING);
224 if (m_deleteContents) hash_table[position]->DeleteContents(true);
225 }
226
227 hash_table[position]->Append (value, object);
228 m_count++;
229}
230
231void wxHashTable::Put (long key, wxObject * object)
232{
233 // Should NEVER be
234 long k = (long) key;
235
236 int position = (int) (k % n);
237 if (position < 0) position = -position;
238
239 if (!hash_table[position])
240 {
241 hash_table[position] = new wxList (wxKEY_INTEGER);
242 if (m_deleteContents) hash_table[position]->DeleteContents(true);
243 }
244
245 hash_table[position]->Append (k, object);
246 m_count++;
247}
248
249void wxHashTable::Put (const wxChar *key, wxObject * object)
250{
251 int position = (int) (MakeKey (key) % n);
252 if (position < 0) position = -position;
253
254 if (!hash_table[position])
255 {
256 hash_table[position] = new wxList (wxKEY_STRING);
257 if (m_deleteContents) hash_table[position]->DeleteContents(true);
258 }
259
260 hash_table[position]->Append (key, object);
261 m_count++;
262}
263
264wxObject *wxHashTable::Get (long key, long value) const
265{
266 // Should NEVER be
267 long k = (long) key;
268
269 int position = (int) (k % n);
270 if (position < 0) position = -position;
271
272 if (!hash_table[position])
273 return (wxObject *) NULL;
274 else
275 {
276 wxNode *node = hash_table[position]->Find (value);
277 if (node)
278 return node->GetData ();
279 else
280 return (wxObject *) NULL;
281 }
282}
283
284wxObject *wxHashTable::Get (long key, const wxChar *value) const
285{
286 // Should NEVER be
287 long k = (long) key;
288
289 int position = (int) (k % n);
290 if (position < 0) position = -position;
291
292 if (!hash_table[position])
293 return (wxObject *) NULL;
294 else
295 {
296 wxNode *node = hash_table[position]->Find (value);
297 if (node)
298 return node->GetData ();
299 else
300 return (wxObject *) NULL;
301 }
302}
303
304wxObject *wxHashTable::Get (long key) const
305{
306 // Should NEVER be
307 long k = (long) key;
308
309 int position = (int) (k % n);
310 if (position < 0) position = -position;
311
312 if (!hash_table[position])
313 return (wxObject *) NULL;
314 else
315 {
316 wxNode *node = hash_table[position]->Find (k);
317 return node ? node->GetData () : (wxObject*)NULL;
318 }
319}
320
321wxObject *wxHashTable::Get (const wxChar *key) const
322{
323 int position = (int) (MakeKey (key) % n);
324 if (position < 0) position = -position;
325
326 if (!hash_table[position])
327 return (wxObject *) NULL;
328 else
329 {
330 wxNode *node = hash_table[position]->Find (key);
331 return node ? node->GetData () : (wxObject*)NULL;
332 }
333}
334
335wxObject *wxHashTable::Delete (long key)
336{
337 // Should NEVER be
338 long k = (long) key;
339
340 int position = (int) (k % n);
341 if (position < 0) position = -position;
342
343 if (!hash_table[position])
344 return (wxObject *) NULL;
345 else
346 {
347 wxNode *node = hash_table[position]->Find (k);
348 if (node)
349 {
350 wxObject *data = node->GetData ();
351 delete node;
352 m_count--;
353 return data;
354 }
355 else
356 return (wxObject *) NULL;
357 }
358}
359
360wxObject *wxHashTable::Delete (const wxChar *key)
361{
362 int position = (int) (MakeKey (key) % n);
363 if (position < 0) position = -position;
364
365 if (!hash_table[position])
366 return (wxObject *) NULL;
367 else
368 {
369 wxNode *node = hash_table[position]->Find (key);
370 if (node)
371 {
372 wxObject *data = node->GetData ();
373 delete node;
374 m_count--;
375 return data;
376 }
377 else
378 return (wxObject *) NULL;
379 }
380}
381
382wxObject *wxHashTable::Delete (long key, int value)
383{
384 // Should NEVER be
385 long k = (long) key;
386
387 int position = (int) (k % n);
388 if (position < 0) position = -position;
389
390 if (!hash_table[position])
391 return (wxObject *) NULL;
392 else
393 {
394 wxNode *node = hash_table[position]->Find (value);
395 if (node)
396 {
397 wxObject *data = node->GetData ();
398 delete node;
399 m_count--;
400 return data;
401 }
402 else
403 return (wxObject *) NULL;
404 }
405}
406
407wxObject *wxHashTable::Delete (long key, const wxChar *value)
408{
409 int position = (int) (key % n);
410 if (position < 0) position = -position;
411
412 if (!hash_table[position])
413 return (wxObject *) NULL;
414 else
415 {
416 wxNode *node = hash_table[position]->Find (value);
417 if (node)
418 {
419 wxObject *data = node->GetData ();
420 delete node;
421 m_count--;
422 return data;
423 }
424 else
425 return (wxObject *) NULL;
426 }
427}
428
429long wxHashTable::MakeKey (const wxChar *string) const
430{
431 long int_key = 0;
432
433 while (*string)
434 int_key += (wxUChar) *string++;
435
436 return int_key;
437}
438
439void wxHashTable::BeginFind ()
440{
441 current_position = -1;
442 current_node = (wxNode *) NULL;
443}
444
445wxHashTable::Node* wxHashTable::Next ()
446{
447 wxNode *found = (wxNode *) NULL;
448 bool end = false;
449 while (!end && !found)
450 {
451 if (!current_node)
452 {
453 current_position++;
454 if (current_position >= n)
455 {
456 current_position = -1;
457 current_node = (wxNode *) NULL;
458 end = true;
459 }
460 else
461 {
462 if (hash_table[current_position])
463 {
464 current_node = hash_table[current_position]->GetFirst ();
465 found = current_node;
466 }
467 }
468 }
469 else
470 {
471 current_node = current_node->GetNext ();
472 found = current_node;
473 }
474 }
475 return found;
476}
477
478void wxHashTable::DeleteContents (bool flag)
479{
480 int i;
481 m_deleteContents = flag;
482 for (i = 0; i < n; i++)
483 {
484 if (hash_table[i])
485 hash_table[i]->DeleteContents (flag);
486 }
487}
488
489void wxHashTable::Clear ()
490{
491 int i;
492 if (hash_table)
493 {
494 for (i = 0; i < n; i++)
495 {
496 if (hash_table[i])
497 hash_table[i]->Clear ();
498 }
499 }
500 m_count = 0;
501}
502
503#else // if !wxUSE_OLD_HASH_TABLE
504
505wxHashTableBase_Node::wxHashTableBase_Node( long key, void* value,
506 wxHashTableBase* table )
507 : m_value( value ), m_hashPtr( table )
508{
509 m_key.integer = key;
510}
511
512wxHashTableBase_Node::wxHashTableBase_Node( const wxChar* key, void* value,
513 wxHashTableBase* table )
514 : m_value( value ), m_hashPtr( table )
515{
516 m_key.string = wxStrcpy( new wxChar[wxStrlen( key ) + 1], key );
517}
518
519wxHashTableBase_Node::~wxHashTableBase_Node()
520{
521 if( m_hashPtr ) m_hashPtr->DoRemoveNode( this );
522}
523
524//
525
526wxHashTableBase::wxHashTableBase()
527 : m_size( 0 ), m_count( 0 ), m_table( NULL ), m_keyType( wxKEY_NONE ),
528 m_deleteContents( false )
529{
530}
531
532void wxHashTableBase::Create( wxKeyType keyType, size_t size )
533{
534 m_keyType = keyType;
535 m_size = size;
536 m_table = new wxHashTableBase_Node*[ m_size ];
537
538 for( size_t i = 0; i < m_size; ++i )
539 m_table[i] = NULL;
540}
541
542void wxHashTableBase::Clear()
543{
544 for( size_t i = 0; i < m_size; ++i )
545 {
546 Node* end = m_table[i];
547
548 if( end == NULL )
549 continue;
550
551 Node *curr, *next = end->GetNext();
552
553 do
554 {
555 curr = next;
556 next = curr->GetNext();
557
558 DoDestroyNode( curr );
559
560 delete curr;
561 }
562 while( curr != end );
563
564 m_table[i] = NULL;
565 }
566
567 m_count = 0;
568}
569
570void wxHashTableBase::DoRemoveNode( wxHashTableBase_Node* node )
571{
572 size_t bucket = ( m_keyType == wxKEY_INTEGER ?
573 node->m_key.integer :
574 MakeKey( node->m_key.string ) ) % m_size;
575
576 if( node->GetNext() == node )
577 {
578 // single-node chain (common case)
579 m_table[bucket] = NULL;
580 }
581 else
582 {
583 Node *start = m_table[bucket], *curr;
584 Node* prev = start;
585
586 for( curr = prev->GetNext(); curr != node;
587 prev = curr, curr = curr->GetNext() ) ;
588
589 DoUnlinkNode( bucket, node, prev );
590 }
591
592 DoDestroyNode( node );
593}
594
595void wxHashTableBase::DoDestroyNode( wxHashTableBase_Node* node )
596{
597 // if it is called from DoRemoveNode, node has already been
598 // removed, from other places it does not matter
599 node->m_hashPtr = NULL;
600
601 if( m_keyType == wxKEY_STRING )
602 delete[] node->m_key.string;
603 if( m_deleteContents )
604 DoDeleteContents( node );
605}
606
607void wxHashTableBase::Destroy()
608{
609 Clear();
610
611 delete[] m_table;
612
613 m_table = NULL;
614 m_size = 0;
615}
616
617void wxHashTableBase::DoInsertNode( size_t bucket, wxHashTableBase_Node* node )
618{
619 if( m_table[bucket] == NULL )
620 {
621 m_table[bucket] = node->m_next = node;
622 }
623 else
624 {
625 Node *prev = m_table[bucket];
626 Node *next = prev->m_next;
627
628 prev->m_next = node;
629 node->m_next = next;
630 m_table[bucket] = node;
631 }
632
633 ++m_count;
634}
635
636void wxHashTableBase::DoPut( long key, long hash, void* data )
637{
638 wxASSERT( m_keyType == wxKEY_INTEGER );
639
640 size_t bucket = size_t(hash) % m_size;
641 Node* node = new wxHashTableBase_Node( key, data, this );
642
643 DoInsertNode( bucket, node );
644}
645
646void wxHashTableBase::DoPut( const wxChar* key, long hash, void* data )
647{
648 wxASSERT( m_keyType == wxKEY_STRING );
649
650 size_t bucket = size_t(hash) % m_size;
651 Node* node = new wxHashTableBase_Node( key, data, this );
652
653 DoInsertNode( bucket, node );
654}
655
656void* wxHashTableBase::DoGet( long key, long hash ) const
657{
658 wxASSERT( m_keyType == wxKEY_INTEGER );
659
660 size_t bucket = size_t(hash) % m_size;
661
662 if( m_table[bucket] == NULL )
663 return NULL;
664
665 Node *first = m_table[bucket]->GetNext(),
666 *curr = first;
667
668 do
669 {
670 if( curr->m_key.integer == key )
671 return curr->m_value;
672
673 curr = curr->GetNext();
674 }
675 while( curr != first );
676
677 return NULL;
678}
679
680void* wxHashTableBase::DoGet( const wxChar* key, long hash ) const
681{
682 wxASSERT( m_keyType == wxKEY_STRING );
683
684 size_t bucket = size_t(hash) % m_size;
685
686 if( m_table[bucket] == NULL )
687 return NULL;
688
689 Node *first = m_table[bucket]->GetNext(),
690 *curr = first;
691
692 do
693 {
694 if( wxStrcmp( curr->m_key.string, key ) == 0 )
695 return curr->m_value;
696
697 curr = curr->GetNext();
698 }
699 while( curr != first );
700
701 return NULL;
702}
703
704void wxHashTableBase::DoUnlinkNode( size_t bucket, wxHashTableBase_Node* node,
705 wxHashTableBase_Node* prev )
706{
707 if( node == m_table[bucket] )
708 m_table[bucket] = prev;
709
710 if( prev == node && prev == node->GetNext() )
711 m_table[bucket] = NULL;
712 else
713 prev->m_next = node->m_next;
714
715 DoDestroyNode( node );
716 --m_count;
717}
718
719void* wxHashTableBase::DoDelete( long key, long hash )
720{
721 wxASSERT( m_keyType == wxKEY_INTEGER );
722
723 size_t bucket = size_t(hash) % m_size;
724
725 if( m_table[bucket] == NULL )
726 return NULL;
727
728 Node *first = m_table[bucket]->GetNext(),
729 *curr = first,
730 *prev = m_table[bucket];
731
732 do
733 {
734 if( curr->m_key.integer == key )
735 {
736 void* retval = curr->m_value;
737 curr->m_value = NULL;
738
739 DoUnlinkNode( bucket, curr, prev );
740 delete curr;
741
742 return retval;
743 }
744
745 prev = curr;
746 curr = curr->GetNext();
747 }
748 while( curr != first );
749
750 return NULL;
751}
752
753void* wxHashTableBase::DoDelete( const wxChar* key, long hash )
754{
755 wxASSERT( m_keyType == wxKEY_STRING );
756
757 size_t bucket = size_t(hash) % m_size;
758
759 if( m_table[bucket] == NULL )
760 return NULL;
761
762 Node *first = m_table[bucket]->GetNext(),
763 *curr = first,
764 *prev = m_table[bucket];
765
766 do
767 {
768 if( wxStrcmp( curr->m_key.string, key ) == 0 )
769 {
770 void* retval = curr->m_value;
771 curr->m_value = NULL;
772
773 DoUnlinkNode( bucket, curr, prev );
774 delete curr;
775
776 return retval;
777 }
778
779 prev = curr;
780 curr = curr->GetNext();
781 }
782 while( curr != first );
783
784 return NULL;
785}
786
787long wxHashTableBase::MakeKey( const wxChar *str )
788{
789 long int_key = 0;
790
791 while( *str )
792 int_key += (wxUChar)*str++;
793
794 return int_key;
795}
796
797// ----------------------------------------------------------------------------
798// wxHashTable
799// ----------------------------------------------------------------------------
800
801wxHashTable::wxHashTable( const wxHashTable& table )
802 : wxHashTableBase()
803{
804 DoCopy( table );
805}
806
807const wxHashTable& wxHashTable::operator=( const wxHashTable& table )
808{
809 Destroy();
810 DoCopy( table );
811
812 return *this;
813}
814
815void wxHashTable::DoCopy( const wxHashTable& WXUNUSED(table) )
816{
817 Create( m_keyType, m_size );
818
819 wxFAIL;
820}
821
822void wxHashTable::DoDeleteContents( wxHashTableBase_Node* node )
823{
824 delete ((wxHashTable_Node*)node)->GetData();
825}
826
827void wxHashTable::GetNextNode( size_t bucketStart )
828{
829 for( size_t i = bucketStart; i < m_size; ++i )
830 {
831 if( m_table[i] != NULL )
832 {
833 m_curr = ((Node*)m_table[i])->GetNext();
834 m_currBucket = i;
835 return;
836 }
837 }
838
839 m_curr = NULL;
840 m_currBucket = 0;
841}
842
843wxHashTable::Node* wxHashTable::Next()
844{
845 if( m_curr == NULL )
846 GetNextNode( 0 );
847 else
848 {
849 m_curr = m_curr->GetNext();
850
851 if( m_curr == ( (Node*)m_table[m_currBucket] )->GetNext() )
852 GetNextNode( m_currBucket + 1 );
853 }
854
855 return m_curr;
856}
857
858#endif // !wxUSE_OLD_HASH_TABLE