]>
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"
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()
143 void wxHashTableBase::DoInsertNode( size_t bucket
, wxHashTableBase_Node
* node
)
145 if( m_table
[bucket
] == NULL
)
147 m_table
[bucket
] = node
->m_next
= node
;
151 Node
*prev
= m_table
[bucket
];
152 Node
*next
= prev
->m_next
;
156 m_table
[bucket
] = node
;
162 void wxHashTableBase::DoPut( long key
, long hash
, void* data
)
164 wxASSERT( m_keyType
== wxKEY_INTEGER
);
166 size_t bucket
= size_t(hash
) % m_size
;
167 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
169 DoInsertNode( bucket
, node
);
172 void wxHashTableBase::DoPut( const wxString
& key
, long hash
, void* data
)
174 wxASSERT( m_keyType
== wxKEY_STRING
);
176 size_t bucket
= size_t(hash
) % m_size
;
177 Node
* node
= new wxHashTableBase_Node( key
, data
, this );
179 DoInsertNode( bucket
, node
);
182 void* wxHashTableBase::DoGet( long key
, long hash
) const
184 wxASSERT( m_keyType
== wxKEY_INTEGER
);
186 size_t bucket
= size_t(hash
) % m_size
;
188 if( m_table
[bucket
] == NULL
)
191 Node
*first
= m_table
[bucket
]->GetNext(),
196 if( curr
->m_key
.integer
== key
)
197 return curr
->m_value
;
199 curr
= curr
->GetNext();
201 while( curr
!= first
);
206 void* wxHashTableBase::DoGet( const wxString
& key
, long hash
) const
208 wxASSERT( m_keyType
== wxKEY_STRING
);
210 size_t bucket
= size_t(hash
) % m_size
;
212 if( m_table
[bucket
] == NULL
)
215 Node
*first
= m_table
[bucket
]->GetNext(),
220 if( *curr
->m_key
.string
== key
)
221 return curr
->m_value
;
223 curr
= curr
->GetNext();
225 while( curr
!= first
);
230 void wxHashTableBase::DoUnlinkNode( size_t bucket
, wxHashTableBase_Node
* node
,
231 wxHashTableBase_Node
* prev
)
233 if( node
== m_table
[bucket
] )
234 m_table
[bucket
] = prev
;
236 if( prev
== node
&& prev
== node
->GetNext() )
237 m_table
[bucket
] = NULL
;
239 prev
->m_next
= node
->m_next
;
241 DoDestroyNode( node
);
245 void* wxHashTableBase::DoDelete( long key
, long hash
)
247 wxASSERT( m_keyType
== wxKEY_INTEGER
);
249 size_t bucket
= size_t(hash
) % m_size
;
251 if( m_table
[bucket
] == NULL
)
254 Node
*first
= m_table
[bucket
]->GetNext(),
256 *prev
= m_table
[bucket
];
260 if( curr
->m_key
.integer
== key
)
262 void* retval
= curr
->m_value
;
263 curr
->m_value
= NULL
;
265 DoUnlinkNode( bucket
, curr
, prev
);
272 curr
= curr
->GetNext();
274 while( curr
!= first
);
279 void* wxHashTableBase::DoDelete( const wxString
& key
, long hash
)
281 wxASSERT( m_keyType
== wxKEY_STRING
);
283 size_t bucket
= size_t(hash
) % m_size
;
285 if( m_table
[bucket
] == NULL
)
288 Node
*first
= m_table
[bucket
]->GetNext(),
290 *prev
= m_table
[bucket
];
294 if( *curr
->m_key
.string
== key
)
296 void* retval
= curr
->m_value
;
297 curr
->m_value
= NULL
;
299 DoUnlinkNode( bucket
, curr
, prev
);
306 curr
= curr
->GetNext();
308 while( curr
!= first
);
313 long wxHashTableBase::MakeKey( const wxString
& str
)
317 const wxStringCharType
*p
= str
.wx_str();
324 // ----------------------------------------------------------------------------
326 // ----------------------------------------------------------------------------
328 wxHashTable::wxHashTable( const wxHashTable
& table
)
334 const wxHashTable
& wxHashTable::operator=( const wxHashTable
& table
)
342 void wxHashTable::DoCopy( const wxHashTable
& WXUNUSED(table
) )
344 Create( m_keyType
, m_size
);
349 void wxHashTable::DoDeleteContents( wxHashTableBase_Node
* node
)
351 delete ((wxHashTable_Node
*)node
)->GetData();
354 void wxHashTable::GetNextNode( size_t bucketStart
)
356 for( size_t i
= bucketStart
; i
< m_size
; ++i
)
358 if( m_table
[i
] != NULL
)
360 m_curr
= ((Node
*)m_table
[i
])->GetNext();
370 wxHashTable::Node
* wxHashTable::Next()
376 m_curr
= m_curr
->GetNext();
378 if( m_curr
== ( (Node
*)m_table
[m_currBucket
] )->GetNext() )
379 GetNextNode( m_currBucket
+ 1 );