]>
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()
144 void wxHashTableBase::DoInsertNode( size_t bucket
, wxHashTableBase_Node
* node
)
146 if( m_table
[bucket
] == NULL
)
148 m_table
[bucket
] = node
->m_next
= node
;
152 Node
*prev
= m_table
[bucket
];
153 Node
*next
= prev
->m_next
;
157 m_table
[bucket
] = node
;
163 void wxHashTableBase::DoPut( long key
, long hash
, void* data
)
165 wxASSERT( m_keyType
== wxKEY_INTEGER
);
167 size_t bucket
= size_t(hash
) % m_size
;
168 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
170 DoInsertNode( bucket
, node
);
173 void wxHashTableBase::DoPut( const wxString
& key
, long hash
, void* data
)
175 wxASSERT( m_keyType
== wxKEY_STRING
);
177 size_t bucket
= size_t(hash
) % m_size
;
178 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
180 DoInsertNode( bucket
, node
);
183 void* wxHashTableBase::DoGet( long key
, long hash
) const
185 wxASSERT( m_keyType
== wxKEY_INTEGER
);
187 size_t bucket
= size_t(hash
) % m_size
;
189 if( m_table
[bucket
] == NULL
)
192 Node
*first
= m_table
[bucket
]->GetNext(),
197 if( curr
->m_key
.integer
== key
)
198 return curr
->m_value
;
200 curr
= curr
->GetNext();
202 while( curr
!= first
);
207 void* wxHashTableBase::DoGet( const wxString
& key
, long hash
) const
209 wxASSERT( m_keyType
== wxKEY_STRING
);
211 size_t bucket
= size_t(hash
) % m_size
;
213 if( m_table
[bucket
] == NULL
)
216 Node
*first
= m_table
[bucket
]->GetNext(),
221 if( *curr
->m_key
.string
== key
)
222 return curr
->m_value
;
224 curr
= curr
->GetNext();
226 while( curr
!= first
);
231 void wxHashTableBase::DoUnlinkNode( size_t bucket
, wxHashTableBase_Node
* node
,
232 wxHashTableBase_Node
* prev
)
234 if( node
== m_table
[bucket
] )
235 m_table
[bucket
] = prev
;
237 if( prev
== node
&& prev
== node
->GetNext() )
238 m_table
[bucket
] = NULL
;
240 prev
->m_next
= node
->m_next
;
242 DoDestroyNode( node
);
246 void* wxHashTableBase::DoDelete( long key
, long hash
)
248 wxASSERT( m_keyType
== wxKEY_INTEGER
);
250 size_t bucket
= size_t(hash
) % m_size
;
252 if( m_table
[bucket
] == NULL
)
255 Node
*first
= m_table
[bucket
]->GetNext(),
257 *prev
= m_table
[bucket
];
261 if( curr
->m_key
.integer
== key
)
263 void* retval
= curr
->m_value
;
264 curr
->m_value
= NULL
;
266 DoUnlinkNode( bucket
, curr
, prev
);
273 curr
= curr
->GetNext();
275 while( curr
!= first
);
280 void* wxHashTableBase::DoDelete( const wxString
& key
, long hash
)
282 wxASSERT( m_keyType
== wxKEY_STRING
);
284 size_t bucket
= size_t(hash
) % m_size
;
286 if( m_table
[bucket
] == NULL
)
289 Node
*first
= m_table
[bucket
]->GetNext(),
291 *prev
= m_table
[bucket
];
295 if( *curr
->m_key
.string
== key
)
297 void* retval
= curr
->m_value
;
298 curr
->m_value
= NULL
;
300 DoUnlinkNode( bucket
, curr
, prev
);
307 curr
= curr
->GetNext();
309 while( curr
!= first
);
314 long wxHashTableBase::MakeKey( const wxString
& str
)
318 const wxStringCharType
*p
= str
.wx_str();
325 // ----------------------------------------------------------------------------
327 // ----------------------------------------------------------------------------
329 wxHashTable::wxHashTable( const wxHashTable
& table
)
335 const wxHashTable
& wxHashTable::operator=( const wxHashTable
& table
)
343 void wxHashTable::DoCopy( const wxHashTable
& WXUNUSED(table
) )
345 Create( m_keyType
, m_size
);
350 void wxHashTable::DoDeleteContents( wxHashTableBase_Node
* node
)
352 delete ((wxHashTable_Node
*)node
)->GetData();
355 void wxHashTable::GetNextNode( size_t bucketStart
)
357 for( size_t i
= bucketStart
; i
< m_size
; ++i
)
359 if( m_table
[i
] != NULL
)
361 m_curr
= ((Node
*)m_table
[i
])->GetNext();
371 wxHashTable::Node
* wxHashTable::Next()
377 m_curr
= m_curr
->GetNext();
379 if( m_curr
== ( (Node
*)m_table
[m_currBucket
] )->GetNext() )
380 GetNextNode( m_currBucket
+ 1 );