]> git.saurik.com Git - wxWidgets.git/blame - src/common/hash.cpp
Upgrade bundled zlib to 1.2.8.
[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 6// Created: 01/02/97
55d99c7a 7// Copyright: (c) Julian Smart
65571936 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
bcaa23de
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
c801d85f
KB
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
8ecff181 23 #pragma hdrstop
c801d85f
KB
24#endif
25
26#ifndef WX_PRECOMP
32d4c30a 27 #include "wx/hash.h"
1436bf0b 28 #include "wx/object.h"
c801d85f
KB
29#endif
30
1a6d9c76
MB
31wxHashTableBase_Node::wxHashTableBase_Node( long key, void* value,
32 wxHashTableBase* table )
33 : m_value( value ), m_hashPtr( table )
34{
35 m_key.integer = key;
36}
37
0518029c 38wxHashTableBase_Node::wxHashTableBase_Node( const wxString& key, void* value,
1a6d9c76
MB
39 wxHashTableBase* table )
40 : m_value( value ), m_hashPtr( table )
41{
0518029c 42 m_key.string = new wxString(key);
1a6d9c76
MB
43}
44
45wxHashTableBase_Node::~wxHashTableBase_Node()
46{
47 if( m_hashPtr ) m_hashPtr->DoRemoveNode( this );
48}
49
50//
51
52wxHashTableBase::wxHashTableBase()
53 : m_size( 0 ), m_count( 0 ), m_table( NULL ), m_keyType( wxKEY_NONE ),
54 m_deleteContents( false )
55{
56}
57
1a6d9c76
MB
58void wxHashTableBase::Create( wxKeyType keyType, size_t size )
59{
60 m_keyType = keyType;
61 m_size = size;
62 m_table = new wxHashTableBase_Node*[ m_size ];
63
64 for( size_t i = 0; i < m_size; ++i )
65 m_table[i] = NULL;
66}
67
68void wxHashTableBase::Clear()
69{
70 for( size_t i = 0; i < m_size; ++i )
71 {
72 Node* end = m_table[i];
73
74 if( end == NULL )
75 continue;
76
77 Node *curr, *next = end->GetNext();
78
79 do
80 {
81 curr = next;
82 next = curr->GetNext();
83
84 DoDestroyNode( curr );
85
86 delete curr;
87 }
88 while( curr != end );
89
90 m_table[i] = NULL;
91 }
92
93 m_count = 0;
94}
95
96void wxHashTableBase::DoRemoveNode( wxHashTableBase_Node* node )
97{
98 size_t bucket = ( m_keyType == wxKEY_INTEGER ?
99 node->m_key.integer :
0518029c 100 MakeKey( *node->m_key.string ) ) % m_size;
1a6d9c76
MB
101
102 if( node->GetNext() == node )
103 {
104 // single-node chain (common case)
105 m_table[bucket] = NULL;
106 }
107 else
108 {
109 Node *start = m_table[bucket], *curr;
110 Node* prev = start;
111
112 for( curr = prev->GetNext(); curr != node;
f803b25b 113 prev = curr, curr = curr->GetNext() ) ;
1a6d9c76
MB
114
115 DoUnlinkNode( bucket, node, prev );
116 }
117
118 DoDestroyNode( node );
119}
120
121void wxHashTableBase::DoDestroyNode( wxHashTableBase_Node* node )
122{
123 // if it is called from DoRemoveNode, node has already been
124 // removed, from other places it does not matter
125 node->m_hashPtr = NULL;
126
127 if( m_keyType == wxKEY_STRING )
0518029c 128 delete node->m_key.string;
1a6d9c76
MB
129 if( m_deleteContents )
130 DoDeleteContents( node );
131}
132
133void wxHashTableBase::Destroy()
134{
135 Clear();
136
5276b0a5 137 wxDELETEA(m_table);
1a6d9c76
MB
138 m_size = 0;
139}
140
141void wxHashTableBase::DoInsertNode( size_t bucket, wxHashTableBase_Node* node )
142{
143 if( m_table[bucket] == NULL )
144 {
145 m_table[bucket] = node->m_next = node;
146 }
147 else
148 {
149 Node *prev = m_table[bucket];
150 Node *next = prev->m_next;
151
152 prev->m_next = node;
153 node->m_next = next;
154 m_table[bucket] = node;
155 }
156
157 ++m_count;
158}
159
160void wxHashTableBase::DoPut( long key, long hash, void* data )
161{
162 wxASSERT( m_keyType == wxKEY_INTEGER );
163
164 size_t bucket = size_t(hash) % m_size;
165 Node* node = new wxHashTableBase_Node( key, data, this );
166
167 DoInsertNode( bucket, node );
168}
169
0518029c 170void wxHashTableBase::DoPut( const wxString& key, long hash, void* data )
1a6d9c76
MB
171{
172 wxASSERT( m_keyType == wxKEY_STRING );
173
174 size_t bucket = size_t(hash) % m_size;
175 Node* node = new wxHashTableBase_Node( key, data, this );
176
177 DoInsertNode( bucket, node );
178}
179
180void* wxHashTableBase::DoGet( long key, long hash ) const
181{
182 wxASSERT( m_keyType == wxKEY_INTEGER );
183
184 size_t bucket = size_t(hash) % m_size;
185
186 if( m_table[bucket] == NULL )
187 return NULL;
188
189 Node *first = m_table[bucket]->GetNext(),
190 *curr = first;
191
192 do
193 {
194 if( curr->m_key.integer == key )
195 return curr->m_value;
196
197 curr = curr->GetNext();
198 }
199 while( curr != first );
200
201 return NULL;
202}
203
0518029c 204void* wxHashTableBase::DoGet( const wxString& key, long hash ) const
1a6d9c76
MB
205{
206 wxASSERT( m_keyType == wxKEY_STRING );
207
208 size_t bucket = size_t(hash) % m_size;
209
210 if( m_table[bucket] == NULL )
211 return NULL;
212
213 Node *first = m_table[bucket]->GetNext(),
214 *curr = first;
215
216 do
217 {
0518029c 218 if( *curr->m_key.string == key )
1a6d9c76
MB
219 return curr->m_value;
220
221 curr = curr->GetNext();
222 }
223 while( curr != first );
224
225 return NULL;
226}
227
228void wxHashTableBase::DoUnlinkNode( size_t bucket, wxHashTableBase_Node* node,
229 wxHashTableBase_Node* prev )
230{
231 if( node == m_table[bucket] )
232 m_table[bucket] = prev;
233
234 if( prev == node && prev == node->GetNext() )
235 m_table[bucket] = NULL;
236 else
237 prev->m_next = node->m_next;
238
239 DoDestroyNode( node );
240 --m_count;
241}
242
243void* wxHashTableBase::DoDelete( long key, long hash )
244{
245 wxASSERT( m_keyType == wxKEY_INTEGER );
246
247 size_t bucket = size_t(hash) % m_size;
248
249 if( m_table[bucket] == NULL )
250 return NULL;
251
252 Node *first = m_table[bucket]->GetNext(),
253 *curr = first,
254 *prev = m_table[bucket];
255
256 do
257 {
258 if( curr->m_key.integer == key )
259 {
260 void* retval = curr->m_value;
261 curr->m_value = NULL;
262
263 DoUnlinkNode( bucket, curr, prev );
264 delete curr;
265
266 return retval;
267 }
268
269 prev = curr;
270 curr = curr->GetNext();
271 }
272 while( curr != first );
273
274 return NULL;
275}
276
0518029c 277void* wxHashTableBase::DoDelete( const wxString& key, long hash )
1a6d9c76
MB
278{
279 wxASSERT( m_keyType == wxKEY_STRING );
280
281 size_t bucket = size_t(hash) % m_size;
282
283 if( m_table[bucket] == NULL )
284 return NULL;
285
286 Node *first = m_table[bucket]->GetNext(),
287 *curr = first,
288 *prev = m_table[bucket];
289
290 do
291 {
0518029c 292 if( *curr->m_key.string == key )
1a6d9c76
MB
293 {
294 void* retval = curr->m_value;
295 curr->m_value = NULL;
296
297 DoUnlinkNode( bucket, curr, prev );
298 delete curr;
299
300 return retval;
301 }
302
303 prev = curr;
304 curr = curr->GetNext();
305 }
306 while( curr != first );
307
308 return NULL;
309}
310
0518029c 311long wxHashTableBase::MakeKey( const wxString& str )
1a6d9c76
MB
312{
313 long int_key = 0;
314
0518029c
VZ
315 const wxStringCharType *p = str.wx_str();
316 while( *p )
317 int_key += *p++;
1a6d9c76
MB
318
319 return int_key;
320}
321
2441fb44
VZ
322// ----------------------------------------------------------------------------
323// wxHashTable
324// ----------------------------------------------------------------------------
1a6d9c76
MB
325
326wxHashTable::wxHashTable( const wxHashTable& table )
2441fb44 327 : wxHashTableBase()
1a6d9c76
MB
328{
329 DoCopy( table );
330}
331
332const wxHashTable& wxHashTable::operator=( const wxHashTable& table )
333{
334 Destroy();
335 DoCopy( table );
336
337 return *this;
338}
339
6aa33060 340void wxHashTable::DoCopy( const wxHashTable& WXUNUSED(table) )
1a6d9c76
MB
341{
342 Create( m_keyType, m_size );
343
7cb32b4b 344 wxFAIL;
1a6d9c76
MB
345}
346
347void wxHashTable::DoDeleteContents( wxHashTableBase_Node* node )
348{
349 delete ((wxHashTable_Node*)node)->GetData();
350}
351
352void wxHashTable::GetNextNode( size_t bucketStart )
353{
354 for( size_t i = bucketStart; i < m_size; ++i )
355 {
356 if( m_table[i] != NULL )
357 {
358 m_curr = ((Node*)m_table[i])->GetNext();
359 m_currBucket = i;
360 return;
361 }
362 }
363
364 m_curr = NULL;
365 m_currBucket = 0;
366}
367
368wxHashTable::Node* wxHashTable::Next()
369{
370 if( m_curr == NULL )
371 GetNextNode( 0 );
372 else
373 {
374 m_curr = m_curr->GetNext();
375
376 if( m_curr == ( (Node*)m_table[m_currBucket] )->GetNext() )
377 GetNextNode( m_currBucket + 1 );
378 }
379
380 return m_curr;
381}
382