]> git.saurik.com Git - wxWidgets.git/blame - src/common/hash.cpp
Added chapter on collection and container classes to contents
[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
bcaa23de
VZ
229// ----------------------------------------------------------------------------
230// old not type safe wxHashTable
231// ----------------------------------------------------------------------------
232
debe6624 233wxHashTable::wxHashTable (int the_key_type, int size)
c801d85f 234{
17d8ee1c
JS
235 n = 0;
236 hash_table = (wxList**) NULL;
237 Create(the_key_type, size);
5692876f 238 m_count = 0;
c7fb814a 239 m_deleteContents = FALSE;
17d8ee1c 240/*
c801d85f
KB
241 n = size;
242 current_position = -1;
c67daf87 243 current_node = (wxNode *) NULL;
c801d85f
KB
244
245 key_type = the_key_type;
246 hash_table = new wxList *[size];
247 int i;
248 for (i = 0; i < size; i++)
c67daf87 249 hash_table[i] = (wxList *) NULL;
17d8ee1c 250*/
c801d85f
KB
251}
252
bcaa23de 253wxHashTable::~wxHashTable ()
c801d85f 254{
e55ad60e
RR
255 Destroy();
256}
257
bcaa23de 258void wxHashTable::Destroy()
e55ad60e
RR
259{
260 if (!hash_table) return;
c801d85f
KB
261 int i;
262 for (i = 0; i < n; i++)
263 if (hash_table[i])
264 delete hash_table[i];
265 delete[] hash_table;
e55ad60e 266 hash_table = NULL;
c801d85f
KB
267}
268
debe6624 269bool wxHashTable::Create(int the_key_type, int size)
c801d85f 270{
17d8ee1c
JS
271 Destroy();
272
c801d85f
KB
273 n = size;
274 current_position = -1;
c67daf87 275 current_node = (wxNode *) NULL;
c801d85f
KB
276
277 key_type = the_key_type;
c801d85f
KB
278 hash_table = new wxList *[size];
279 int i;
280 for (i = 0; i < size; i++)
c67daf87 281 hash_table[i] = (wxList *) NULL;
c801d85f
KB
282 return TRUE;
283}
284
4e67bfc7
VS
285
286void wxHashTable::DoCopy(const wxHashTable& table)
287{
288 n = table.n;
289 current_position = table.current_position;
290 current_node = NULL; // doesn't matter - Next() will reconstruct it
291 key_type = table.key_type;
292
293 hash_table = new wxList *[n];
294 for (int i = 0; i < n; i++) {
295 if (table.hash_table[i] == NULL)
296 hash_table[i] = NULL;
297 else {
298 hash_table[i] = new wxList(key_type);
299 *(hash_table[i]) = *(table.hash_table[i]);
300 }
301 }
302}
303
debe6624 304void wxHashTable::Put (long key, long value, wxObject * object)
c801d85f
KB
305{
306 // Should NEVER be
307 long k = (long) key;
c801d85f
KB
308
309 int position = (int) (k % n);
ffae916f
BJ
310 if (position < 0) position = -position;
311
c801d85f 312 if (!hash_table[position])
c7fb814a 313 {
c801d85f 314 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
315 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
316 }
c801d85f
KB
317
318 hash_table[position]->Append (value, object);
5692876f 319 m_count++;
c801d85f
KB
320}
321
50920146 322void wxHashTable::Put (long key, const wxChar *value, wxObject * object)
c801d85f
KB
323{
324 // Should NEVER be
bcaa23de 325 long k = (long) key;
c801d85f
KB
326
327 int position = (int) (k % n);
ffae916f 328 if (position < 0) position = -position;
bcaa23de 329
c801d85f 330 if (!hash_table[position])
c7fb814a 331 {
c801d85f 332 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
333 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
334 }
c801d85f
KB
335
336 hash_table[position]->Append (value, object);
5692876f 337 m_count++;
c801d85f
KB
338}
339
debe6624 340void wxHashTable::Put (long key, wxObject * object)
c801d85f
KB
341{
342 // Should NEVER be
343 long k = (long) key;
bcaa23de 344
c801d85f 345 int position = (int) (k % n);
ffae916f
BJ
346 if (position < 0) position = -position;
347
c801d85f 348 if (!hash_table[position])
c7fb814a 349 {
c801d85f 350 hash_table[position] = new wxList (wxKEY_INTEGER);
c7fb814a
VS
351 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
352 }
bcaa23de 353
c801d85f 354 hash_table[position]->Append (k, object);
5692876f 355 m_count++;
c801d85f
KB
356}
357
50920146 358void wxHashTable::Put (const wxChar *key, wxObject * object)
c801d85f
KB
359{
360 int position = (int) (MakeKey (key) % n);
ffae916f 361 if (position < 0) position = -position;
c801d85f
KB
362
363 if (!hash_table[position])
c7fb814a 364 {
c801d85f 365 hash_table[position] = new wxList (wxKEY_STRING);
c7fb814a
VS
366 if (m_deleteContents) hash_table[position]->DeleteContents(TRUE);
367 }
c801d85f
KB
368
369 hash_table[position]->Append (key, object);
5692876f 370 m_count++;
c801d85f
KB
371}
372
debe6624 373wxObject *wxHashTable::Get (long key, long value) const
c801d85f
KB
374{
375 // Should NEVER be
376 long k = (long) key;
c801d85f
KB
377
378 int position = (int) (k % n);
ffae916f
BJ
379 if (position < 0) position = -position;
380
c801d85f 381 if (!hash_table[position])
c67daf87 382 return (wxObject *) NULL;
c801d85f
KB
383 else
384 {
385 wxNode *node = hash_table[position]->Find (value);
386 if (node)
bcaa23de 387 return node->Data ();
c801d85f 388 else
bcaa23de 389 return (wxObject *) NULL;
c801d85f
KB
390 }
391}
392
50920146 393wxObject *wxHashTable::Get (long key, const wxChar *value) const
c801d85f
KB
394{
395 // Should NEVER be
396 long k = (long) key;
bcaa23de 397
c801d85f 398 int position = (int) (k % n);
ffae916f
BJ
399 if (position < 0) position = -position;
400
c801d85f 401 if (!hash_table[position])
c67daf87 402 return (wxObject *) NULL;
c801d85f
KB
403 else
404 {
405 wxNode *node = hash_table[position]->Find (value);
406 if (node)
bcaa23de 407 return node->Data ();
c801d85f 408 else
bcaa23de 409 return (wxObject *) NULL;
c801d85f
KB
410 }
411}
412
debe6624 413wxObject *wxHashTable::Get (long key) const
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])
c67daf87 422 return (wxObject *) NULL;
c801d85f
KB
423 else
424 {
425 wxNode *node = hash_table[position]->Find (k);
426 return node ? node->Data () : (wxObject*)NULL;
427 }
428}
429
50920146 430wxObject *wxHashTable::Get (const wxChar *key) const
c801d85f
KB
431{
432 int position = (int) (MakeKey (key) % n);
ffae916f 433 if (position < 0) position = -position;
c801d85f
KB
434
435 if (!hash_table[position])
c67daf87 436 return (wxObject *) NULL;
c801d85f
KB
437 else
438 {
439 wxNode *node = hash_table[position]->Find (key);
440 return node ? node->Data () : (wxObject*)NULL;
441 }
442}
443
debe6624 444wxObject *wxHashTable::Delete (long key)
c801d85f
KB
445{
446 // Should NEVER be
447 long k = (long) key;
c801d85f
KB
448
449 int position = (int) (k % n);
ffae916f
BJ
450 if (position < 0) position = -position;
451
c801d85f 452 if (!hash_table[position])
c67daf87 453 return (wxObject *) NULL;
c801d85f
KB
454 else
455 {
456 wxNode *node = hash_table[position]->Find (k);
457 if (node)
bcaa23de
VZ
458 {
459 wxObject *data = node->Data ();
460 delete node;
461 m_count--;
462 return data;
463 }
c801d85f 464 else
bcaa23de 465 return (wxObject *) NULL;
c801d85f
KB
466 }
467}
468
50920146 469wxObject *wxHashTable::Delete (const wxChar *key)
c801d85f
KB
470{
471 int position = (int) (MakeKey (key) % n);
ffae916f
BJ
472 if (position < 0) position = -position;
473
c801d85f 474 if (!hash_table[position])
c67daf87 475 return (wxObject *) NULL;
c801d85f
KB
476 else
477 {
478 wxNode *node = hash_table[position]->Find (key);
479 if (node)
bcaa23de
VZ
480 {
481 wxObject *data = node->Data ();
482 delete node;
483 m_count--;
484 return data;
485 }
c801d85f 486 else
bcaa23de 487 return (wxObject *) NULL;
c801d85f
KB
488 }
489}
490
debe6624 491wxObject *wxHashTable::Delete (long key, int value)
c801d85f
KB
492{
493 // Should NEVER be
bcaa23de 494 long k = (long) key;
c801d85f
KB
495
496 int position = (int) (k % n);
ffae916f
BJ
497 if (position < 0) position = -position;
498
c801d85f 499 if (!hash_table[position])
c67daf87 500 return (wxObject *) NULL;
c801d85f
KB
501 else
502 {
503 wxNode *node = hash_table[position]->Find (value);
504 if (node)
bcaa23de
VZ
505 {
506 wxObject *data = node->Data ();
507 delete node;
508 m_count--;
509 return data;
510 }
c801d85f 511 else
bcaa23de 512 return (wxObject *) NULL;
c801d85f
KB
513 }
514}
515
50920146 516wxObject *wxHashTable::Delete (long key, const wxChar *value)
c801d85f
KB
517{
518 int position = (int) (key % n);
ffae916f
BJ
519 if (position < 0) position = -position;
520
c801d85f 521 if (!hash_table[position])
c67daf87 522 return (wxObject *) NULL;
c801d85f
KB
523 else
524 {
525 wxNode *node = hash_table[position]->Find (value);
526 if (node)
bcaa23de
VZ
527 {
528 wxObject *data = node->Data ();
529 delete node;
530 m_count--;
531 return data;
532 }
c801d85f 533 else
bcaa23de 534 return (wxObject *) NULL;
c801d85f
KB
535 }
536}
537
50920146 538long wxHashTable::MakeKey (const wxChar *string) const
c801d85f
KB
539{
540 long int_key = 0;
541
542 while (*string)
50920146 543 int_key += (wxUChar) *string++;
c801d85f
KB
544
545 return int_key;
546}
547
bcaa23de 548void wxHashTable::BeginFind ()
c801d85f
KB
549{
550 current_position = -1;
c67daf87 551 current_node = (wxNode *) NULL;
c801d85f
KB
552}
553
bcaa23de 554wxNode *wxHashTable::Next ()
c801d85f 555{
c67daf87 556 wxNode *found = (wxNode *) NULL;
c801d85f
KB
557 bool end = FALSE;
558 while (!end && !found)
559 {
560 if (!current_node)
bcaa23de
VZ
561 {
562 current_position++;
563 if (current_position >= n)
564 {
565 current_position = -1;
566 current_node = (wxNode *) NULL;
567 end = TRUE;
568 }
569 else
570 {
571 if (hash_table[current_position])
572 {
573 current_node = hash_table[current_position]->First ();
574 found = current_node;
575 }
576 }
577 }
c801d85f 578 else
bcaa23de
VZ
579 {
580 current_node = current_node->Next ();
581 found = current_node;
582 }
c801d85f
KB
583 }
584 return found;
585}
586
debe6624 587void wxHashTable::DeleteContents (bool flag)
c801d85f
KB
588{
589 int i;
c7fb814a 590 m_deleteContents = flag;
c801d85f
KB
591 for (i = 0; i < n; i++)
592 {
593 if (hash_table[i])
bcaa23de 594 hash_table[i]->DeleteContents (flag);
c801d85f
KB
595 }
596}
597
bcaa23de 598void wxHashTable::Clear ()
c801d85f
KB
599{
600 int i;
601 for (i = 0; i < n; i++)
602 {
603 if (hash_table[i])
bcaa23de 604 hash_table[i]->Clear ();
c801d85f 605 }
5692876f 606 m_count = 0;
c801d85f
KB
607}
608