]>
git.saurik.com Git - wxWidgets.git/blob - src/common/hash.cpp
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()
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
28 #include "wx/object.h"
31 wxHashTableBase_Node::wxHashTableBase_Node( long key
, void* value
,
32 wxHashTableBase
* table
)
33 : m_value( value
), m_hashPtr( table
)
38 wxHashTableBase_Node::wxHashTableBase_Node( const wxString
& key
, void* value
,
39 wxHashTableBase
* table
)
40 : m_value( value
), m_hashPtr( table
)
42 m_key
.string
= new wxString(key
);
45 wxHashTableBase_Node::~wxHashTableBase_Node()
47 if( m_hashPtr
) m_hashPtr
->DoRemoveNode( this );
52 wxHashTableBase::wxHashTableBase()
53 : m_size( 0 ), m_count( 0 ), m_table( NULL
), m_keyType( wxKEY_NONE
),
54 m_deleteContents( false )
58 void wxHashTableBase::Create( wxKeyType keyType
, size_t size
)
62 m_table
= new wxHashTableBase_Node
*[ m_size
];
64 for( size_t i
= 0; i
< m_size
; ++i
)
68 void wxHashTableBase::Clear()
70 for( size_t i
= 0; i
< m_size
; ++i
)
72 Node
* end
= m_table
[i
];
77 Node
*curr
, *next
= end
->GetNext();
82 next
= curr
->GetNext();
84 DoDestroyNode( curr
);
96 void wxHashTableBase::DoRemoveNode( wxHashTableBase_Node
* node
)
98 size_t bucket
= ( m_keyType
== wxKEY_INTEGER
?
100 MakeKey( *node
->m_key
.string
) ) % m_size
;
102 if( node
->GetNext() == node
)
104 // single-node chain (common case)
105 m_table
[bucket
] = NULL
;
109 Node
*start
= m_table
[bucket
], *curr
;
112 for( curr
= prev
->GetNext(); curr
!= node
;
113 prev
= curr
, curr
= curr
->GetNext() ) ;
115 DoUnlinkNode( bucket
, node
, prev
);
118 DoDestroyNode( node
);
121 void wxHashTableBase::DoDestroyNode( wxHashTableBase_Node
* node
)
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
;
127 if( m_keyType
== wxKEY_STRING
)
128 delete node
->m_key
.string
;
129 if( m_deleteContents
)
130 DoDeleteContents( node
);
133 void wxHashTableBase::Destroy()
141 void wxHashTableBase::DoInsertNode( size_t bucket
, wxHashTableBase_Node
* node
)
143 if( m_table
[bucket
] == NULL
)
145 m_table
[bucket
] = node
->m_next
= node
;
149 Node
*prev
= m_table
[bucket
];
150 Node
*next
= prev
->m_next
;
154 m_table
[bucket
] = node
;
160 void wxHashTableBase::DoPut( long key
, long hash
, void* data
)
162 wxASSERT( m_keyType
== wxKEY_INTEGER
);
164 size_t bucket
= size_t(hash
) % m_size
;
165 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
167 DoInsertNode( bucket
, node
);
170 void wxHashTableBase::DoPut( const wxString
& key
, long hash
, void* data
)
172 wxASSERT( m_keyType
== wxKEY_STRING
);
174 size_t bucket
= size_t(hash
) % m_size
;
175 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
177 DoInsertNode( bucket
, node
);
180 void* wxHashTableBase::DoGet( long key
, long hash
) const
182 wxASSERT( m_keyType
== wxKEY_INTEGER
);
184 size_t bucket
= size_t(hash
) % m_size
;
186 if( m_table
[bucket
] == NULL
)
189 Node
*first
= m_table
[bucket
]->GetNext(),
194 if( curr
->m_key
.integer
== key
)
195 return curr
->m_value
;
197 curr
= curr
->GetNext();
199 while( curr
!= first
);
204 void* wxHashTableBase::DoGet( const wxString
& key
, long hash
) const
206 wxASSERT( m_keyType
== wxKEY_STRING
);
208 size_t bucket
= size_t(hash
) % m_size
;
210 if( m_table
[bucket
] == NULL
)
213 Node
*first
= m_table
[bucket
]->GetNext(),
218 if( *curr
->m_key
.string
== key
)
219 return curr
->m_value
;
221 curr
= curr
->GetNext();
223 while( curr
!= first
);
228 void wxHashTableBase::DoUnlinkNode( size_t bucket
, wxHashTableBase_Node
* node
,
229 wxHashTableBase_Node
* prev
)
231 if( node
== m_table
[bucket
] )
232 m_table
[bucket
] = prev
;
234 if( prev
== node
&& prev
== node
->GetNext() )
235 m_table
[bucket
] = NULL
;
237 prev
->m_next
= node
->m_next
;
239 DoDestroyNode( node
);
243 void* wxHashTableBase::DoDelete( long key
, long hash
)
245 wxASSERT( m_keyType
== wxKEY_INTEGER
);
247 size_t bucket
= size_t(hash
) % m_size
;
249 if( m_table
[bucket
] == NULL
)
252 Node
*first
= m_table
[bucket
]->GetNext(),
254 *prev
= m_table
[bucket
];
258 if( curr
->m_key
.integer
== key
)
260 void* retval
= curr
->m_value
;
261 curr
->m_value
= NULL
;
263 DoUnlinkNode( bucket
, curr
, prev
);
270 curr
= curr
->GetNext();
272 while( curr
!= first
);
277 void* wxHashTableBase::DoDelete( const wxString
& key
, long hash
)
279 wxASSERT( m_keyType
== wxKEY_STRING
);
281 size_t bucket
= size_t(hash
) % m_size
;
283 if( m_table
[bucket
] == NULL
)
286 Node
*first
= m_table
[bucket
]->GetNext(),
288 *prev
= m_table
[bucket
];
292 if( *curr
->m_key
.string
== key
)
294 void* retval
= curr
->m_value
;
295 curr
->m_value
= NULL
;
297 DoUnlinkNode( bucket
, curr
, prev
);
304 curr
= curr
->GetNext();
306 while( curr
!= first
);
311 long wxHashTableBase::MakeKey( const wxString
& str
)
315 const wxStringCharType
*p
= str
.wx_str();
322 // ----------------------------------------------------------------------------
324 // ----------------------------------------------------------------------------
326 wxHashTable::wxHashTable( const wxHashTable
& table
)
332 const wxHashTable
& wxHashTable::operator=( const wxHashTable
& table
)
340 void wxHashTable::DoCopy( const wxHashTable
& WXUNUSED(table
) )
342 Create( m_keyType
, m_size
);
347 void wxHashTable::DoDeleteContents( wxHashTableBase_Node
* node
)
349 delete ((wxHashTable_Node
*)node
)->GetData();
352 void wxHashTable::GetNextNode( size_t bucketStart
)
354 for( size_t i
= bucketStart
; i
< m_size
; ++i
)
356 if( m_table
[i
] != NULL
)
358 m_curr
= ((Node
*)m_table
[i
])->GetNext();
368 wxHashTable::Node
* wxHashTable::Next()
374 m_curr
= m_curr
->GetNext();
376 if( m_curr
== ( (Node
*)m_table
[m_currBucket
] )->GetNext() )
377 GetNextNode( m_currBucket
+ 1 );