]>
Commit | Line | Data |
---|---|---|
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 | 41 | IMPLEMENT_DYNAMIC_CLASS(wxHashTable, wxObject) |
c801d85f | 42 | |
bcaa23de VZ |
43 | // ============================================================================ |
44 | // implementation | |
45 | // ============================================================================ | |
46 | ||
47 | // ---------------------------------------------------------------------------- | |
48 | // wxHashTablleBase for working with "void *" data | |
49 | // ---------------------------------------------------------------------------- | |
50 | ||
51 | wxHashTableBase::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 | ||
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 | { | |
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 |
125 | wxHashTableLong::~wxHashTableLong() |
126 | { | |
127 | Destroy(); | |
128 | } | |
129 | ||
c2bb85e9 VZ |
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 | ||
b7aaabf8 VS |
145 | void wxHashTableLong::Create(size_t size) |
146 | { | |
147 | Init(size); | |
148 | } | |
149 | ||
c2bb85e9 VZ |
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 | ||
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 | ||
182 | long 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 | ||
204 | long 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 | ||
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 | { | |
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 |
312 | bool 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 | 342 | wxHashTable::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 | 362 | wxHashTable::~wxHashTable () |
c801d85f | 363 | { |
e55ad60e RR |
364 | Destroy(); |
365 | } | |
366 | ||
bcaa23de | 367 | void 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 | 378 | bool 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 | |
395 | void 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 | 414 | void 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 | 432 | void 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 | 450 | void 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 | 468 | void 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 | 483 | wxObject *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 | 503 | wxObject *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 | 523 | wxObject *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 | 540 | wxObject *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 | 554 | wxObject *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 | 579 | wxObject *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 | 601 | wxObject *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 | 626 | wxObject *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 | 648 | long 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 | 658 | void wxHashTable::BeginFind () |
c801d85f KB |
659 | { |
660 | current_position = -1; | |
c67daf87 | 661 | current_node = (wxNode *) NULL; |
c801d85f KB |
662 | } |
663 | ||
1a6d9c76 | 664 | wxHashTable::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 | 697 | void 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 | 708 | void 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 | |
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 | ||
1a6d9c76 MB |
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; | |
f803b25b | 806 | prev = curr, curr = curr->GetNext() ) ; |
1a6d9c76 MB |
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 | ||
2441fb44 VZ |
1016 | // ---------------------------------------------------------------------------- |
1017 | // wxHashTable | |
1018 | // ---------------------------------------------------------------------------- | |
1a6d9c76 MB |
1019 | |
1020 | wxHashTable::wxHashTable( const wxHashTable& table ) | |
2441fb44 | 1021 | : wxHashTableBase() |
1a6d9c76 MB |
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 | ||
6aa33060 | 1034 | void wxHashTable::DoCopy( const wxHashTable& WXUNUSED(table) ) |
1a6d9c76 MB |
1035 | { |
1036 | Create( m_keyType, m_size ); | |
1037 | ||
7cb32b4b | 1038 | wxFAIL; |
1a6d9c76 MB |
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 | ||
6e86701b | 1077 | #endif // !wxUSE_OLD_HASH_TABLE |