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