]>
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()
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/object.h"
32 wxHashTableBase_Node::wxHashTableBase_Node( long key
, void* value
,
33 wxHashTableBase
* table
)
34 : m_value( value
), m_hashPtr( table
)
39 wxHashTableBase_Node::wxHashTableBase_Node( const wxString
& key
, void* value
,
40 wxHashTableBase
* table
)
41 : m_value( value
), m_hashPtr( table
)
43 m_key
.string
= new wxString(key
);
46 wxHashTableBase_Node::~wxHashTableBase_Node()
48 if( m_hashPtr
) m_hashPtr
->DoRemoveNode( this );
53 wxHashTableBase::wxHashTableBase()
54 : m_size( 0 ), m_count( 0 ), m_table( NULL
), m_keyType( wxKEY_NONE
),
55 m_deleteContents( false )
59 void wxHashTableBase::Create( wxKeyType keyType
, size_t size
)
63 m_table
= new wxHashTableBase_Node
*[ m_size
];
65 for( size_t i
= 0; i
< m_size
; ++i
)
69 void wxHashTableBase::Clear()
71 for( size_t i
= 0; i
< m_size
; ++i
)
73 Node
* end
= m_table
[i
];
78 Node
*curr
, *next
= end
->GetNext();
83 next
= curr
->GetNext();
85 DoDestroyNode( curr
);
97 void wxHashTableBase::DoRemoveNode( wxHashTableBase_Node
* node
)
99 size_t bucket
= ( m_keyType
== wxKEY_INTEGER
?
100 node
->m_key
.integer
:
101 MakeKey( *node
->m_key
.string
) ) % m_size
;
103 if( node
->GetNext() == node
)
105 // single-node chain (common case)
106 m_table
[bucket
] = NULL
;
110 Node
*start
= m_table
[bucket
], *curr
;
113 for( curr
= prev
->GetNext(); curr
!= node
;
114 prev
= curr
, curr
= curr
->GetNext() ) ;
116 DoUnlinkNode( bucket
, node
, prev
);
119 DoDestroyNode( node
);
122 void wxHashTableBase::DoDestroyNode( wxHashTableBase_Node
* node
)
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
;
128 if( m_keyType
== wxKEY_STRING
)
129 delete node
->m_key
.string
;
130 if( m_deleteContents
)
131 DoDeleteContents( node
);
134 void wxHashTableBase::Destroy()
142 void wxHashTableBase::DoInsertNode( size_t bucket
, wxHashTableBase_Node
* node
)
144 if( m_table
[bucket
] == NULL
)
146 m_table
[bucket
] = node
->m_next
= node
;
150 Node
*prev
= m_table
[bucket
];
151 Node
*next
= prev
->m_next
;
155 m_table
[bucket
] = node
;
161 void wxHashTableBase::DoPut( long key
, long hash
, void* data
)
163 wxASSERT( m_keyType
== wxKEY_INTEGER
);
165 size_t bucket
= size_t(hash
) % m_size
;
166 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
168 DoInsertNode( bucket
, node
);
171 void wxHashTableBase::DoPut( const wxString
& key
, long hash
, void* data
)
173 wxASSERT( m_keyType
== wxKEY_STRING
);
175 size_t bucket
= size_t(hash
) % m_size
;
176 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
178 DoInsertNode( bucket
, node
);
181 void* wxHashTableBase::DoGet( long key
, long hash
) const
183 wxASSERT( m_keyType
== wxKEY_INTEGER
);
185 size_t bucket
= size_t(hash
) % m_size
;
187 if( m_table
[bucket
] == NULL
)
190 Node
*first
= m_table
[bucket
]->GetNext(),
195 if( curr
->m_key
.integer
== key
)
196 return curr
->m_value
;
198 curr
= curr
->GetNext();
200 while( curr
!= first
);
205 void* wxHashTableBase::DoGet( const wxString
& key
, long hash
) const
207 wxASSERT( m_keyType
== wxKEY_STRING
);
209 size_t bucket
= size_t(hash
) % m_size
;
211 if( m_table
[bucket
] == NULL
)
214 Node
*first
= m_table
[bucket
]->GetNext(),
219 if( *curr
->m_key
.string
== key
)
220 return curr
->m_value
;
222 curr
= curr
->GetNext();
224 while( curr
!= first
);
229 void wxHashTableBase::DoUnlinkNode( size_t bucket
, wxHashTableBase_Node
* node
,
230 wxHashTableBase_Node
* prev
)
232 if( node
== m_table
[bucket
] )
233 m_table
[bucket
] = prev
;
235 if( prev
== node
&& prev
== node
->GetNext() )
236 m_table
[bucket
] = NULL
;
238 prev
->m_next
= node
->m_next
;
240 DoDestroyNode( node
);
244 void* wxHashTableBase::DoDelete( long key
, long hash
)
246 wxASSERT( m_keyType
== wxKEY_INTEGER
);
248 size_t bucket
= size_t(hash
) % m_size
;
250 if( m_table
[bucket
] == NULL
)
253 Node
*first
= m_table
[bucket
]->GetNext(),
255 *prev
= m_table
[bucket
];
259 if( curr
->m_key
.integer
== key
)
261 void* retval
= curr
->m_value
;
262 curr
->m_value
= NULL
;
264 DoUnlinkNode( bucket
, curr
, prev
);
271 curr
= curr
->GetNext();
273 while( curr
!= first
);
278 void* wxHashTableBase::DoDelete( const wxString
& key
, long hash
)
280 wxASSERT( m_keyType
== wxKEY_STRING
);
282 size_t bucket
= size_t(hash
) % m_size
;
284 if( m_table
[bucket
] == NULL
)
287 Node
*first
= m_table
[bucket
]->GetNext(),
289 *prev
= m_table
[bucket
];
293 if( *curr
->m_key
.string
== key
)
295 void* retval
= curr
->m_value
;
296 curr
->m_value
= NULL
;
298 DoUnlinkNode( bucket
, curr
, prev
);
305 curr
= curr
->GetNext();
307 while( curr
!= first
);
312 long wxHashTableBase::MakeKey( const wxString
& str
)
316 const wxStringCharType
*p
= str
.wx_str();
323 // ----------------------------------------------------------------------------
325 // ----------------------------------------------------------------------------
327 wxHashTable::wxHashTable( const wxHashTable
& table
)
333 const wxHashTable
& wxHashTable::operator=( const wxHashTable
& table
)
341 void wxHashTable::DoCopy( const wxHashTable
& WXUNUSED(table
) )
343 Create( m_keyType
, m_size
);
348 void wxHashTable::DoDeleteContents( wxHashTableBase_Node
* node
)
350 delete ((wxHashTable_Node
*)node
)->GetData();
353 void wxHashTable::GetNextNode( size_t bucketStart
)
355 for( size_t i
= bucketStart
; i
< m_size
; ++i
)
357 if( m_table
[i
] != NULL
)
359 m_curr
= ((Node
*)m_table
[i
])->GetNext();
369 wxHashTable::Node
* wxHashTable::Next()
375 m_curr
= m_curr
->GetNext();
377 if( m_curr
== ( (Node
*)m_table
[m_currBucket
] )->GetNext() )
378 GetNextNode( m_currBucket
+ 1 );