]> git.saurik.com Git - wxWidgets.git/blame - src/common/hash.cpp
fix wxTimeSpan::Format() for negative spans with 0 hour component (#10055)
[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
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
32d4c30a 28 #include "wx/hash.h"
1436bf0b 29 #include "wx/object.h"
c801d85f
KB
30#endif
31
1a6d9c76
MB
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
0518029c 39wxHashTableBase_Node::wxHashTableBase_Node( const wxString& key, void* value,
1a6d9c76
MB
40 wxHashTableBase* table )
41 : m_value( value ), m_hashPtr( table )
42{
0518029c 43 m_key.string = new wxString(key);
1a6d9c76
MB
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
1a6d9c76
MB
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 :
0518029c 101 MakeKey( *node->m_key.string ) ) % m_size;
1a6d9c76
MB
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;
f803b25b 114 prev = curr, curr = curr->GetNext() ) ;
1a6d9c76
MB
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 )
0518029c 129 delete node->m_key.string;
1a6d9c76
MB
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
0518029c 173void wxHashTableBase::DoPut( const wxString& key, long hash, void* data )
1a6d9c76
MB
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
0518029c 207void* wxHashTableBase::DoGet( const wxString& key, long hash ) const
1a6d9c76
MB
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 {
0518029c 221 if( *curr->m_key.string == key )
1a6d9c76
MB
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
0518029c 280void* wxHashTableBase::DoDelete( const wxString& key, long hash )
1a6d9c76
MB
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 {
0518029c 295 if( *curr->m_key.string == key )
1a6d9c76
MB
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
0518029c 314long wxHashTableBase::MakeKey( const wxString& str )
1a6d9c76
MB
315{
316 long int_key = 0;
317
0518029c
VZ
318 const wxStringCharType *p = str.wx_str();
319 while( *p )
320 int_key += *p++;
1a6d9c76
MB
321
322 return int_key;
323}
324
2441fb44
VZ
325// ----------------------------------------------------------------------------
326// wxHashTable
327// ----------------------------------------------------------------------------
1a6d9c76
MB
328
329wxHashTable::wxHashTable( const wxHashTable& table )
2441fb44 330 : wxHashTableBase()
1a6d9c76
MB
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
6aa33060 343void wxHashTable::DoCopy( const wxHashTable& WXUNUSED(table) )
1a6d9c76
MB
344{
345 Create( m_keyType, m_size );
346
7cb32b4b 347 wxFAIL;
1a6d9c76
MB
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