]> git.saurik.com Git - wxWidgets.git/blob - src/common/hash.cpp
don't crash on weird line endings like \r\r\n
[wxWidgets.git] / src / common / hash.cpp
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
41 IMPLEMENT_DYNAMIC_CLASS(wxHashTable, wxObject)
42
43 // ============================================================================
44 // implementation
45 // ============================================================================
46
47 // ----------------------------------------------------------------------------
48 // wxHashTablleBase for working with "void *" data
49 // ----------------------------------------------------------------------------
50
51 wxHashTableBase::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
60 void 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
73 void 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
90 void 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
102 wxNodeBase *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 #if WXWIN_COMPATIBILITY_2_4
120
121 // ----------------------------------------------------------------------------
122 // wxHashTableLong
123 // ----------------------------------------------------------------------------
124
125 wxHashTableLong::~wxHashTableLong()
126 {
127 Destroy();
128 }
129
130 void wxHashTableLong::Init(size_t size)
131 {
132 m_hashSize = size;
133 m_values = new wxArrayLong *[size];
134 m_keys = new wxArrayLong *[size];
135
136 for ( size_t n = 0; n < m_hashSize; n++ )
137 {
138 m_values[n] =
139 m_keys[n] = (wxArrayLong *)NULL;
140 }
141
142 m_count = 0;
143 }
144
145 void wxHashTableLong::Create(size_t size)
146 {
147 Init(size);
148 }
149
150 void wxHashTableLong::Destroy()
151 {
152 for ( size_t n = 0; n < m_hashSize; n++ )
153 {
154 delete m_values[n];
155 delete m_keys[n];
156 }
157
158 delete [] m_values;
159 delete [] m_keys;
160 m_hashSize = 0;
161 m_count = 0;
162 }
163
164 void wxHashTableLong::Put(long key, long value)
165 {
166 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
167
168 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
169
170 if ( !m_keys[slot] )
171 {
172 m_keys[slot] = new wxArrayLong;
173 m_values[slot] = new wxArrayLong;
174 }
175
176 m_keys[slot]->Add(key);
177 m_values[slot]->Add(value);
178
179 m_count++;
180 }
181
182 long wxHashTableLong::Get(long key) const
183 {
184 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
185
186 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
187
188 wxArrayLong *keys = m_keys[slot];
189 if ( keys )
190 {
191 size_t count = keys->GetCount();
192 for ( size_t n = 0; n < count; n++ )
193 {
194 if ( keys->Item(n) == key )
195 {
196 return m_values[slot]->Item(n);
197 }
198 }
199 }
200
201 return wxNOT_FOUND;
202 }
203
204 long wxHashTableLong::Delete(long key)
205 {
206 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
207
208 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
209
210 wxArrayLong *keys = m_keys[slot];
211 if ( keys )
212 {
213 size_t count = keys->GetCount();
214 for ( size_t n = 0; n < count; n++ )
215 {
216 if ( keys->Item(n) == key )
217 {
218 long val = m_values[slot]->Item(n);
219
220 keys->RemoveAt(n);
221 m_values[slot]->RemoveAt(n);
222
223 m_count--;
224
225 return val;
226 }
227 }
228 }
229
230 return wxNOT_FOUND;
231 }
232
233 // ----------------------------------------------------------------------------
234 // wxStringHashTable: more efficient than storing strings in a list
235 // ----------------------------------------------------------------------------
236
237 wxStringHashTable::wxStringHashTable(size_t sizeTable)
238 {
239 m_keys = new wxArrayLong *[sizeTable];
240 m_values = new wxArrayString *[sizeTable];
241
242 m_hashSize = sizeTable;
243 for ( size_t n = 0; n < m_hashSize; n++ )
244 {
245 m_values[n] = (wxArrayString *)NULL;
246 m_keys[n] = (wxArrayLong *)NULL;
247 }
248 }
249
250 wxStringHashTable::~wxStringHashTable()
251 {
252 Destroy();
253 }
254
255 void wxStringHashTable::Destroy()
256 {
257 for ( size_t n = 0; n < m_hashSize; n++ )
258 {
259 delete m_values[n];
260 delete m_keys[n];
261 }
262
263 delete [] m_values;
264 delete [] m_keys;
265 m_hashSize = 0;
266 }
267
268 void wxStringHashTable::Put(long key, const wxString& value)
269 {
270 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
271
272 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
273
274 if ( !m_keys[slot] )
275 {
276 m_keys[slot] = new wxArrayLong;
277 m_values[slot] = new wxArrayString;
278 }
279
280 m_keys[slot]->Add(key);
281 m_values[slot]->Add(value);
282 }
283
284 wxString wxStringHashTable::Get(long key, bool *wasFound) const
285 {
286 wxCHECK_MSG( m_hashSize, wxEmptyString, _T("must call Create() first") );
287
288 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
289
290 wxArrayLong *keys = m_keys[slot];
291 if ( keys )
292 {
293 size_t count = keys->GetCount();
294 for ( size_t n = 0; n < count; n++ )
295 {
296 if ( keys->Item(n) == key )
297 {
298 if ( wasFound )
299 *wasFound = true;
300
301 return m_values[slot]->Item(n);
302 }
303 }
304 }
305
306 if ( wasFound )
307 *wasFound = false;
308
309 return wxEmptyString;
310 }
311
312 bool wxStringHashTable::Delete(long key) const
313 {
314 wxCHECK_MSG( m_hashSize, false, _T("must call Create() first") );
315
316 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
317
318 wxArrayLong *keys = m_keys[slot];
319 if ( keys )
320 {
321 size_t count = keys->GetCount();
322 for ( size_t n = 0; n < count; n++ )
323 {
324 if ( keys->Item(n) == key )
325 {
326 keys->RemoveAt(n);
327 m_values[slot]->RemoveAt(n);
328 return true;
329 }
330 }
331 }
332
333 return false;
334 }
335
336 #endif // WXWIN_COMPATIBILITY_2_4
337
338 // ----------------------------------------------------------------------------
339 // old not type safe wxHashTable
340 // ----------------------------------------------------------------------------
341
342 wxHashTable::wxHashTable (int the_key_type, int size)
343 {
344 n = 0;
345 hash_table = (wxList**) NULL;
346 Create(the_key_type, size);
347 m_count = 0;
348 m_deleteContents = false;
349 /*
350 n = size;
351 current_position = -1;
352 current_node = (wxNode *) NULL;
353
354 key_type = the_key_type;
355 hash_table = new wxList *[size];
356 int i;
357 for (i = 0; i < size; i++)
358 hash_table[i] = (wxList *) NULL;
359 */
360 }
361
362 wxHashTable::~wxHashTable ()
363 {
364 Destroy();
365 }
366
367 void wxHashTable::Destroy()
368 {
369 if (!hash_table) return;
370 int i;
371 for (i = 0; i < n; i++)
372 if (hash_table[i])
373 delete hash_table[i];
374 delete[] hash_table;
375 hash_table = NULL;
376 }
377
378 bool wxHashTable::Create(int the_key_type, int size)
379 {
380 Destroy();
381
382 n = size;
383 current_position = -1;
384 current_node = (wxNode *) NULL;
385
386 key_type = the_key_type;
387 hash_table = new wxList *[size];
388 int i;
389 for (i = 0; i < size; i++)
390 hash_table[i] = (wxList *) NULL;
391 return true;
392 }
393
394
395 void wxHashTable::DoCopy(const wxHashTable& table)
396 {
397 n = table.n;
398 m_count = table.m_count;
399 current_position = table.current_position;
400 current_node = NULL; // doesn't matter - Next() will reconstruct it
401 key_type = table.key_type;
402
403 hash_table = new wxList *[n];
404 for (int i = 0; i < n; i++) {
405 if (table.hash_table[i] == NULL)
406 hash_table[i] = NULL;
407 else {
408 hash_table[i] = new wxList(key_type);
409 *(hash_table[i]) = *(table.hash_table[i]);
410 }
411 }
412 }
413
414 void wxHashTable::Put (long key, long value, wxObject * object)
415 {
416 // Should NEVER be
417 long k = (long) key;
418
419 int position = (int) (k % n);
420 if (position < 0) position = -position;
421
422 if (!hash_table[position])
423 {
424 hash_table[position] = new wxList (wxKEY_INTEGER);
425 if (m_deleteContents) hash_table[position]->DeleteContents(true);
426 }
427
428 hash_table[position]->Append (value, object);
429 m_count++;
430 }
431
432 void wxHashTable::Put (long key, const wxChar *value, wxObject * object)
433 {
434 // Should NEVER be
435 long k = (long) key;
436
437 int position = (int) (k % n);
438 if (position < 0) position = -position;
439
440 if (!hash_table[position])
441 {
442 hash_table[position] = new wxList (wxKEY_STRING);
443 if (m_deleteContents) hash_table[position]->DeleteContents(true);
444 }
445
446 hash_table[position]->Append (value, object);
447 m_count++;
448 }
449
450 void wxHashTable::Put (long key, wxObject * object)
451 {
452 // Should NEVER be
453 long k = (long) key;
454
455 int position = (int) (k % n);
456 if (position < 0) position = -position;
457
458 if (!hash_table[position])
459 {
460 hash_table[position] = new wxList (wxKEY_INTEGER);
461 if (m_deleteContents) hash_table[position]->DeleteContents(true);
462 }
463
464 hash_table[position]->Append (k, object);
465 m_count++;
466 }
467
468 void wxHashTable::Put (const wxChar *key, wxObject * object)
469 {
470 int position = (int) (MakeKey (key) % n);
471 if (position < 0) position = -position;
472
473 if (!hash_table[position])
474 {
475 hash_table[position] = new wxList (wxKEY_STRING);
476 if (m_deleteContents) hash_table[position]->DeleteContents(true);
477 }
478
479 hash_table[position]->Append (key, object);
480 m_count++;
481 }
482
483 wxObject *wxHashTable::Get (long key, long value) const
484 {
485 // Should NEVER be
486 long k = (long) key;
487
488 int position = (int) (k % n);
489 if (position < 0) position = -position;
490
491 if (!hash_table[position])
492 return (wxObject *) NULL;
493 else
494 {
495 wxNode *node = hash_table[position]->Find (value);
496 if (node)
497 return node->GetData ();
498 else
499 return (wxObject *) NULL;
500 }
501 }
502
503 wxObject *wxHashTable::Get (long key, const wxChar *value) const
504 {
505 // Should NEVER be
506 long k = (long) key;
507
508 int position = (int) (k % n);
509 if (position < 0) position = -position;
510
511 if (!hash_table[position])
512 return (wxObject *) NULL;
513 else
514 {
515 wxNode *node = hash_table[position]->Find (value);
516 if (node)
517 return node->GetData ();
518 else
519 return (wxObject *) NULL;
520 }
521 }
522
523 wxObject *wxHashTable::Get (long key) const
524 {
525 // Should NEVER be
526 long k = (long) key;
527
528 int position = (int) (k % n);
529 if (position < 0) position = -position;
530
531 if (!hash_table[position])
532 return (wxObject *) NULL;
533 else
534 {
535 wxNode *node = hash_table[position]->Find (k);
536 return node ? node->GetData () : (wxObject*)NULL;
537 }
538 }
539
540 wxObject *wxHashTable::Get (const wxChar *key) const
541 {
542 int position = (int) (MakeKey (key) % n);
543 if (position < 0) position = -position;
544
545 if (!hash_table[position])
546 return (wxObject *) NULL;
547 else
548 {
549 wxNode *node = hash_table[position]->Find (key);
550 return node ? node->GetData () : (wxObject*)NULL;
551 }
552 }
553
554 wxObject *wxHashTable::Delete (long key)
555 {
556 // Should NEVER be
557 long k = (long) key;
558
559 int position = (int) (k % n);
560 if (position < 0) position = -position;
561
562 if (!hash_table[position])
563 return (wxObject *) NULL;
564 else
565 {
566 wxNode *node = hash_table[position]->Find (k);
567 if (node)
568 {
569 wxObject *data = node->GetData ();
570 delete node;
571 m_count--;
572 return data;
573 }
574 else
575 return (wxObject *) NULL;
576 }
577 }
578
579 wxObject *wxHashTable::Delete (const wxChar *key)
580 {
581 int position = (int) (MakeKey (key) % n);
582 if (position < 0) position = -position;
583
584 if (!hash_table[position])
585 return (wxObject *) NULL;
586 else
587 {
588 wxNode *node = hash_table[position]->Find (key);
589 if (node)
590 {
591 wxObject *data = node->GetData ();
592 delete node;
593 m_count--;
594 return data;
595 }
596 else
597 return (wxObject *) NULL;
598 }
599 }
600
601 wxObject *wxHashTable::Delete (long key, int value)
602 {
603 // Should NEVER be
604 long k = (long) key;
605
606 int position = (int) (k % n);
607 if (position < 0) position = -position;
608
609 if (!hash_table[position])
610 return (wxObject *) NULL;
611 else
612 {
613 wxNode *node = hash_table[position]->Find (value);
614 if (node)
615 {
616 wxObject *data = node->GetData ();
617 delete node;
618 m_count--;
619 return data;
620 }
621 else
622 return (wxObject *) NULL;
623 }
624 }
625
626 wxObject *wxHashTable::Delete (long key, const wxChar *value)
627 {
628 int position = (int) (key % n);
629 if (position < 0) position = -position;
630
631 if (!hash_table[position])
632 return (wxObject *) NULL;
633 else
634 {
635 wxNode *node = hash_table[position]->Find (value);
636 if (node)
637 {
638 wxObject *data = node->GetData ();
639 delete node;
640 m_count--;
641 return data;
642 }
643 else
644 return (wxObject *) NULL;
645 }
646 }
647
648 long wxHashTable::MakeKey (const wxChar *string) const
649 {
650 long int_key = 0;
651
652 while (*string)
653 int_key += (wxUChar) *string++;
654
655 return int_key;
656 }
657
658 void wxHashTable::BeginFind ()
659 {
660 current_position = -1;
661 current_node = (wxNode *) NULL;
662 }
663
664 wxHashTable::Node* wxHashTable::Next ()
665 {
666 wxNode *found = (wxNode *) NULL;
667 bool end = false;
668 while (!end && !found)
669 {
670 if (!current_node)
671 {
672 current_position++;
673 if (current_position >= n)
674 {
675 current_position = -1;
676 current_node = (wxNode *) NULL;
677 end = true;
678 }
679 else
680 {
681 if (hash_table[current_position])
682 {
683 current_node = hash_table[current_position]->GetFirst ();
684 found = current_node;
685 }
686 }
687 }
688 else
689 {
690 current_node = current_node->GetNext ();
691 found = current_node;
692 }
693 }
694 return found;
695 }
696
697 void wxHashTable::DeleteContents (bool flag)
698 {
699 int i;
700 m_deleteContents = flag;
701 for (i = 0; i < n; i++)
702 {
703 if (hash_table[i])
704 hash_table[i]->DeleteContents (flag);
705 }
706 }
707
708 void wxHashTable::Clear ()
709 {
710 int i;
711 if (hash_table)
712 {
713 for (i = 0; i < n; i++)
714 {
715 if (hash_table[i])
716 hash_table[i]->Clear ();
717 }
718 }
719 m_count = 0;
720 }
721
722 #else // if !wxUSE_OLD_HASH_TABLE
723
724 wxHashTableBase_Node::wxHashTableBase_Node( long key, void* value,
725 wxHashTableBase* table )
726 : m_value( value ), m_hashPtr( table )
727 {
728 m_key.integer = key;
729 }
730
731 wxHashTableBase_Node::wxHashTableBase_Node( const wxChar* key, void* value,
732 wxHashTableBase* table )
733 : m_value( value ), m_hashPtr( table )
734 {
735 m_key.string = wxStrcpy( new wxChar[wxStrlen( key ) + 1], key );
736 }
737
738 wxHashTableBase_Node::~wxHashTableBase_Node()
739 {
740 if( m_hashPtr ) m_hashPtr->DoRemoveNode( this );
741 }
742
743 //
744
745 wxHashTableBase::wxHashTableBase()
746 : m_size( 0 ), m_count( 0 ), m_table( NULL ), m_keyType( wxKEY_NONE ),
747 m_deleteContents( false )
748 {
749 }
750
751 void wxHashTableBase::Create( wxKeyType keyType, size_t size )
752 {
753 m_keyType = keyType;
754 m_size = size;
755 m_table = new wxHashTableBase_Node*[ m_size ];
756
757 for( size_t i = 0; i < m_size; ++i )
758 m_table[i] = NULL;
759 }
760
761 void wxHashTableBase::Clear()
762 {
763 for( size_t i = 0; i < m_size; ++i )
764 {
765 Node* end = m_table[i];
766
767 if( end == NULL )
768 continue;
769
770 Node *curr, *next = end->GetNext();
771
772 do
773 {
774 curr = next;
775 next = curr->GetNext();
776
777 DoDestroyNode( curr );
778
779 delete curr;
780 }
781 while( curr != end );
782
783 m_table[i] = NULL;
784 }
785
786 m_count = 0;
787 }
788
789 void wxHashTableBase::DoRemoveNode( wxHashTableBase_Node* node )
790 {
791 size_t bucket = ( m_keyType == wxKEY_INTEGER ?
792 node->m_key.integer :
793 MakeKey( node->m_key.string ) ) % m_size;
794
795 if( node->GetNext() == node )
796 {
797 // single-node chain (common case)
798 m_table[bucket] = NULL;
799 }
800 else
801 {
802 Node *start = m_table[bucket], *curr;
803 Node* prev = start;
804
805 for( curr = prev->GetNext(); curr != node;
806 prev = curr, curr = curr->GetNext() ) ;
807
808 DoUnlinkNode( bucket, node, prev );
809 }
810
811 DoDestroyNode( node );
812 }
813
814 void wxHashTableBase::DoDestroyNode( wxHashTableBase_Node* node )
815 {
816 // if it is called from DoRemoveNode, node has already been
817 // removed, from other places it does not matter
818 node->m_hashPtr = NULL;
819
820 if( m_keyType == wxKEY_STRING )
821 delete[] node->m_key.string;
822 if( m_deleteContents )
823 DoDeleteContents( node );
824 }
825
826 void wxHashTableBase::Destroy()
827 {
828 Clear();
829
830 delete[] m_table;
831
832 m_table = NULL;
833 m_size = 0;
834 }
835
836 void wxHashTableBase::DoInsertNode( size_t bucket, wxHashTableBase_Node* node )
837 {
838 if( m_table[bucket] == NULL )
839 {
840 m_table[bucket] = node->m_next = node;
841 }
842 else
843 {
844 Node *prev = m_table[bucket];
845 Node *next = prev->m_next;
846
847 prev->m_next = node;
848 node->m_next = next;
849 m_table[bucket] = node;
850 }
851
852 ++m_count;
853 }
854
855 void wxHashTableBase::DoPut( long key, long hash, void* data )
856 {
857 wxASSERT( m_keyType == wxKEY_INTEGER );
858
859 size_t bucket = size_t(hash) % m_size;
860 Node* node = new wxHashTableBase_Node( key, data, this );
861
862 DoInsertNode( bucket, node );
863 }
864
865 void wxHashTableBase::DoPut( const wxChar* key, long hash, void* data )
866 {
867 wxASSERT( m_keyType == wxKEY_STRING );
868
869 size_t bucket = size_t(hash) % m_size;
870 Node* node = new wxHashTableBase_Node( key, data, this );
871
872 DoInsertNode( bucket, node );
873 }
874
875 void* wxHashTableBase::DoGet( long key, long hash ) const
876 {
877 wxASSERT( m_keyType == wxKEY_INTEGER );
878
879 size_t bucket = size_t(hash) % m_size;
880
881 if( m_table[bucket] == NULL )
882 return NULL;
883
884 Node *first = m_table[bucket]->GetNext(),
885 *curr = first;
886
887 do
888 {
889 if( curr->m_key.integer == key )
890 return curr->m_value;
891
892 curr = curr->GetNext();
893 }
894 while( curr != first );
895
896 return NULL;
897 }
898
899 void* wxHashTableBase::DoGet( const wxChar* key, long hash ) const
900 {
901 wxASSERT( m_keyType == wxKEY_STRING );
902
903 size_t bucket = size_t(hash) % m_size;
904
905 if( m_table[bucket] == NULL )
906 return NULL;
907
908 Node *first = m_table[bucket]->GetNext(),
909 *curr = first;
910
911 do
912 {
913 if( wxStrcmp( curr->m_key.string, key ) == 0 )
914 return curr->m_value;
915
916 curr = curr->GetNext();
917 }
918 while( curr != first );
919
920 return NULL;
921 }
922
923 void wxHashTableBase::DoUnlinkNode( size_t bucket, wxHashTableBase_Node* node,
924 wxHashTableBase_Node* prev )
925 {
926 if( node == m_table[bucket] )
927 m_table[bucket] = prev;
928
929 if( prev == node && prev == node->GetNext() )
930 m_table[bucket] = NULL;
931 else
932 prev->m_next = node->m_next;
933
934 DoDestroyNode( node );
935 --m_count;
936 }
937
938 void* wxHashTableBase::DoDelete( long key, long hash )
939 {
940 wxASSERT( m_keyType == wxKEY_INTEGER );
941
942 size_t bucket = size_t(hash) % m_size;
943
944 if( m_table[bucket] == NULL )
945 return NULL;
946
947 Node *first = m_table[bucket]->GetNext(),
948 *curr = first,
949 *prev = m_table[bucket];
950
951 do
952 {
953 if( curr->m_key.integer == key )
954 {
955 void* retval = curr->m_value;
956 curr->m_value = NULL;
957
958 DoUnlinkNode( bucket, curr, prev );
959 delete curr;
960
961 return retval;
962 }
963
964 prev = curr;
965 curr = curr->GetNext();
966 }
967 while( curr != first );
968
969 return NULL;
970 }
971
972 void* wxHashTableBase::DoDelete( const wxChar* key, long hash )
973 {
974 wxASSERT( m_keyType == wxKEY_STRING );
975
976 size_t bucket = size_t(hash) % m_size;
977
978 if( m_table[bucket] == NULL )
979 return NULL;
980
981 Node *first = m_table[bucket]->GetNext(),
982 *curr = first,
983 *prev = m_table[bucket];
984
985 do
986 {
987 if( wxStrcmp( curr->m_key.string, key ) == 0 )
988 {
989 void* retval = curr->m_value;
990 curr->m_value = NULL;
991
992 DoUnlinkNode( bucket, curr, prev );
993 delete curr;
994
995 return retval;
996 }
997
998 prev = curr;
999 curr = curr->GetNext();
1000 }
1001 while( curr != first );
1002
1003 return NULL;
1004 }
1005
1006 long wxHashTableBase::MakeKey( const wxChar *str )
1007 {
1008 long int_key = 0;
1009
1010 while( *str )
1011 int_key += (wxUChar)*str++;
1012
1013 return int_key;
1014 }
1015
1016 // ----------------------------------------------------------------------------
1017 // wxHashTable
1018 // ----------------------------------------------------------------------------
1019
1020 wxHashTable::wxHashTable( const wxHashTable& table )
1021 : wxHashTableBase()
1022 {
1023 DoCopy( table );
1024 }
1025
1026 const wxHashTable& wxHashTable::operator=( const wxHashTable& table )
1027 {
1028 Destroy();
1029 DoCopy( table );
1030
1031 return *this;
1032 }
1033
1034 void wxHashTable::DoCopy( const wxHashTable& WXUNUSED(table) )
1035 {
1036 Create( m_keyType, m_size );
1037
1038 wxFAIL;
1039 }
1040
1041 void wxHashTable::DoDeleteContents( wxHashTableBase_Node* node )
1042 {
1043 delete ((wxHashTable_Node*)node)->GetData();
1044 }
1045
1046 void wxHashTable::GetNextNode( size_t bucketStart )
1047 {
1048 for( size_t i = bucketStart; i < m_size; ++i )
1049 {
1050 if( m_table[i] != NULL )
1051 {
1052 m_curr = ((Node*)m_table[i])->GetNext();
1053 m_currBucket = i;
1054 return;
1055 }
1056 }
1057
1058 m_curr = NULL;
1059 m_currBucket = 0;
1060 }
1061
1062 wxHashTable::Node* wxHashTable::Next()
1063 {
1064 if( m_curr == NULL )
1065 GetNextNode( 0 );
1066 else
1067 {
1068 m_curr = m_curr->GetNext();
1069
1070 if( m_curr == ( (Node*)m_table[m_currBucket] )->GetNext() )
1071 GetNextNode( m_currBucket + 1 );
1072 }
1073
1074 return m_curr;
1075 }
1076
1077 #endif // !wxUSE_OLD_HASH_TABLE