]> git.saurik.com Git - wxWidgets.git/blame - src/common/hash.cpp
Fixed size buffers are not a good thing. Period.
[wxWidgets.git] / src / common / hash.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: hash.cpp
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$
8// Copyright: (c) Julian Smart and Markus Holzem
bcaa23de 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
bcaa23de
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f
KB
20#ifdef __GNUG__
21#pragma implementation "hash.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28#pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32#include "wx/list.h"
33#endif
34
35#include "wx/hash.h"
36
37#include <string.h>
38#include <stdarg.h>
39
bcaa23de
VZ
40// ----------------------------------------------------------------------------
41// wxWin macros
42// ----------------------------------------------------------------------------
43
c801d85f 44IMPLEMENT_DYNAMIC_CLASS(wxHashTable, wxObject)
c801d85f 45
bcaa23de
VZ
46// ============================================================================
47// implementation
48// ============================================================================
49
50// ----------------------------------------------------------------------------
51// wxHashTablleBase for working with "void *" data
52// ----------------------------------------------------------------------------
53
54wxHashTableBase::wxHashTableBase()
55{
56 m_deleteContents = FALSE;
57 m_hashTable = (wxListBase **)NULL;
58 m_hashSize = 0;
59 m_count = 0;
60 m_keyType = wxKEY_NONE;
61}
62
63void wxHashTableBase::Create(wxKeyType keyType, size_t size)
64{
65 Destroy();
66
67 m_hashSize = size;
68 m_keyType = keyType;
69 m_hashTable = new wxListBase *[size];
70 for ( size_t n = 0; n < m_hashSize; n++ )
71 {
72 m_hashTable[n] = (wxListBase *) NULL;
73 }
74}
75
76void wxHashTableBase::Destroy()
77{
78 if ( m_hashTable )
79 {
80 for ( size_t n = 0; n < m_hashSize; n++ )
81 {
82 delete m_hashTable[n];
83 }
84
85 delete [] m_hashTable;
86
87 m_hashTable = (wxListBase **)NULL;
88
89 m_count = 0;
90 }
91}
92
93void wxHashTableBase::DeleteContents(bool flag)
94{
95 m_deleteContents = flag;
96 for ( size_t n = 0; n < m_hashSize; n++ )
97 {
98 if ( m_hashTable[n] )
99 {
100 m_hashTable[n]->DeleteContents(flag);
101 }
102 }
103}
104
105wxNodeBase *wxHashTableBase::GetNode(long key, long value) const
106{
3ca6a5f0 107 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
bcaa23de
VZ
108
109 wxNodeBase *node;
110 if ( m_hashTable[slot] )
111 {
112 node = m_hashTable[slot]->Find(wxListKey(value));
113 }
114 else
115 {
116 node = (wxNodeBase *)NULL;
117 }
118
119 return node;
120}
121
c2bb85e9
VZ
122// ----------------------------------------------------------------------------
123// wxHashTableLong
124// ----------------------------------------------------------------------------
125
a95e38c0
VZ
126wxHashTableLong::~wxHashTableLong()
127{
128 Destroy();
129}
130
c2bb85e9
VZ
131void wxHashTableLong::Init(size_t size)
132{
133 m_hashSize = size;
134 m_values = new wxArrayLong *[size];
135 m_keys = new wxArrayLong *[size];
136
137 for ( size_t n = 0; n < m_hashSize; n++ )
138 {
139 m_values[n] =
140 m_keys[n] = (wxArrayLong *)NULL;
141 }
142
143 m_count = 0;
144}
145
b7aaabf8
VS
146void wxHashTableLong::Create(size_t size)
147{
148 Init(size);
149}
150
c2bb85e9
VZ
151void wxHashTableLong::Destroy()
152{
153 for ( size_t n = 0; n < m_hashSize; n++ )
154 {
155 delete m_values[n];
156 delete m_keys[n];
157 }
158
159 delete [] m_values;
160 delete [] m_keys;
161 m_hashSize = 0;
162 m_count = 0;
163}
164
165void wxHashTableLong::Put(long key, long value)
166{
167 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
168
3ca6a5f0 169 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
170
171 if ( !m_keys[slot] )
172 {
173 m_keys[slot] = new wxArrayLong;
174 m_values[slot] = new wxArrayLong;
175 }
176
177 m_keys[slot]->Add(key);
178 m_values[slot]->Add(value);
179
180 m_count++;
181}
182
183long wxHashTableLong::Get(long key) const
184{
185 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
186
3ca6a5f0 187 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
188
189 wxArrayLong *keys = m_keys[slot];
190 if ( keys )
191 {
192 size_t count = keys->GetCount();
193 for ( size_t n = 0; n < count; n++ )
194 {
195 if ( keys->Item(n) == key )
196 {
197 return m_values[slot]->Item(n);
198 }
199 }
200 }
201
202 return wxNOT_FOUND;
203}
204
205long wxHashTableLong::Delete(long key)
206{
207 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
208
3ca6a5f0 209 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
210
211 wxArrayLong *keys = m_keys[slot];
212 if ( keys )
213 {
214 size_t count = keys->GetCount();
215 for ( size_t n = 0; n < count; n++ )
216 {
217 if ( keys->Item(n) == key )
218 {
219 long val = m_values[slot]->Item(n);
220
221 keys->RemoveAt(n);
222 m_values[slot]->RemoveAt(n);
223
224 m_count--;
225
226 return val;
227 }
228 }
229 }
230
231 return wxNOT_FOUND;
232}
233
bd83cb56
VZ
234// ----------------------------------------------------------------------------
235// wxStringHashTable: more efficient than storing strings in a list
236// ----------------------------------------------------------------------------
237
238wxStringHashTable::wxStringHashTable(size_t sizeTable)
239{
240 m_keys = new wxArrayLong *[sizeTable];
241 m_values = new wxArrayString *[sizeTable];
242
243 m_hashSize = sizeTable;
244 for ( size_t n = 0; n < m_hashSize; n++ )
245 {
246 m_values[n] = (wxArrayString *)NULL;
247 m_keys[n] = (wxArrayLong *)NULL;
248 }
249}
250
251wxStringHashTable::~wxStringHashTable()
252{
253 Destroy();
254}
255
256void wxStringHashTable::Destroy()
257{
258 for ( size_t n = 0; n < m_hashSize; n++ )
259 {
260 delete m_values[n];
261 delete m_keys[n];
262 }
263
264 delete [] m_values;
265 delete [] m_keys;
266 m_hashSize = 0;
267}
268
269void wxStringHashTable::Put(long key, const wxString& value)
270{
271 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
272
273 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
274
275 if ( !m_keys[slot] )
276 {
277 m_keys[slot] = new wxArrayLong;
278 m_values[slot] = new wxArrayString;
279 }
280
281 m_keys[slot]->Add(key);
282 m_values[slot]->Add(value);
283}
284
285wxString wxStringHashTable::Get(long key, bool *wasFound) const
286{
287 wxCHECK_MSG( m_hashSize, _T(""), _T("must call Create() first") );
288
289 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
290
291 wxArrayLong *keys = m_keys[slot];
292 if ( keys )
293 {
294 size_t count = keys->GetCount();
295 for ( size_t n = 0; n < count; n++ )
296 {
297 if ( keys->Item(n) == key )
298 {
299 if ( wasFound )
300 *wasFound = TRUE;
301
302 return m_values[slot]->Item(n);
303 }
304 }
305 }
306
307 if ( wasFound )
308 *wasFound = FALSE;
309
310 return _T("");
311}
312
53e112a0
JS
313bool wxStringHashTable::Delete(long key) const
314{
315 wxCHECK_MSG( m_hashSize, FALSE, _T("must call Create() first") );
316
317 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
318
319 wxArrayLong *keys = m_keys[slot];
320 if ( keys )
321 {
322 size_t count = keys->GetCount();
323 for ( size_t n = 0; n < count; n++ )
324 {
325 if ( keys->Item(n) == key )
326 {
f8305caf 327 keys->RemoveAt(n);
53e112a0
JS
328 m_values[slot]->RemoveAt(n);
329 return TRUE;
330 }
331 }
332 }
333
334 return FALSE;
335}
336
bcaa23de
VZ
337// ----------------------------------------------------------------------------
338// old not type safe wxHashTable
339// ----------------------------------------------------------------------------
340
debe6624 341wxHashTable::wxHashTable (int the_key_type, int size)
c801d85f 342{
17d8ee1c
JS
343 n = 0;
344 hash_table = (wxList**) NULL;
345 Create(the_key_type, size);
5692876f 346 m_count = 0;
c7fb814a 347 m_deleteContents = FALSE;
17d8ee1c 348/*
c801d85f
KB
349 n = size;
350 current_position = -1;
c67daf87 351 current_node = (wxNode *) NULL;
c801d85f
KB
352
353 key_type = the_key_type;
354 hash_table = new wxList *[size];
355 int i;
356 for (i = 0; i < size; i++)
c67daf87 357 hash_table[i] = (wxList *) NULL;
17d8ee1c 358*/
c801d85f
KB
359}
360
bcaa23de 361wxHashTable::~wxHashTable ()
c801d85f 362{
e55ad60e
RR
363 Destroy();
364}
365
bcaa23de 366void wxHashTable::Destroy()
e55ad60e
RR
367{
368 if (!hash_table) return;
c801d85f
KB
369 int i;
370 for (i = 0; i < n; i++)
371 if (hash_table[i])
372 delete hash_table[i];
373 delete[] hash_table;
e55ad60e 374 hash_table = NULL;
c801d85f
KB
375}
376
debe6624 377bool wxHashTable::Create(int the_key_type, int size)
c801d85f 378{
17d8ee1c
JS
379 Destroy();
380
c801d85f
KB
381 n = size;
382 current_position = -1;
c67daf87 383 current_node = (wxNode *) NULL;
c801d85f
KB
384
385 key_type = the_key_type;
c801d85f
KB
386 hash_table = new wxList *[size];
387 int i;
388 for (i = 0; i < size; i++)
c67daf87 389 hash_table[i] = (wxList *) NULL;
c801d85f
KB
390 return TRUE;
391}
392
4e67bfc7
VS
393
394void wxHashTable::DoCopy(const wxHashTable& table)
395{
396 n = table.n;
ea450825 397 m_count = table.m_count;
4e67bfc7
VS
398 current_position = table.current_position;
399 current_node = NULL; // doesn't matter - Next() will reconstruct it
400 key_type = table.key_type;
401
402 hash_table = new wxList *[n];
403 for (int i = 0; i < n; i++) {
404 if (table.hash_table[i] == NULL)
405 hash_table[i] = NULL;
406 else {
407 hash_table[i] = new wxList(key_type);
408 *(hash_table[i]) = *(table.hash_table[i]);
409 }
410 }
411}
412
debe6624 413void wxHashTable::Put (long key, long value, wxObject * object)
c801d85f
KB
414{
415 // Should NEVER be
416 long k = (long) key;
c801d85f
KB
417
418 int position = (int) (k % n);
ffae916f
BJ
419 if (position < 0) position = -position;
420
c801d85f 421 if (!hash_table[position])
c7fb814a 422 {
cbb26e3f 423 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
424 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
425 }
c801d85f
KB
426
427 hash_table[position]->Append (value, object);
5692876f 428 m_count++;
c801d85f
KB
429}
430
50920146 431void wxHashTable::Put (long key, const wxChar *value, wxObject * object)
c801d85f
KB
432{
433 // Should NEVER be
bcaa23de 434 long k = (long) key;
c801d85f
KB
435
436 int position = (int) (k % n);
ffae916f 437 if (position < 0) position = -position;
bcaa23de 438
c801d85f 439 if (!hash_table[position])
c7fb814a 440 {
cbb26e3f 441 hash_table[position] = new wxList (wxKEY_STRING);
c7fb814a
VS
442 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
443 }
c801d85f
KB
444
445 hash_table[position]->Append (value, object);
5692876f 446 m_count++;
c801d85f
KB
447}
448
debe6624 449void wxHashTable::Put (long key, wxObject * object)
c801d85f
KB
450{
451 // Should NEVER be
452 long k = (long) key;
bcaa23de 453
c801d85f 454 int position = (int) (k % n);
ffae916f
BJ
455 if (position < 0) position = -position;
456
c801d85f 457 if (!hash_table[position])
c7fb814a 458 {
c801d85f 459 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
460 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
461 }
bcaa23de 462
c801d85f 463 hash_table[position]->Append (k, object);
5692876f 464 m_count++;
c801d85f
KB
465}
466
50920146 467void wxHashTable::Put (const wxChar *key, wxObject * object)
c801d85f
KB
468{
469 int position = (int) (MakeKey (key) % n);
ffae916f 470 if (position < 0) position = -position;
c801d85f
KB
471
472 if (!hash_table[position])
c7fb814a 473 {
c801d85f 474 hash_table[position] = new wxList (wxKEY_STRING);
c7fb814a
VS
475 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
476 }
c801d85f
KB
477
478 hash_table[position]->Append (key, object);
5692876f 479 m_count++;
c801d85f
KB
480}
481
debe6624 482wxObject *wxHashTable::Get (long key, long value) const
c801d85f
KB
483{
484 // Should NEVER be
485 long k = (long) key;
c801d85f
KB
486
487 int position = (int) (k % n);
ffae916f
BJ
488 if (position < 0) position = -position;
489
c801d85f 490 if (!hash_table[position])
c67daf87 491 return (wxObject *) NULL;
c801d85f
KB
492 else
493 {
494 wxNode *node = hash_table[position]->Find (value);
495 if (node)
bcaa23de 496 return node->Data ();
c801d85f 497 else
bcaa23de 498 return (wxObject *) NULL;
c801d85f
KB
499 }
500}
501
50920146 502wxObject *wxHashTable::Get (long key, const wxChar *value) const
c801d85f
KB
503{
504 // Should NEVER be
505 long k = (long) key;
bcaa23de 506
c801d85f 507 int position = (int) (k % n);
ffae916f
BJ
508 if (position < 0) position = -position;
509
c801d85f 510 if (!hash_table[position])
c67daf87 511 return (wxObject *) NULL;
c801d85f
KB
512 else
513 {
514 wxNode *node = hash_table[position]->Find (value);
515 if (node)
bcaa23de 516 return node->Data ();
c801d85f 517 else
bcaa23de 518 return (wxObject *) NULL;
c801d85f
KB
519 }
520}
521
debe6624 522wxObject *wxHashTable::Get (long key) const
c801d85f
KB
523{
524 // Should NEVER be
525 long k = (long) key;
c801d85f
KB
526
527 int position = (int) (k % n);
ffae916f
BJ
528 if (position < 0) position = -position;
529
c801d85f 530 if (!hash_table[position])
c67daf87 531 return (wxObject *) NULL;
c801d85f
KB
532 else
533 {
534 wxNode *node = hash_table[position]->Find (k);
535 return node ? node->Data () : (wxObject*)NULL;
536 }
537}
538
50920146 539wxObject *wxHashTable::Get (const wxChar *key) const
c801d85f
KB
540{
541 int position = (int) (MakeKey (key) % n);
ffae916f 542 if (position < 0) position = -position;
c801d85f
KB
543
544 if (!hash_table[position])
c67daf87 545 return (wxObject *) NULL;
c801d85f
KB
546 else
547 {
548 wxNode *node = hash_table[position]->Find (key);
549 return node ? node->Data () : (wxObject*)NULL;
550 }
551}
552
debe6624 553wxObject *wxHashTable::Delete (long key)
c801d85f
KB
554{
555 // Should NEVER be
556 long k = (long) key;
c801d85f
KB
557
558 int position = (int) (k % n);
ffae916f
BJ
559 if (position < 0) position = -position;
560
c801d85f 561 if (!hash_table[position])
c67daf87 562 return (wxObject *) NULL;
c801d85f
KB
563 else
564 {
565 wxNode *node = hash_table[position]->Find (k);
566 if (node)
bcaa23de
VZ
567 {
568 wxObject *data = node->Data ();
569 delete node;
570 m_count--;
571 return data;
572 }
c801d85f 573 else
bcaa23de 574 return (wxObject *) NULL;
c801d85f
KB
575 }
576}
577
50920146 578wxObject *wxHashTable::Delete (const wxChar *key)
c801d85f
KB
579{
580 int position = (int) (MakeKey (key) % n);
ffae916f
BJ
581 if (position < 0) position = -position;
582
c801d85f 583 if (!hash_table[position])
c67daf87 584 return (wxObject *) NULL;
c801d85f
KB
585 else
586 {
587 wxNode *node = hash_table[position]->Find (key);
588 if (node)
bcaa23de
VZ
589 {
590 wxObject *data = node->Data ();
591 delete node;
592 m_count--;
593 return data;
594 }
c801d85f 595 else
bcaa23de 596 return (wxObject *) NULL;
c801d85f
KB
597 }
598}
599
debe6624 600wxObject *wxHashTable::Delete (long key, int value)
c801d85f
KB
601{
602 // Should NEVER be
bcaa23de 603 long k = (long) key;
c801d85f
KB
604
605 int position = (int) (k % n);
ffae916f
BJ
606 if (position < 0) position = -position;
607
c801d85f 608 if (!hash_table[position])
c67daf87 609 return (wxObject *) NULL;
c801d85f
KB
610 else
611 {
612 wxNode *node = hash_table[position]->Find (value);
613 if (node)
bcaa23de
VZ
614 {
615 wxObject *data = node->Data ();
616 delete node;
617 m_count--;
618 return data;
619 }
c801d85f 620 else
bcaa23de 621 return (wxObject *) NULL;
c801d85f
KB
622 }
623}
624
50920146 625wxObject *wxHashTable::Delete (long key, const wxChar *value)
c801d85f
KB
626{
627 int position = (int) (key % n);
ffae916f
BJ
628 if (position < 0) position = -position;
629
c801d85f 630 if (!hash_table[position])
c67daf87 631 return (wxObject *) NULL;
c801d85f
KB
632 else
633 {
634 wxNode *node = hash_table[position]->Find (value);
635 if (node)
bcaa23de
VZ
636 {
637 wxObject *data = node->Data ();
638 delete node;
639 m_count--;
640 return data;
641 }
c801d85f 642 else
bcaa23de 643 return (wxObject *) NULL;
c801d85f
KB
644 }
645}
646
50920146 647long wxHashTable::MakeKey (const wxChar *string) const
c801d85f
KB
648{
649 long int_key = 0;
650
651 while (*string)
50920146 652 int_key += (wxUChar) *string++;
c801d85f
KB
653
654 return int_key;
655}
656
bcaa23de 657void wxHashTable::BeginFind ()
c801d85f
KB
658{
659 current_position = -1;
c67daf87 660 current_node = (wxNode *) NULL;
c801d85f
KB
661}
662
bcaa23de 663wxNode *wxHashTable::Next ()
c801d85f 664{
c67daf87 665 wxNode *found = (wxNode *) NULL;
c801d85f
KB
666 bool end = FALSE;
667 while (!end && !found)
668 {
669 if (!current_node)
bcaa23de
VZ
670 {
671 current_position++;
672 if (current_position >= n)
673 {
674 current_position = -1;
675 current_node = (wxNode *) NULL;
676 end = TRUE;
677 }
678 else
679 {
680 if (hash_table[current_position])
681 {
682 current_node = hash_table[current_position]->First ();
683 found = current_node;
684 }
685 }
686 }
c801d85f 687 else
bcaa23de
VZ
688 {
689 current_node = current_node->Next ();
690 found = current_node;
691 }
c801d85f
KB
692 }
693 return found;
694}
695
debe6624 696void wxHashTable::DeleteContents (bool flag)
c801d85f
KB
697{
698 int i;
c7fb814a 699 m_deleteContents = flag;
c801d85f
KB
700 for (i = 0; i < n; i++)
701 {
702 if (hash_table[i])
bcaa23de 703 hash_table[i]->DeleteContents (flag);
c801d85f
KB
704 }
705}
706
bcaa23de 707void wxHashTable::Clear ()
c801d85f 708{
19230604
RD
709 int i;
710 if (hash_table)
c801d85f 711 {
19230604
RD
712 for (i = 0; i < n; i++)
713 {
714 if (hash_table[i])
715 hash_table[i]->Clear ();
716 }
c801d85f 717 }
5692876f 718 m_count = 0;
c801d85f
KB
719}
720