]> git.saurik.com Git - wxWidgets.git/blame - src/common/hash.cpp
fixed bug with Broadcast() not waking up all threads (Pieter van der Meulen)
[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
146void wxHashTableLong::Destroy()
147{
148 for ( size_t n = 0; n < m_hashSize; n++ )
149 {
150 delete m_values[n];
151 delete m_keys[n];
152 }
153
154 delete [] m_values;
155 delete [] m_keys;
156 m_hashSize = 0;
157 m_count = 0;
158}
159
160void wxHashTableLong::Put(long key, long value)
161{
162 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
163
3ca6a5f0 164 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
165
166 if ( !m_keys[slot] )
167 {
168 m_keys[slot] = new wxArrayLong;
169 m_values[slot] = new wxArrayLong;
170 }
171
172 m_keys[slot]->Add(key);
173 m_values[slot]->Add(value);
174
175 m_count++;
176}
177
178long wxHashTableLong::Get(long key) const
179{
180 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
181
3ca6a5f0 182 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
183
184 wxArrayLong *keys = m_keys[slot];
185 if ( keys )
186 {
187 size_t count = keys->GetCount();
188 for ( size_t n = 0; n < count; n++ )
189 {
190 if ( keys->Item(n) == key )
191 {
192 return m_values[slot]->Item(n);
193 }
194 }
195 }
196
197 return wxNOT_FOUND;
198}
199
200long wxHashTableLong::Delete(long key)
201{
202 wxCHECK_MSG( m_hashSize, wxNOT_FOUND, _T("must call Create() first") );
203
3ca6a5f0 204 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
c2bb85e9
VZ
205
206 wxArrayLong *keys = m_keys[slot];
207 if ( keys )
208 {
209 size_t count = keys->GetCount();
210 for ( size_t n = 0; n < count; n++ )
211 {
212 if ( keys->Item(n) == key )
213 {
214 long val = m_values[slot]->Item(n);
215
216 keys->RemoveAt(n);
217 m_values[slot]->RemoveAt(n);
218
219 m_count--;
220
221 return val;
222 }
223 }
224 }
225
226 return wxNOT_FOUND;
227}
228
bd83cb56
VZ
229// ----------------------------------------------------------------------------
230// wxStringHashTable: more efficient than storing strings in a list
231// ----------------------------------------------------------------------------
232
233wxStringHashTable::wxStringHashTable(size_t sizeTable)
234{
235 m_keys = new wxArrayLong *[sizeTable];
236 m_values = new wxArrayString *[sizeTable];
237
238 m_hashSize = sizeTable;
239 for ( size_t n = 0; n < m_hashSize; n++ )
240 {
241 m_values[n] = (wxArrayString *)NULL;
242 m_keys[n] = (wxArrayLong *)NULL;
243 }
244}
245
246wxStringHashTable::~wxStringHashTable()
247{
248 Destroy();
249}
250
251void wxStringHashTable::Destroy()
252{
253 for ( size_t n = 0; n < m_hashSize; n++ )
254 {
255 delete m_values[n];
256 delete m_keys[n];
257 }
258
259 delete [] m_values;
260 delete [] m_keys;
261 m_hashSize = 0;
262}
263
264void wxStringHashTable::Put(long key, const wxString& value)
265{
266 wxCHECK_RET( m_hashSize, _T("must call Create() first") );
267
268 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
269
270 if ( !m_keys[slot] )
271 {
272 m_keys[slot] = new wxArrayLong;
273 m_values[slot] = new wxArrayString;
274 }
275
276 m_keys[slot]->Add(key);
277 m_values[slot]->Add(value);
278}
279
280wxString wxStringHashTable::Get(long key, bool *wasFound) const
281{
282 wxCHECK_MSG( m_hashSize, _T(""), _T("must call Create() first") );
283
284 size_t slot = (size_t)abs((int)(key % (long)m_hashSize));
285
286 wxArrayLong *keys = m_keys[slot];
287 if ( keys )
288 {
289 size_t count = keys->GetCount();
290 for ( size_t n = 0; n < count; n++ )
291 {
292 if ( keys->Item(n) == key )
293 {
294 if ( wasFound )
295 *wasFound = TRUE;
296
297 return m_values[slot]->Item(n);
298 }
299 }
300 }
301
302 if ( wasFound )
303 *wasFound = FALSE;
304
305 return _T("");
306}
307
bcaa23de
VZ
308// ----------------------------------------------------------------------------
309// old not type safe wxHashTable
310// ----------------------------------------------------------------------------
311
debe6624 312wxHashTable::wxHashTable (int the_key_type, int size)
c801d85f 313{
17d8ee1c
JS
314 n = 0;
315 hash_table = (wxList**) NULL;
316 Create(the_key_type, size);
5692876f 317 m_count = 0;
c7fb814a 318 m_deleteContents = FALSE;
17d8ee1c 319/*
c801d85f
KB
320 n = size;
321 current_position = -1;
c67daf87 322 current_node = (wxNode *) NULL;
c801d85f
KB
323
324 key_type = the_key_type;
325 hash_table = new wxList *[size];
326 int i;
327 for (i = 0; i < size; i++)
c67daf87 328 hash_table[i] = (wxList *) NULL;
17d8ee1c 329*/
c801d85f
KB
330}
331
bcaa23de 332wxHashTable::~wxHashTable ()
c801d85f 333{
e55ad60e
RR
334 Destroy();
335}
336
bcaa23de 337void wxHashTable::Destroy()
e55ad60e
RR
338{
339 if (!hash_table) return;
c801d85f
KB
340 int i;
341 for (i = 0; i < n; i++)
342 if (hash_table[i])
343 delete hash_table[i];
344 delete[] hash_table;
e55ad60e 345 hash_table = NULL;
c801d85f
KB
346}
347
debe6624 348bool wxHashTable::Create(int the_key_type, int size)
c801d85f 349{
17d8ee1c
JS
350 Destroy();
351
c801d85f
KB
352 n = size;
353 current_position = -1;
c67daf87 354 current_node = (wxNode *) NULL;
c801d85f
KB
355
356 key_type = the_key_type;
c801d85f
KB
357 hash_table = new wxList *[size];
358 int i;
359 for (i = 0; i < size; i++)
c67daf87 360 hash_table[i] = (wxList *) NULL;
c801d85f
KB
361 return TRUE;
362}
363
4e67bfc7
VS
364
365void wxHashTable::DoCopy(const wxHashTable& table)
366{
367 n = table.n;
368 current_position = table.current_position;
369 current_node = NULL; // doesn't matter - Next() will reconstruct it
370 key_type = table.key_type;
371
372 hash_table = new wxList *[n];
373 for (int i = 0; i < n; i++) {
374 if (table.hash_table[i] == NULL)
375 hash_table[i] = NULL;
376 else {
377 hash_table[i] = new wxList(key_type);
378 *(hash_table[i]) = *(table.hash_table[i]);
379 }
380 }
381}
382
debe6624 383void wxHashTable::Put (long key, long value, wxObject * object)
c801d85f
KB
384{
385 // Should NEVER be
386 long k = (long) key;
c801d85f
KB
387
388 int position = (int) (k % n);
ffae916f
BJ
389 if (position < 0) position = -position;
390
c801d85f 391 if (!hash_table[position])
c7fb814a 392 {
c801d85f 393 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
394 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
395 }
c801d85f
KB
396
397 hash_table[position]->Append (value, object);
5692876f 398 m_count++;
c801d85f
KB
399}
400
50920146 401void wxHashTable::Put (long key, const wxChar *value, wxObject * object)
c801d85f
KB
402{
403 // Should NEVER be
bcaa23de 404 long k = (long) key;
c801d85f
KB
405
406 int position = (int) (k % n);
ffae916f 407 if (position < 0) position = -position;
bcaa23de 408
c801d85f 409 if (!hash_table[position])
c7fb814a 410 {
c801d85f 411 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
412 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
413 }
c801d85f
KB
414
415 hash_table[position]->Append (value, object);
5692876f 416 m_count++;
c801d85f
KB
417}
418
debe6624 419void wxHashTable::Put (long key, wxObject * object)
c801d85f
KB
420{
421 // Should NEVER be
422 long k = (long) key;
bcaa23de 423
c801d85f 424 int position = (int) (k % n);
ffae916f
BJ
425 if (position < 0) position = -position;
426
c801d85f 427 if (!hash_table[position])
c7fb814a 428 {
c801d85f 429 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
430 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
431 }
bcaa23de 432
c801d85f 433 hash_table[position]->Append (k, object);
5692876f 434 m_count++;
c801d85f
KB
435}
436
50920146 437void wxHashTable::Put (const wxChar *key, wxObject * object)
c801d85f
KB
438{
439 int position = (int) (MakeKey (key) % n);
ffae916f 440 if (position < 0) position = -position;
c801d85f
KB
441
442 if (!hash_table[position])
c7fb814a 443 {
c801d85f 444 hash_table[position] = new wxList (wxKEY_STRING);
c7fb814a
VS
445 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
446 }
c801d85f
KB
447
448 hash_table[position]->Append (key, object);
5692876f 449 m_count++;
c801d85f
KB
450}
451
debe6624 452wxObject *wxHashTable::Get (long key, long value) const
c801d85f
KB
453{
454 // Should NEVER be
455 long k = (long) key;
c801d85f
KB
456
457 int position = (int) (k % n);
ffae916f
BJ
458 if (position < 0) position = -position;
459
c801d85f 460 if (!hash_table[position])
c67daf87 461 return (wxObject *) NULL;
c801d85f
KB
462 else
463 {
464 wxNode *node = hash_table[position]->Find (value);
465 if (node)
bcaa23de 466 return node->Data ();
c801d85f 467 else
bcaa23de 468 return (wxObject *) NULL;
c801d85f
KB
469 }
470}
471
50920146 472wxObject *wxHashTable::Get (long key, const wxChar *value) const
c801d85f
KB
473{
474 // Should NEVER be
475 long k = (long) key;
bcaa23de 476
c801d85f 477 int position = (int) (k % n);
ffae916f
BJ
478 if (position < 0) position = -position;
479
c801d85f 480 if (!hash_table[position])
c67daf87 481 return (wxObject *) NULL;
c801d85f
KB
482 else
483 {
484 wxNode *node = hash_table[position]->Find (value);
485 if (node)
bcaa23de 486 return node->Data ();
c801d85f 487 else
bcaa23de 488 return (wxObject *) NULL;
c801d85f
KB
489 }
490}
491
debe6624 492wxObject *wxHashTable::Get (long key) const
c801d85f
KB
493{
494 // Should NEVER be
495 long k = (long) key;
c801d85f
KB
496
497 int position = (int) (k % n);
ffae916f
BJ
498 if (position < 0) position = -position;
499
c801d85f 500 if (!hash_table[position])
c67daf87 501 return (wxObject *) NULL;
c801d85f
KB
502 else
503 {
504 wxNode *node = hash_table[position]->Find (k);
505 return node ? node->Data () : (wxObject*)NULL;
506 }
507}
508
50920146 509wxObject *wxHashTable::Get (const wxChar *key) const
c801d85f
KB
510{
511 int position = (int) (MakeKey (key) % n);
ffae916f 512 if (position < 0) position = -position;
c801d85f
KB
513
514 if (!hash_table[position])
c67daf87 515 return (wxObject *) NULL;
c801d85f
KB
516 else
517 {
518 wxNode *node = hash_table[position]->Find (key);
519 return node ? node->Data () : (wxObject*)NULL;
520 }
521}
522
debe6624 523wxObject *wxHashTable::Delete (long key)
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);
536 if (node)
bcaa23de
VZ
537 {
538 wxObject *data = node->Data ();
539 delete node;
540 m_count--;
541 return data;
542 }
c801d85f 543 else
bcaa23de 544 return (wxObject *) NULL;
c801d85f
KB
545 }
546}
547
50920146 548wxObject *wxHashTable::Delete (const wxChar *key)
c801d85f
KB
549{
550 int position = (int) (MakeKey (key) % n);
ffae916f
BJ
551 if (position < 0) position = -position;
552
c801d85f 553 if (!hash_table[position])
c67daf87 554 return (wxObject *) NULL;
c801d85f
KB
555 else
556 {
557 wxNode *node = hash_table[position]->Find (key);
558 if (node)
bcaa23de
VZ
559 {
560 wxObject *data = node->Data ();
561 delete node;
562 m_count--;
563 return data;
564 }
c801d85f 565 else
bcaa23de 566 return (wxObject *) NULL;
c801d85f
KB
567 }
568}
569
debe6624 570wxObject *wxHashTable::Delete (long key, int value)
c801d85f
KB
571{
572 // Should NEVER be
bcaa23de 573 long k = (long) key;
c801d85f
KB
574
575 int position = (int) (k % n);
ffae916f
BJ
576 if (position < 0) position = -position;
577
c801d85f 578 if (!hash_table[position])
c67daf87 579 return (wxObject *) NULL;
c801d85f
KB
580 else
581 {
582 wxNode *node = hash_table[position]->Find (value);
583 if (node)
bcaa23de
VZ
584 {
585 wxObject *data = node->Data ();
586 delete node;
587 m_count--;
588 return data;
589 }
c801d85f 590 else
bcaa23de 591 return (wxObject *) NULL;
c801d85f
KB
592 }
593}
594
50920146 595wxObject *wxHashTable::Delete (long key, const wxChar *value)
c801d85f
KB
596{
597 int position = (int) (key % n);
ffae916f
BJ
598 if (position < 0) position = -position;
599
c801d85f 600 if (!hash_table[position])
c67daf87 601 return (wxObject *) NULL;
c801d85f
KB
602 else
603 {
604 wxNode *node = hash_table[position]->Find (value);
605 if (node)
bcaa23de
VZ
606 {
607 wxObject *data = node->Data ();
608 delete node;
609 m_count--;
610 return data;
611 }
c801d85f 612 else
bcaa23de 613 return (wxObject *) NULL;
c801d85f
KB
614 }
615}
616
50920146 617long wxHashTable::MakeKey (const wxChar *string) const
c801d85f
KB
618{
619 long int_key = 0;
620
621 while (*string)
50920146 622 int_key += (wxUChar) *string++;
c801d85f
KB
623
624 return int_key;
625}
626
bcaa23de 627void wxHashTable::BeginFind ()
c801d85f
KB
628{
629 current_position = -1;
c67daf87 630 current_node = (wxNode *) NULL;
c801d85f
KB
631}
632
bcaa23de 633wxNode *wxHashTable::Next ()
c801d85f 634{
c67daf87 635 wxNode *found = (wxNode *) NULL;
c801d85f
KB
636 bool end = FALSE;
637 while (!end && !found)
638 {
639 if (!current_node)
bcaa23de
VZ
640 {
641 current_position++;
642 if (current_position >= n)
643 {
644 current_position = -1;
645 current_node = (wxNode *) NULL;
646 end = TRUE;
647 }
648 else
649 {
650 if (hash_table[current_position])
651 {
652 current_node = hash_table[current_position]->First ();
653 found = current_node;
654 }
655 }
656 }
c801d85f 657 else
bcaa23de
VZ
658 {
659 current_node = current_node->Next ();
660 found = current_node;
661 }
c801d85f
KB
662 }
663 return found;
664}
665
debe6624 666void wxHashTable::DeleteContents (bool flag)
c801d85f
KB
667{
668 int i;
c7fb814a 669 m_deleteContents = flag;
c801d85f
KB
670 for (i = 0; i < n; i++)
671 {
672 if (hash_table[i])
bcaa23de 673 hash_table[i]->DeleteContents (flag);
c801d85f
KB
674 }
675}
676
bcaa23de 677void wxHashTable::Clear ()
c801d85f
KB
678{
679 int i;
680 for (i = 0; i < n; i++)
681 {
682 if (hash_table[i])
bcaa23de 683 hash_table[i]->Clear ();
c801d85f 684 }
5692876f 685 m_count = 0;
c801d85f
KB
686}
687