]> git.saurik.com Git - wxWidgets.git/blame - src/common/hash.cpp
Bug fix.
[wxWidgets.git] / src / common / hash.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
7cb32b4b 2// Name: src/common/hash.cpp
c801d85f
KB
3// Purpose: wxHashTable implementation
4// Author: Julian Smart
bcaa23de 5// Modified by: VZ at 25.02.00: type safe hashes with WX_DECLARE_HASH()
c801d85f
KB
6// Created: 01/02/97
7// RCS-ID: $Id$
55d99c7a 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
bcaa23de
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
8ecff181 24 #pragma hdrstop
c801d85f
KB
25#endif
26
27#ifndef WX_PRECOMP
8ecff181 28 #include "wx/list.h"
32d4c30a 29 #include "wx/hash.h"
c801d85f
KB
30#endif
31
6e86701b 32#if wxUSE_OLD_HASH_TABLE
df5168c4 33
c801d85f
KB
34#include <string.h>
35#include <stdarg.h>
36
bcaa23de
VZ
37// ----------------------------------------------------------------------------
38// wxWin macros
39// ----------------------------------------------------------------------------
40
c801d85f 41IMPLEMENT_DYNAMIC_CLASS(wxHashTable, wxObject)
c801d85f 42
bcaa23de
VZ
43// ============================================================================
44// implementation
45// ============================================================================
46
47// ----------------------------------------------------------------------------
48// wxHashTablleBase for working with "void *" data
49// ----------------------------------------------------------------------------
50
51wxHashTableBase::wxHashTableBase()
52{
f803b25b 53 m_deleteContents = false;
bcaa23de
VZ
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{
3ca6a5f0 104 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
bcaa23de
VZ
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
ba8c1601
MB
119#if WXWIN_COMPATIBILITY_2_4
120
c2bb85e9
VZ
121// ----------------------------------------------------------------------------
122// wxHashTableLong
123// ----------------------------------------------------------------------------
124
a95e38c0
VZ
125wxHashTableLong::~wxHashTableLong()
126{
127 Destroy();
128}
129
c2bb85e9
VZ
130void 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
b7aaabf8
VS
145void wxHashTableLong::Create(size_t size)
146{
147 Init(size);
148}
149
c2bb85e9
VZ
150void 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
164void wxHashTableLong::Put(long key, long value)
165{
166 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
167
3ca6a5f0 168 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
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
182long wxHashTableLong::Get(long key) const
183{
184 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
185
3ca6a5f0 186 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
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
204long wxHashTableLong::Delete(long key)
205{
206 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
207
3ca6a5f0 208 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
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
bd83cb56
VZ
233// ----------------------------------------------------------------------------
234// wxStringHashTable: more efficient than storing strings in a list
235// ----------------------------------------------------------------------------
236
237wxStringHashTable::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
250wxStringHashTable::~wxStringHashTable()
251{
252 Destroy();
253}
254
255void 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
268void 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
284wxString wxStringHashTable::Get(long key, bool *wasFound) const
285{
525d8583 286 wxCHECK_MSG( m_hashSize, wxEmptyString, _T("must call Create() first") );
bd83cb56
VZ
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 )
f803b25b 299 *wasFound = true;
bd83cb56
VZ
300
301 return m_values[slot]->Item(n);
302 }
303 }
304 }
305
306 if ( wasFound )
f803b25b 307 *wasFound = false;
bd83cb56 308
525d8583 309 return wxEmptyString;
bd83cb56
VZ
310}
311
53e112a0
JS
312bool wxStringHashTable::Delete(long key) const
313{
f803b25b 314 wxCHECK_MSG( m_hashSize, false, _T("must call Create() first") );
53e112a0
JS
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 {
f8305caf 326 keys->RemoveAt(n);
53e112a0 327 m_values[slot]->RemoveAt(n);
f803b25b 328 return true;
53e112a0
JS
329 }
330 }
331 }
332
f803b25b 333 return false;
53e112a0
JS
334}
335
ba8c1601
MB
336#endif // WXWIN_COMPATIBILITY_2_4
337
bcaa23de
VZ
338// ----------------------------------------------------------------------------
339// old not type safe wxHashTable
340// ----------------------------------------------------------------------------
341
debe6624 342wxHashTable::wxHashTable (int the_key_type, int size)
c801d85f 343{
17d8ee1c
JS
344 n = 0;
345 hash_table = (wxList**) NULL;
346 Create(the_key_type, size);
5692876f 347 m_count = 0;
f803b25b 348 m_deleteContents = false;
17d8ee1c 349/*
c801d85f
KB
350 n = size;
351 current_position = -1;
c67daf87 352 current_node = (wxNode *) NULL;
c801d85f
KB
353
354 key_type = the_key_type;
355 hash_table = new wxList *[size];
356 int i;
357 for (i = 0; i < size; i++)
c67daf87 358 hash_table[i] = (wxList *) NULL;
17d8ee1c 359*/
c801d85f
KB
360}
361
bcaa23de 362wxHashTable::~wxHashTable ()
c801d85f 363{
e55ad60e
RR
364 Destroy();
365}
366
bcaa23de 367void wxHashTable::Destroy()
e55ad60e
RR
368{
369 if (!hash_table) return;
c801d85f
KB
370 int i;
371 for (i = 0; i < n; i++)
372 if (hash_table[i])
373 delete hash_table[i];
374 delete[] hash_table;
e55ad60e 375 hash_table = NULL;
c801d85f
KB
376}
377
debe6624 378bool wxHashTable::Create(int the_key_type, int size)
c801d85f 379{
17d8ee1c
JS
380 Destroy();
381
c801d85f
KB
382 n = size;
383 current_position = -1;
c67daf87 384 current_node = (wxNode *) NULL;
c801d85f
KB
385
386 key_type = the_key_type;
c801d85f
KB
387 hash_table = new wxList *[size];
388 int i;
389 for (i = 0; i < size; i++)
c67daf87 390 hash_table[i] = (wxList *) NULL;
f803b25b 391 return true;
c801d85f
KB
392}
393
4e67bfc7
VS
394
395void wxHashTable::DoCopy(const wxHashTable& table)
396{
397 n = table.n;
ea450825 398 m_count = table.m_count;
4e67bfc7
VS
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
debe6624 414void wxHashTable::Put (long key, long value, wxObject * object)
c801d85f
KB
415{
416 // Should NEVER be
417 long k = (long) key;
c801d85f
KB
418
419 int position = (int) (k % n);
ffae916f
BJ
420 if (position < 0) position = -position;
421
c801d85f 422 if (!hash_table[position])
c7fb814a 423 {
cbb26e3f 424 hash_table[position] = new wxList (wxKEY_INTEGER);
f803b25b 425 if (m_deleteContents) hash_table[position]->DeleteContents(true);
c7fb814a 426 }
c801d85f
KB
427
428 hash_table[position]->Append (value, object);
5692876f 429 m_count++;
c801d85f
KB
430}
431
50920146 432void wxHashTable::Put (long key, const wxChar *value, wxObject * object)
c801d85f
KB
433{
434 // Should NEVER be
bcaa23de 435 long k = (long) key;
c801d85f
KB
436
437 int position = (int) (k % n);
ffae916f 438 if (position < 0) position = -position;
bcaa23de 439
c801d85f 440 if (!hash_table[position])
c7fb814a 441 {
cbb26e3f 442 hash_table[position] = new wxList (wxKEY_STRING);
f803b25b 443 if (m_deleteContents) hash_table[position]->DeleteContents(true);
c7fb814a 444 }
c801d85f
KB
445
446 hash_table[position]->Append (value, object);
5692876f 447 m_count++;
c801d85f
KB
448}
449
debe6624 450void wxHashTable::Put (long key, wxObject * object)
c801d85f
KB
451{
452 // Should NEVER be
453 long k = (long) key;
bcaa23de 454
c801d85f 455 int position = (int) (k % n);
ffae916f
BJ
456 if (position < 0) position = -position;
457
c801d85f 458 if (!hash_table[position])
c7fb814a 459 {
c801d85f 460 hash_table[position] = new wxList (wxKEY_INTEGER);
f803b25b 461 if (m_deleteContents) hash_table[position]->DeleteContents(true);
c7fb814a 462 }
bcaa23de 463
c801d85f 464 hash_table[position]->Append (k, object);
5692876f 465 m_count++;
c801d85f
KB
466}
467
50920146 468void wxHashTable::Put (const wxChar *key, wxObject * object)
c801d85f
KB
469{
470 int position = (int) (MakeKey (key) % n);
ffae916f 471 if (position < 0) position = -position;
c801d85f
KB
472
473 if (!hash_table[position])
c7fb814a 474 {
c801d85f 475 hash_table[position] = new wxList (wxKEY_STRING);
f803b25b 476 if (m_deleteContents) hash_table[position]->DeleteContents(true);
c7fb814a 477 }
c801d85f
KB
478
479 hash_table[position]->Append (key, object);
5692876f 480 m_count++;
c801d85f
KB
481}
482
debe6624 483wxObject *wxHashTable::Get (long key, long value) const
c801d85f
KB
484{
485 // Should NEVER be
486 long k = (long) key;
c801d85f
KB
487
488 int position = (int) (k % n);
ffae916f
BJ
489 if (position < 0) position = -position;
490
c801d85f 491 if (!hash_table[position])
c67daf87 492 return (wxObject *) NULL;
c801d85f
KB
493 else
494 {
495 wxNode *node = hash_table[position]->Find (value);
496 if (node)
b1d4dd7a 497 return node->GetData ();
c801d85f 498 else
bcaa23de 499 return (wxObject *) NULL;
c801d85f
KB
500 }
501}
502
50920146 503wxObject *wxHashTable::Get (long key, const wxChar *value) const
c801d85f
KB
504{
505 // Should NEVER be
506 long k = (long) key;
bcaa23de 507
c801d85f 508 int position = (int) (k % n);
ffae916f
BJ
509 if (position < 0) position = -position;
510
c801d85f 511 if (!hash_table[position])
c67daf87 512 return (wxObject *) NULL;
c801d85f
KB
513 else
514 {
515 wxNode *node = hash_table[position]->Find (value);
516 if (node)
b1d4dd7a 517 return node->GetData ();
c801d85f 518 else
bcaa23de 519 return (wxObject *) NULL;
c801d85f
KB
520 }
521}
522
debe6624 523wxObject *wxHashTable::Get (long key) const
c801d85f
KB
524{
525 // Should NEVER be
526 long k = (long) key;
c801d85f
KB
527
528 int position = (int) (k % n);
ffae916f
BJ
529 if (position < 0) position = -position;
530
c801d85f 531 if (!hash_table[position])
c67daf87 532 return (wxObject *) NULL;
c801d85f
KB
533 else
534 {
535 wxNode *node = hash_table[position]->Find (k);
b1d4dd7a 536 return node ? node->GetData () : (wxObject*)NULL;
c801d85f
KB
537 }
538}
539
50920146 540wxObject *wxHashTable::Get (const wxChar *key) const
c801d85f
KB
541{
542 int position = (int) (MakeKey (key) % n);
ffae916f 543 if (position < 0) position = -position;
c801d85f
KB
544
545 if (!hash_table[position])
c67daf87 546 return (wxObject *) NULL;
c801d85f
KB
547 else
548 {
549 wxNode *node = hash_table[position]->Find (key);
b1d4dd7a 550 return node ? node->GetData () : (wxObject*)NULL;
c801d85f
KB
551 }
552}
553
debe6624 554wxObject *wxHashTable::Delete (long key)
c801d85f
KB
555{
556 // Should NEVER be
557 long k = (long) key;
c801d85f
KB
558
559 int position = (int) (k % n);
ffae916f
BJ
560 if (position < 0) position = -position;
561
c801d85f 562 if (!hash_table[position])
c67daf87 563 return (wxObject *) NULL;
c801d85f
KB
564 else
565 {
566 wxNode *node = hash_table[position]->Find (k);
567 if (node)
bcaa23de 568 {
b1d4dd7a 569 wxObject *data = node->GetData ();
bcaa23de
VZ
570 delete node;
571 m_count--;
572 return data;
573 }
c801d85f 574 else
bcaa23de 575 return (wxObject *) NULL;
c801d85f
KB
576 }
577}
578
50920146 579wxObject *wxHashTable::Delete (const wxChar *key)
c801d85f
KB
580{
581 int position = (int) (MakeKey (key) % n);
ffae916f
BJ
582 if (position < 0) position = -position;
583
c801d85f 584 if (!hash_table[position])
c67daf87 585 return (wxObject *) NULL;
c801d85f
KB
586 else
587 {
588 wxNode *node = hash_table[position]->Find (key);
589 if (node)
bcaa23de 590 {
b1d4dd7a 591 wxObject *data = node->GetData ();
bcaa23de
VZ
592 delete node;
593 m_count--;
594 return data;
595 }
c801d85f 596 else
bcaa23de 597 return (wxObject *) NULL;
c801d85f
KB
598 }
599}
600
debe6624 601wxObject *wxHashTable::Delete (long key, int value)
c801d85f
KB
602{
603 // Should NEVER be
bcaa23de 604 long k = (long) key;
c801d85f
KB
605
606 int position = (int) (k % n);
ffae916f
BJ
607 if (position < 0) position = -position;
608
c801d85f 609 if (!hash_table[position])
c67daf87 610 return (wxObject *) NULL;
c801d85f
KB
611 else
612 {
613 wxNode *node = hash_table[position]->Find (value);
614 if (node)
bcaa23de 615 {
b1d4dd7a 616 wxObject *data = node->GetData ();
bcaa23de
VZ
617 delete node;
618 m_count--;
619 return data;
620 }
c801d85f 621 else
bcaa23de 622 return (wxObject *) NULL;
c801d85f
KB
623 }
624}
625
50920146 626wxObject *wxHashTable::Delete (long key, const wxChar *value)
c801d85f
KB
627{
628 int position = (int) (key % n);
ffae916f
BJ
629 if (position < 0) position = -position;
630
c801d85f 631 if (!hash_table[position])
c67daf87 632 return (wxObject *) NULL;
c801d85f
KB
633 else
634 {
635 wxNode *node = hash_table[position]->Find (value);
636 if (node)
bcaa23de 637 {
b1d4dd7a 638 wxObject *data = node->GetData ();
bcaa23de
VZ
639 delete node;
640 m_count--;
641 return data;
642 }
c801d85f 643 else
bcaa23de 644 return (wxObject *) NULL;
c801d85f
KB
645 }
646}
647
50920146 648long wxHashTable::MakeKey (const wxChar *string) const
c801d85f
KB
649{
650 long int_key = 0;
651
652 while (*string)
50920146 653 int_key += (wxUChar) *string++;
c801d85f
KB
654
655 return int_key;
656}
657
bcaa23de 658void wxHashTable::BeginFind ()
c801d85f
KB
659{
660 current_position = -1;
c67daf87 661 current_node = (wxNode *) NULL;
c801d85f
KB
662}
663
1a6d9c76 664wxHashTable::Node* wxHashTable::Next ()
c801d85f 665{
c67daf87 666 wxNode *found = (wxNode *) NULL;
f803b25b 667 bool end = false;
c801d85f
KB
668 while (!end && !found)
669 {
670 if (!current_node)
bcaa23de
VZ
671 {
672 current_position++;
673 if (current_position >= n)
674 {
675 current_position = -1;
676 current_node = (wxNode *) NULL;
f803b25b 677 end = true;
bcaa23de
VZ
678 }
679 else
680 {
681 if (hash_table[current_position])
682 {
b1d4dd7a 683 current_node = hash_table[current_position]->GetFirst ();
bcaa23de
VZ
684 found = current_node;
685 }
686 }
687 }
c801d85f 688 else
bcaa23de 689 {
b1d4dd7a 690 current_node = current_node->GetNext ();
bcaa23de
VZ
691 found = current_node;
692 }
c801d85f
KB
693 }
694 return found;
695}
696
debe6624 697void wxHashTable::DeleteContents (bool flag)
c801d85f
KB
698{
699 int i;
c7fb814a 700 m_deleteContents = flag;
c801d85f
KB
701 for (i = 0; i < n; i++)
702 {
703 if (hash_table[i])
bcaa23de 704 hash_table[i]->DeleteContents (flag);
c801d85f
KB
705 }
706}
707
bcaa23de 708void wxHashTable::Clear ()
c801d85f 709{
19230604
RD
710 int i;
711 if (hash_table)
c801d85f 712 {
19230604
RD
713 for (i = 0; i < n; i++)
714 {
715 if (hash_table[i])
716 hash_table[i]->Clear ();
717 }
c801d85f 718 }
5692876f 719 m_count = 0;
c801d85f
KB
720}
721
6e86701b 722#else // if !wxUSE_OLD_HASH_TABLE
1a6d9c76
MB
723
724wxHashTableBase_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
731wxHashTableBase_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
738wxHashTableBase_Node::~wxHashTableBase_Node()
739{
740 if( m_hashPtr ) m_hashPtr->DoRemoveNode( this );
741}
742
743//
744
745wxHashTableBase::wxHashTableBase()
746 : m_size( 0 ), m_count( 0 ), m_table( NULL ), m_keyType( wxKEY_NONE ),
747 m_deleteContents( false )
748{
749}
750
1a6d9c76
MB
751void 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
761void 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
789void 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;
f803b25b 806 prev = curr, curr = curr->GetNext() ) ;
1a6d9c76
MB
807
808 DoUnlinkNode( bucket, node, prev );
809 }
810
811 DoDestroyNode( node );
812}
813
814void 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
826void wxHashTableBase::Destroy()
827{
828 Clear();
829
830 delete[] m_table;
831
832 m_table = NULL;
833 m_size = 0;
834}
835
836void 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
855void 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
865void 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
875void* 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
899void* 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
923void 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
938void* 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
972void* 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
1006long 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
2441fb44
VZ
1016// ----------------------------------------------------------------------------
1017// wxHashTable
1018// ----------------------------------------------------------------------------
1a6d9c76
MB
1019
1020wxHashTable::wxHashTable( const wxHashTable& table )
2441fb44 1021 : wxHashTableBase()
1a6d9c76
MB
1022{
1023 DoCopy( table );
1024}
1025
1026const wxHashTable& wxHashTable::operator=( const wxHashTable& table )
1027{
1028 Destroy();
1029 DoCopy( table );
1030
1031 return *this;
1032}
1033
6aa33060 1034void wxHashTable::DoCopy( const wxHashTable& WXUNUSED(table) )
1a6d9c76
MB
1035{
1036 Create( m_keyType, m_size );
1037
7cb32b4b 1038 wxFAIL;
1a6d9c76
MB
1039}
1040
1041void wxHashTable::DoDeleteContents( wxHashTableBase_Node* node )
1042{
1043 delete ((wxHashTable_Node*)node)->GetData();
1044}
1045
1046void 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
1062wxHashTable::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
6e86701b 1077#endif // !wxUSE_OLD_HASH_TABLE