diff --git a/include/wx/hash.h b/include/wx/hash.h index 0b3470f6d8..3720dd0c1f 100644 --- a/include/wx/hash.h +++ b/include/wx/hash.h @@ -140,7 +140,24 @@ WX_DECLARE_EXPORTED_HASH_MAP( wxHashKeyValue, void*, wxHashTableHash, wxHashTableEqual, - wxHashTableBaseBase ); + wxHashTableBaseBaseBase ); + +// hack: we should really have HASH_MULTI(MAP|SET), but this requires +// less work + +class WXDLLIMPEXP_BASE wxHashTableBaseBase : public wxHashTableBaseBaseBase +{ +public: + wxHashTableBaseBase(size_t size, const wxHashTableHash& hash, + const wxHashTableEqual& equal) + : wxHashTableBaseBaseBase(size, hash, equal) + { } + + void multi_insert(const wxHashKeyValue& key, void* value) + { + CreateNodeLast(value_type(key, value)); + } +}; class WXDLLIMPEXP_BASE wxHashTableBase { @@ -176,7 +193,7 @@ protected: wxASSERT( m_keyType == wxKEY_INTEGER ); wxHashKeyValue k; k.integer = key; - m_map[k] = data; + m_map.multi_insert(k, data); } void DoPut( const wxChar* key, void* data ) @@ -184,17 +201,8 @@ protected: wxASSERT( m_keyType == wxKEY_STRING ); wxHashKeyValue k; - k.string = (wxChar*)key; - wxHashTableBaseBase::iterator it = m_map.find(k); - - if( it == m_map.end() ) - { - k.string = new wxChar[wxStrlen(key) + 1]; - wxStrcpy(k.string, key); - m_map[k] = data; - } - else - it->second = data; + k.string = wxStrcpy(new wxChar[wxStrlen(key) + 1], key); + m_map.multi_insert(k, data); } void* DoGet( long key ) const @@ -407,8 +415,8 @@ public: wxObject *Get(const wxChar *value) const { return (wxObject*)DoGet( value ); } // Deletes entry and returns data if found - wxObject *Delete(long key) { return (wxObject*)DoGet( key ); } - wxObject *Delete(const wxChar *key) { return (wxObject*)DoGet( key ); } + wxObject *Delete(long key) { return (wxObject*)DoDelete( key ); } + wxObject *Delete(const wxChar *key) { return (wxObject*)DoDelete( key ); } #if 0 // Construct your own integer key from a string, e.g. in case diff --git a/include/wx/hashmap.h b/include/wx/hashmap.h index 5924d71576..fbabe5b8f2 100644 --- a/include/wx/hashmap.h +++ b/include/wx/hashmap.h @@ -297,6 +297,19 @@ protected: \ \ return node; \ } \ + void CreateNodeLast( const value_type& value ) \ + { \ + size_t bucket = m_hasher( m_getKey(value) ) % m_tableBuckets; \ + Node* curr = m_table[bucket], \ + * next = m_table[bucket]; \ + while( next ) { curr = next; next = next->m_next(); } \ + Node** ptr = curr ? (Node**)&curr->m_nxt : &m_table[bucket]; \ + *ptr = new Node( value ); \ + /* must be after the node is inserted */ \ + ++m_items; \ + if( SHOULD_GROW( m_tableBuckets, m_items ) ) \ + ResizeTable( m_tableBuckets ); \ + } \ void CreateNode( const value_type& value ) \ {\ CreateNode(value, m_hasher( m_getKey(value) ) % m_tableBuckets ); \ diff --git a/samples/console/console.cpp b/samples/console/console.cpp index 7906063b3c..42df7b135b 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -1152,10 +1152,11 @@ static void TestHash() { wxHashTable hash(wxKEY_INTEGER), hash2(wxKEY_STRING); + wxObject o; int i; for ( i = 0; i < 100; ++i ) - hash.Put(i, (wxObject*)&i + i); + hash.Put(i, &o + i); hash.BeginFind(); wxHashTable::compatibility_iterator it = hash.Next(); @@ -1171,18 +1172,50 @@ static void TestHash() wxPuts(_T("Error in wxHashTable::compatibility_iterator\n")); for ( i = 99; i >= 0; --i ) - if( hash.Get(i) != (wxObject*)&i + i ) + if( hash.Get(i) != &o + i ) wxPuts(_T("Error in wxHashTable::Get/Put\n")); - hash2.Put("foo", (wxObject*)&i + 1); - hash2.Put("bar", (wxObject*)&i + 2); - hash2.Put("baz", (wxObject*)&i + 3); + for ( i = 0; i < 100; ++i ) + hash.Put(i, &o + i + 20); - if (hash2.Get("moo") != NULL) + for ( i = 99; i >= 0; --i ) + if( hash.Get(i) != &o + i) + wxPuts(_T("Error (2) in wxHashTable::Get/Put\n")); + + for ( i = 0; i < 50; ++i ) + if( hash.Delete(i) != &o + i) + wxPuts(_T("Error in wxHashTable::Delete\n")); + + for ( i = 50; i < 100; ++i ) + if( hash.Get(i) != &o + i) + wxPuts(_T("Error (3) in wxHashTable::Get/Put\n")); + + for ( i = 0; i < 50; ++i ) + if( hash.Get(i) != &o + i + 20) + wxPuts(_T("Error (4) in wxHashTable::Put/Delete\n")); + + for ( i = 0; i < 50; ++i ) + if( hash.Delete(i) != &o + i + 20) + wxPuts(_T("Error (2) in wxHashTable::Delete\n")); + + for ( i = 0; i < 50; ++i ) + if( hash.Get(i) != NULL) + wxPuts(_T("Error (5) in wxHashTable::Put/Delete\n")); + + hash2.Put(_T("foo"), &o + 1); + hash2.Put(_T("bar"), &o + 2); + hash2.Put(_T("baz"), &o + 3); + + if (hash2.Get(_T("moo")) != NULL) wxPuts(_T("Error in wxHashTable::Get\n")); - if (hash2.Get("bar") != (wxObject*)&i + 2) + if (hash2.Get(_T("bar")) != &o + 2) wxPuts(_T("Error in wxHashTable::Get/Put\n")); + + hash2.Put(_T("bar"), &o + 0); + + if (hash2.Get(_T("bar")) != &o + 2) + wxPuts(_T("Error (2) in wxHashTable::Get/Put\n")); } #if !wxUSE_STL {