From 8a8fee442f7331d40cbe4b0a834cd1b7b7474e00 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 19:59:01 +0100 Subject: [PATCH 01/37] Make wxEnvVariableHashMap just a std::unordered_map<> Use the standard container directly instead of using a wx synonym for it, this is more clear. Use the same hack here as in e13dbd4278 (Use std::unordered_map<> in wxMsgCatalog and related classes, 2023-04-12) to allow the existing code including this header keep using the functions from wx/wxcrt.h without including it explicitly. --- include/wx/utils.h | 12 ++++++++++-- interface/wx/utils.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/wx/utils.h b/include/wx/utils.h index 239dc6f6f4..51479e48f4 100644 --- a/include/wx/utils.h +++ b/include/wx/utils.h @@ -18,7 +18,6 @@ #include "wx/object.h" #include "wx/list.h" #include "wx/filefn.h" -#include "wx/hashmap.h" #include "wx/versioninfo.h" #include "wx/meta/implicitconversion.h" @@ -38,6 +37,13 @@ class WXDLLIMPEXP_FWD_BASE wxArrayInt; // needed for wxOperatingSystemId, wxLinuxDistributionInfo #include "wx/platinfo.h" +// This is a hack, but this header used to include wx/hashmap.h which, in turn, +// included wx/wxcrt.h and it turns out quite some existing code relied on it +// by using the CRT wrapper functions declared there without explicitly +// including that header, so keep including it from here to let it continue to +// compile. +#include "wx/wxcrt.h" + #if defined(__X__) #include #include @@ -45,6 +51,8 @@ class WXDLLIMPEXP_FWD_BASE wxArrayInt; #include +#include + // ---------------------------------------------------------------------------- // Forward declaration // ---------------------------------------------------------------------------- @@ -366,7 +374,7 @@ enum }; // Map storing environment variables. -typedef wxStringToStringHashMap wxEnvVariableHashMap; +using wxEnvVariableHashMap = std::unordered_map; // Used to pass additional parameters for child process to wxExecute(). Could // be extended with other fields later. diff --git a/interface/wx/utils.h b/interface/wx/utils.h index debe854677..8eadeb5758 100644 --- a/interface/wx/utils.h +++ b/interface/wx/utils.h @@ -253,7 +253,7 @@ wxVersionInfo wxGetLibraryVersionInfo(); @header{wx/utils.h} */ -typedef wxStringToStringHashMap wxEnvVariableHashMap; +using wxEnvVariableHashMap = std::unordered_map; /** This is a macro defined as @c getenv() or its wide char version in Unicode From bfe76ece58cc9f9e22497705d08f85371e240bc3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:01:02 +0100 Subject: [PATCH 02/37] Define GetComponentLevels() directly without using a macro Just define the trivial accessor functions explicitly instead of using a macro for defining it. --- src/common/log.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/common/log.cpp b/src/common/log.cpp index 38231abbee..c7979eb3af 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -149,7 +149,16 @@ PreviousLogInfo gs_prevLog; // map containing all components for which log level was explicitly set // // NB: all accesses to it must be protected by GetLevelsCS() critical section -WX_DEFINE_GLOBAL_VAR(wxStringToNumHashMap, ComponentLevels); +namespace +{ + +inline wxStringToNumHashMap& GetComponentLevels() +{ + static wxStringToNumHashMap s_componentLevels; + return s_componentLevels; +} + +} // anonymous namespace // ---------------------------------------------------------------------------- // wxLogOutputBest: wxLog wrapper around wxMessageOutputBest From cdb70479e475e07afa86a6c1e79210ca3c9be72c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:02:51 +0100 Subject: [PATCH 03/37] Use appropriately typed map for GetComponentLevels() Replace wxStringToNumHashMap with a map using the correct wxLogLevel type for the values to avoid unnecessary casts when using it. --- src/common/log.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/common/log.cpp b/src/common/log.cpp index c7979eb3af..30985507fb 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -152,9 +152,11 @@ PreviousLogInfo gs_prevLog; namespace { -inline wxStringToNumHashMap& GetComponentLevels() +using ComponentLevelsMap = std::unordered_map; + +inline ComponentLevelsMap& GetComponentLevels() { - static wxStringToNumHashMap s_componentLevels; + static ComponentLevelsMap s_componentLevels; return s_componentLevels; } @@ -612,13 +614,12 @@ wxLogLevel wxLog::GetComponentLevel(const wxString& componentOrig) // Make a copy before modifying it in the loop. wxString component = componentOrig; - const wxStringToNumHashMap& componentLevels = GetComponentLevels(); + const auto& componentLevels = GetComponentLevels(); while ( !component.empty() ) { - wxStringToNumHashMap::const_iterator - it = componentLevels.find(component); + const auto it = componentLevels.find(component); if ( it != componentLevels.end() ) - return static_cast(it->second); + return it->second; component = component.BeforeLast('/'); } From baa9a28eb0e33fad2f81937939306e7b9e169a79 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:05:14 +0100 Subject: [PATCH 04/37] Use std::unordered_map<> in wxShadowObject Use the standard containers directly instead of using wx hash map macros for declaring the types for clarity and simplicity. --- include/wx/clntdata.h | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/include/wx/clntdata.h b/include/wx/clntdata.h index 20ebc17418..f5b4314d34 100644 --- a/include/wx/clntdata.h +++ b/include/wx/clntdata.h @@ -13,20 +13,14 @@ #include "wx/defs.h" #include "wx/string.h" -#include "wx/hashmap.h" #include "wx/object.h" +#include + typedef int (*wxShadowObjectMethod)(void*, void*); -WX_DECLARE_STRING_HASH_MAP_WITH_DECL( - wxShadowObjectMethod, - wxShadowObjectMethods, - class WXDLLIMPEXP_BASE -); -WX_DECLARE_STRING_HASH_MAP_WITH_DECL( - void *, - wxShadowObjectFields, - class WXDLLIMPEXP_BASE -); + +using wxShadowObjectMethods = std::unordered_map; +using wxShadowObjectFields = std::unordered_map; class WXDLLIMPEXP_BASE wxShadowObject { @@ -35,7 +29,7 @@ public: void AddMethod( const wxString &name, wxShadowObjectMethod method ) { - wxShadowObjectMethods::iterator it = m_methods.find( name ); + const auto it = m_methods.find( name ); if (it == m_methods.end()) m_methods[ name ] = method; else @@ -44,7 +38,7 @@ public: bool InvokeMethod( const wxString &name, void* window, void* param, int* returnValue ) { - wxShadowObjectMethods::iterator it = m_methods.find( name ); + const auto it = m_methods.find( name ); if (it == m_methods.end()) return false; wxShadowObjectMethod method = it->second; @@ -56,7 +50,7 @@ public: void AddField( const wxString &name, void* initialValue = nullptr ) { - wxShadowObjectFields::iterator it = m_fields.find( name ); + const auto it = m_fields.find( name ); if (it == m_fields.end()) m_fields[ name ] = initialValue; else @@ -65,7 +59,7 @@ public: void SetField( const wxString &name, void* value ) { - wxShadowObjectFields::iterator it = m_fields.find( name ); + const auto it = m_fields.find( name ); if (it == m_fields.end()) return; it->second = value; @@ -73,7 +67,7 @@ public: void* GetField( const wxString &name, void *defaultValue = nullptr ) { - wxShadowObjectFields::iterator it = m_fields.find( name ); + const auto it = m_fields.find( name ); if (it == m_fields.end()) return defaultValue; return it->second; From cc3498f49bc686062ecb8b02b8bb9b86976b0acd Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:05:44 +0100 Subject: [PATCH 05/37] Use std::unordered_map<> in wxLogRecordInfo Use the standard containers directly instead of using wx synonyms. --- include/wx/log.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/wx/log.h b/include/wx/log.h index dde1dceba4..3c8d413d07 100644 --- a/include/wx/log.h +++ b/include/wx/log.h @@ -44,7 +44,6 @@ class WXDLLIMPEXP_FWD_BASE wxObject; #include // for time_t #include "wx/dynarray.h" -#include "wx/hashmap.h" #include "wx/msgout.h" #include "wx/time.h" @@ -52,6 +51,8 @@ class WXDLLIMPEXP_FWD_BASE wxObject; #include "wx/thread.h" #endif // wxUSE_THREADS +#include + // wxUSE_LOG_DEBUG enables the debug log messages #ifndef wxUSE_LOG_DEBUG #if wxDEBUG_LEVEL @@ -236,7 +237,7 @@ public: if ( !m_data ) return false; - const wxStringToNumHashMap::const_iterator it = m_data->numValues.find(key); + const auto it = m_data->numValues.find(key); if ( it == m_data->numValues.end() ) return false; @@ -250,7 +251,7 @@ public: if ( !m_data ) return false; - const wxStringToStringHashMap::const_iterator it = m_data->strValues.find(key); + const auto it = m_data->strValues.find(key); if ( it == m_data->strValues.end() ) return false; @@ -272,8 +273,8 @@ private: // sink (e.g. wxLogSysError() uses this to pass the error code) struct ExtraData { - wxStringToNumHashMap numValues; - wxStringToStringHashMap strValues; + std::unordered_map numValues; + std::unordered_map strValues; }; // nullptr if not used From 55d3e798a8479b2824a6657e472385777e1ee0c7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 18 Apr 2023 00:42:35 +0200 Subject: [PATCH 06/37] Use std::unordered_map<> in wxWebView Replace a wx synonym with the direct use of the standard class. --- include/wx/webview.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/wx/webview.h b/include/wx/webview.h index 82ccf984f4..2fa343cb54 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -30,6 +30,8 @@ #error "wxWebView not implemented on this platform." #endif +#include + class wxFSFile; class wxFileSystem; class wxWebView; @@ -186,7 +188,7 @@ public: virtual wxWebViewConfiguration CreateConfiguration(); }; -WX_DECLARE_STRING_HASH_MAP(wxSharedPtr, wxStringWebViewFactoryMap); +using wxStringWebViewFactoryMap = std::unordered_map>; class WXDLLIMPEXP_WEBVIEW wxWebView : public wxControl { From 9966b4793c504bdee186ef6253df72473d541aab Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:06:42 +0100 Subject: [PATCH 07/37] Use std::unordered_map<> in wxFileSystem Use the standard containers directly instead of using wx synonyms. --- include/wx/filesys.h | 5 +++-- src/common/filesys.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/wx/filesys.h b/include/wx/filesys.h index cf5a99d45a..ea46f69139 100644 --- a/include/wx/filesys.h +++ b/include/wx/filesys.h @@ -16,7 +16,8 @@ #include "wx/stream.h" #include "wx/datetime.h" #include "wx/filename.h" -#include "wx/hashmap.h" + +#include class WXDLLIMPEXP_FWD_BASE wxFSFile; class WXDLLIMPEXP_FWD_BASE wxFileSystemHandler; @@ -165,7 +166,7 @@ enum wxFileSystemOpenFlags wxFS_SEEKABLE = 4 // Returned stream will be seekable }; -WX_DECLARE_VOIDPTR_HASH_MAP_WITH_DECL(wxFileSystemHandler*, wxFSHandlerHash, class WXDLLIMPEXP_BASE); +using wxFSHandlerHash = std::unordered_map; class WXDLLIMPEXP_BASE wxFileSystem : public wxObject { diff --git a/src/common/filesys.cpp b/src/common/filesys.cpp index c0a322de62..aabb9255a1 100644 --- a/src/common/filesys.cpp +++ b/src/common/filesys.cpp @@ -334,7 +334,8 @@ wxList wxFileSystem::m_Handlers; wxFileSystem::~wxFileSystem() { - WX_CLEAR_HASH_MAP(wxFSHandlerHash, m_LocalHandlers) + for ( const auto& kv : m_LocalHandlers ) + delete kv.second; } From 492c1dd7c790472fa9d24d2456db6c0146aa7955 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:07:40 +0100 Subject: [PATCH 08/37] Use std::unordered_map<> in wxArchiveFSHandler code In addition to removing wx hash map macros, also change the private wxArchiveFSEntryHash to store std::unique_ptr rather than the raw pointers to ensure they're destroyed automatically and we don't need to use WX_CLEAR_HASH_MAP() for them. --- include/wx/fs_arc.h | 5 +++-- src/common/fs_arc.cpp | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/include/wx/fs_arc.h b/include/wx/fs_arc.h index 0412cd26ef..c252f8ad8c 100644 --- a/include/wx/fs_arc.h +++ b/include/wx/fs_arc.h @@ -14,9 +14,10 @@ #if wxUSE_FS_ARCHIVE #include "wx/filesys.h" -#include "wx/hashmap.h" -WX_DECLARE_STRING_HASH_MAP(int, wxArchiveFilenameHashMap); +#include + +using wxArchiveFilenameHashMap = std::unordered_map; //--------------------------------------------------------------------------- // wxArchiveFSHandler diff --git a/src/common/fs_arc.cpp b/src/common/fs_arc.cpp index b1e2a954be..e5b2cb523b 100644 --- a/src/common/fs_arc.cpp +++ b/src/common/fs_arc.cpp @@ -32,7 +32,8 @@ // version. //--------------------------------------------------------------------------- -WX_DECLARE_STRING_HASH_MAP(wxArchiveEntry*, wxArchiveFSEntryHash); +using wxArchiveFSEntryHash = + std::unordered_map>; struct wxArchiveFSEntry { @@ -59,6 +60,7 @@ public: wxArchiveFSEntry *GetNext(wxArchiveFSEntry *fse); private: + // Takes ownership of "entry". wxArchiveFSEntry *AddToCache(wxArchiveEntry *entry); void CloseStreams(); @@ -98,8 +100,6 @@ wxArchiveFSCacheDataImpl::wxArchiveFSCacheDataImpl( wxArchiveFSCacheDataImpl::~wxArchiveFSCacheDataImpl() { - WX_CLEAR_HASH_MAP(wxArchiveFSEntryHash, m_hash); - wxArchiveFSEntry *entry = m_begin; while (entry) @@ -114,7 +114,7 @@ wxArchiveFSCacheDataImpl::~wxArchiveFSCacheDataImpl() wxArchiveFSEntry *wxArchiveFSCacheDataImpl::AddToCache(wxArchiveEntry *entry) { - m_hash[entry->GetName(wxPATH_UNIX)] = entry; + m_hash[entry->GetName(wxPATH_UNIX)] = std::unique_ptr(entry); wxArchiveFSEntry *fse = new wxArchiveFSEntry; *m_endptr = fse; (*m_endptr)->entry = entry; @@ -131,10 +131,10 @@ void wxArchiveFSCacheDataImpl::CloseStreams() wxArchiveEntry *wxArchiveFSCacheDataImpl::Get(const wxString& name) { - wxArchiveFSEntryHash::iterator it = m_hash.find(name); + const auto it = m_hash.find(name); if (it != m_hash.end()) - return it->second; + return it->second.get(); if (!m_archive) return nullptr; @@ -254,7 +254,8 @@ wxArchiveFSCacheData& wxArchiveFSCacheData::operator=( // of wxFileSystem. //--------------------------------------------------------------------------- -WX_DECLARE_STRING_HASH_MAP(wxArchiveFSCacheData, wxArchiveFSCacheDataHash); +using wxArchiveFSCacheDataHash = + std::unordered_map; class wxArchiveFSCache { @@ -289,9 +290,9 @@ wxArchiveFSCacheData* wxArchiveFSCache::Add( wxArchiveFSCacheData *wxArchiveFSCache::Get(const wxString& name) { - wxArchiveFSCacheDataHash::iterator it; + const auto it = m_hash.find(name); - if ((it = m_hash.find(name)) != m_hash.end()) + if (it != m_hash.end()) return &it->second; return nullptr; From a3be5fd165172530436f1293f66fd51904d00dff Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:09:33 +0100 Subject: [PATCH 09/37] Use std::unordered_map<> in wxHTTP directly Replace wxStringToStringHashMap with std::unordered_map<>, although still use (private) typedefs for the two different maps storing the cookies and the headers respectively for clarity. Also use a range for loop for iterating over the headers. Include wx/wxcrt.h from http.cpp explicitly because wxAtoi(), declared there, is used in this file, but it was previously only included indirectly via wx/hashmap.h. --- include/wx/protocol/http.h | 18 +++++++++++------- src/common/http.cpp | 6 +++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/wx/protocol/http.h b/include/wx/protocol/http.h index 5053fed714..03d5f012d4 100644 --- a/include/wx/protocol/http.h +++ b/include/wx/protocol/http.h @@ -14,10 +14,11 @@ #if wxUSE_PROTOCOL_HTTP -#include "wx/hashmap.h" #include "wx/protocol/protocol.h" #include "wx/buffer.h" +#include + class WXDLLIMPEXP_NET wxHTTP : public wxProtocol { public: @@ -51,10 +52,13 @@ public: wxDEPRECATED(void SetPostBuffer(const wxString& post_buf)); protected: - typedef wxStringToStringHashMap::iterator wxHeaderIterator; - typedef wxStringToStringHashMap::const_iterator wxHeaderConstIterator; - typedef wxStringToStringHashMap::iterator wxCookieIterator; - typedef wxStringToStringHashMap::const_iterator wxCookieConstIterator; + using wxHeadersMap = std::unordered_map; + typedef wxHeadersMap::iterator wxHeaderIterator; + typedef wxHeadersMap::const_iterator wxHeaderConstIterator; + + using wxCookiesMap = std::unordered_map; + typedef wxCookiesMap::iterator wxCookieIterator; + typedef wxCookiesMap::const_iterator wxCookieConstIterator; bool BuildRequest(const wxString& path, const wxString& method); void SendHeaders(); @@ -75,9 +79,9 @@ protected: // internal variables: wxString m_method; - wxStringToStringHashMap m_cookies; + wxCookiesMap m_cookies; - wxStringToStringHashMap m_headers; + wxHeadersMap m_headers; bool m_read, m_proxy_mode; wxSockAddress *m_addr; diff --git a/src/common/http.cpp b/src/common/http.cpp index 79c4e4b7bb..60dd9dbe4f 100644 --- a/src/common/http.cpp +++ b/src/common/http.cpp @@ -28,6 +28,7 @@ #include "wx/protocol/http.h" #include "wx/sckstrm.h" #include "wx/thread.h" +#include "wx/wxcrt.h" // ---------------------------------------------------------------------------- @@ -227,12 +228,11 @@ wxHTTP::SetPostText(const wxString& contentType, void wxHTTP::SendHeaders() { - typedef wxStringToStringHashMap::iterator iterator; wxString buf; - for (iterator it = m_headers.begin(), en = m_headers.end(); it != en; ++it ) + for ( const auto& kv : m_headers ) { - buf.Printf(wxT("%s: %s\r\n"), it->first.c_str(), it->second.c_str()); + buf.Printf("%s: %s\r\n", kv.first, kv.second); const wxWX2MBbuf cbuf = buf.mb_str(); Write(cbuf, strlen(cbuf)); From 01c73be2bb6e26f3ab14ba98ce7f10794c3e1721 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:10:47 +0100 Subject: [PATCH 10/37] Use a std::unordered_map<> of appropriate type in PNG code Instead of using wxLongToLongHashMap, use the standard container with unsigned long as key type, as this is what is actually used in this code. --- src/common/imagpng.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/imagpng.cpp b/src/common/imagpng.cpp index 0da9536163..6850bce1f1 100644 --- a/src/common/imagpng.cpp +++ b/src/common/imagpng.cpp @@ -35,6 +35,8 @@ // For memcpy #include +#include + // ---------------------------------------------------------------------------- // local functions // ---------------------------------------------------------------------------- @@ -452,7 +454,7 @@ wxPNGHandler::LoadFile(wxImage *image, // SaveFile() palette helpers // ---------------------------------------------------------------------------- -typedef wxLongToLongHashMap PaletteMap; +using PaletteMap = std::unordered_map; static unsigned long PaletteMakeKey(const png_color_8& clr) { From 5adb77018b223bcd2ca8b52677bbcab4afd0bee6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:11:41 +0100 Subject: [PATCH 11/37] Use std::unordered_map<> in wxRichTextXMLHandler Also move the map itself as well as the inline methods using it to the source file to avoid having to include from the header unnecessarily. --- include/wx/richtext/richtextxml.h | 7 ++----- src/richtext/richtextxml.cpp | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/wx/richtext/richtextxml.h b/include/wx/richtext/richtextxml.h index 67b76b6830..5ca8b1c0ab 100644 --- a/include/wx/richtext/richtextxml.h +++ b/include/wx/richtext/richtextxml.h @@ -15,7 +15,6 @@ * Includes */ -#include "wx/hashmap.h" #include "wx/richtext/richtextbuffer.h" #include "wx/richtext/richtextstyles.h" @@ -217,12 +216,12 @@ public: Call with XML node name, C++ class name so that wxRTC can read in the node. If you add a custom object, call this. */ - static void RegisterNodeName(const wxString& nodeName, const wxString& className) { sm_nodeNameToClassMap[nodeName] = className; } + static void RegisterNodeName(const wxString& nodeName, const wxString& className); /** Cleans up the mapping between node name and C++ class. */ - static void ClearNodeToClassMap() { sm_nodeNameToClassMap.clear(); } + static void ClearNodeToClassMap(); protected: #if wxUSE_STREAMS @@ -231,8 +230,6 @@ protected: #endif wxRichTextXMLHelper m_helper; - - static wxStringToStringHashMap sm_nodeNameToClassMap; }; #endif diff --git a/src/richtext/richtextxml.cpp b/src/richtext/richtextxml.cpp index 4814650ab8..91a2f65973 100644 --- a/src/richtext/richtextxml.cpp +++ b/src/richtext/richtextxml.cpp @@ -32,6 +32,8 @@ #include "wx/stopwatch.h" #include "wx/xml/xml.h" +#include + // Set to 1 for slower wxXmlDocument method, 0 for faster direct method. // If we make wxXmlDocument::Save more efficient, we might switch to this // method. @@ -50,7 +52,12 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler, wxRichTextFileHandler); -wxStringToStringHashMap wxRichTextXMLHandler::sm_nodeNameToClassMap; +namespace +{ + +std::unordered_map gs_nodeNameToClassMap; + +} // anonymous namespace void wxRichTextXMLHandler::Init() { @@ -111,12 +118,22 @@ bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer *buffer, wxInputStream& s return success; } +void wxRichTextXMLHandler::RegisterNodeName(const wxString& nodeName, const wxString& className) +{ + gs_nodeNameToClassMap[nodeName] = className; +} + +void wxRichTextXMLHandler::ClearNodeToClassMap() +{ + gs_nodeNameToClassMap.clear(); +} + /// Creates an object given an XML element name wxRichTextObject* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject* WXUNUSED(parent), const wxString& name) const { // The standard node to class mappings are added in wxRichTextModule::OnInit in richtextbuffer.cpp - wxStringToStringHashMap::const_iterator it = sm_nodeNameToClassMap.find(name); - if (it == sm_nodeNameToClassMap.end()) + const auto it = gs_nodeNameToClassMap.find(name); + if (it == gs_nodeNameToClassMap.end()) return nullptr; else return wxDynamicCast(wxCreateDynamicObject(it->second), wxRichTextObject); From 1c70100beac9f595060e0ed971f05be11360a35b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:12:41 +0100 Subject: [PATCH 12/37] Use std::unordered_map<> in the GUI unit test code This allows to use the correct types for the map keys and values too. --- tests/testableframe.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/testableframe.h b/tests/testableframe.h index 515e908800..7626ca6e6f 100644 --- a/tests/testableframe.h +++ b/tests/testableframe.h @@ -7,9 +7,10 @@ /////////////////////////////////////////////////////////////////////////////// #include "wx/frame.h" -#include "wx/hashmap.h" #include "wx/event.h" +#include + class wxTestableFrame : public wxFrame { public: @@ -23,7 +24,7 @@ private: int GetEventCount(wxEventType type); void ClearEventCount(wxEventType type); - wxLongToLongHashMap m_count; + std::unordered_map m_count; }; class EventCounter From 8c5932de547111774666033a635fa080d3643928 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:19:40 +0100 Subject: [PATCH 13/37] Use std::unordered_map<> in wxSimpleHelpProvider This is not nominally backwards-compatible because the existing maps were protected and not private, but there shouldn't be any code using them, so still change them to avoid the ugly hacks with type casts in all directions when using them, and also make them private to emphasize that they must not be used directly. --- include/wx/cshelp.h | 12 +++++------- src/common/cshelp.cpp | 26 ++++++++++---------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/include/wx/cshelp.h b/include/wx/cshelp.h index 33c0734bd4..f3ee47604d 100644 --- a/include/wx/cshelp.h +++ b/include/wx/cshelp.h @@ -17,13 +17,14 @@ #include "wx/help.h" -#include "wx/hashmap.h" #if wxUSE_BMPBUTTON #include "wx/bmpbuttn.h" #endif #include "wx/event.h" +#include + // ---------------------------------------------------------------------------- // classes used to implement context help UI // ---------------------------------------------------------------------------- @@ -194,9 +195,6 @@ private: static wxHelpProvider *ms_helpProvider; }; -WX_DECLARE_EXPORTED_HASH_MAP( wxUIntPtr, wxString, wxIntegerHash, - wxIntegerEqual, wxSimpleHelpProviderHashMap ); - // wxSimpleHelpProvider is an implementation of wxHelpProvider which supports // only plain text help strings and shows the string associated with the // control (if any) in a tooltip @@ -213,11 +211,11 @@ public: virtual void AddHelp(wxWindowID id, const wxString& text) override; virtual void RemoveHelp(wxWindowBase* window) override; -protected: +private: // we use 2 hashes for storing the help strings associated with windows // and the ids - wxSimpleHelpProviderHashMap m_hashWindows, - m_hashIds; + std::unordered_map m_hashWindows; + std::unordered_map m_hashIds; }; // wxHelpControllerHelpProvider is an implementation of wxHelpProvider which supports diff --git a/src/common/cshelp.cpp b/src/common/cshelp.cpp index e99221173a..bd6a7192d5 100644 --- a/src/common/cshelp.cpp +++ b/src/common/cshelp.cpp @@ -308,39 +308,33 @@ wxString wxHelpProvider::GetHelpTextMaybeAtPoint(wxWindowBase *window) // wxSimpleHelpProvider // ---------------------------------------------------------------------------- -#define WINHASH_KEY(w) wxPtrToUInt(w) - wxString wxSimpleHelpProvider::GetHelp(const wxWindowBase *window) { - wxSimpleHelpProviderHashMap::iterator it = m_hashWindows.find(WINHASH_KEY(window)); + const auto it = m_hashWindows.find(window); + if ( it != m_hashWindows.end() ) + return it->second; - if ( it == m_hashWindows.end() ) - { - it = m_hashIds.find(window->GetId()); - if ( it == m_hashIds.end() ) - return wxEmptyString; - } + const auto it2 = m_hashIds.find(window->GetId()); + if ( it2 != m_hashIds.end() ) + return it2->second; - return it->second; + return {}; } void wxSimpleHelpProvider::AddHelp(wxWindowBase *window, const wxString& text) { - m_hashWindows.erase(WINHASH_KEY(window)); - m_hashWindows[WINHASH_KEY(window)] = text; + m_hashWindows[window] = text; } void wxSimpleHelpProvider::AddHelp(wxWindowID id, const wxString& text) { - wxSimpleHelpProviderHashMap::key_type key = (wxSimpleHelpProviderHashMap::key_type)id; - m_hashIds.erase(key); - m_hashIds[key] = text; + m_hashIds[id] = text; } // removes the association void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window) { - m_hashWindows.erase(WINHASH_KEY(window)); + m_hashWindows.erase(window); } bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window) From d3480f58b064a88a0151580ecd44ba7fb9f7a8ab Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:32:11 +0100 Subject: [PATCH 14/37] Use std::unordered_map> in wxMemoryFSHandler Replace a map of raw pointers defined using wx synonym with the direct use of the standard class using smart pointers to simplify code and make it more robust. Don't define wxMemoryFSHash in the global scope any longer, it shouldn't be used by any existing code, but if it is, it's better to prevent it from compiling immediately, as it would be broken anyhow by the change to the map value type. --- include/wx/fs_mem.h | 10 ++++++++-- src/common/fs_mem.cpp | 27 ++++++++++++++------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/include/wx/fs_mem.h b/include/wx/fs_mem.h index 9e6e126bb2..6a40ae1a7b 100644 --- a/include/wx/fs_mem.h +++ b/include/wx/fs_mem.h @@ -15,10 +15,10 @@ #include "wx/filesys.h" -#include "wx/hashmap.h" +#include +#include class wxMemoryFSFile; -WX_DECLARE_STRING_HASH_MAP(wxMemoryFSFile *, wxMemoryFSHash); #if wxUSE_GUI #include "wx/bitmap.h" @@ -59,7 +59,13 @@ protected: // error and returns false if it does exist static bool CheckDoesntExist(const wxString& filename); + // add the given object to m_Hash, taking ownership of the pointer + static void DoAddFile(const wxString& filename, wxMemoryFSFile* file); + +private: // the hash map indexed by the names of the files stored in the memory FS + using wxMemoryFSHash = + std::unordered_map>; static wxMemoryFSHash m_Hash; // the file name currently being searched for, i.e. the argument of the diff --git a/src/common/fs_mem.cpp b/src/common/fs_mem.cpp index f4e943b941..08fbed97c1 100644 --- a/src/common/fs_mem.cpp +++ b/src/common/fs_mem.cpp @@ -77,7 +77,7 @@ private: //-------------------------------------------------------------------------------- -wxMemoryFSHash wxMemoryFSHandlerBase::m_Hash; +wxMemoryFSHandlerBase::wxMemoryFSHash wxMemoryFSHandlerBase::m_Hash; wxMemoryFSHandlerBase::wxMemoryFSHandlerBase() : wxFileSystemHandler() @@ -89,7 +89,6 @@ wxMemoryFSHandlerBase::~wxMemoryFSHandlerBase() // as only one copy of FS handler is supposed to exist, we may silently // delete static data here. (There is no way how to remove FS handler from // wxFileSystem other than releasing _all_ handlers.) - WX_CLEAR_HASH_MAP(wxMemoryFSHash, m_Hash); } bool wxMemoryFSHandlerBase::CanOpen(const wxString& location) @@ -104,7 +103,7 @@ wxFSFile * wxMemoryFSHandlerBase::OpenFile(wxFileSystem& WXUNUSED(fs), if ( i == m_Hash.end() ) return nullptr; - const wxMemoryFSFile * const obj = i->second; + const auto& obj = i->second; return new wxFSFile ( @@ -175,6 +174,13 @@ bool wxMemoryFSHandlerBase::CheckDoesntExist(const wxString& filename) } +/*static*/ +void wxMemoryFSHandlerBase::DoAddFile(const wxString& filename, + wxMemoryFSFile* file) +{ + m_Hash[filename] = std::unique_ptr(file); +} + /*static*/ void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename, const wxString& textdata, @@ -199,7 +205,7 @@ void wxMemoryFSHandlerBase::AddFileWithMimeType(const wxString& filename, if ( !CheckDoesntExist(filename) ) return; - m_Hash[filename] = new wxMemoryFSFile(binarydata, size, mimetype); + DoAddFile(filename, new wxMemoryFSFile(binarydata, size, mimetype)); } /*static*/ @@ -221,17 +227,12 @@ void wxMemoryFSHandlerBase::AddFile(const wxString& filename, /*static*/ void wxMemoryFSHandlerBase::RemoveFile(const wxString& filename) { - wxMemoryFSHash::iterator i = m_Hash.find(filename); - if ( i == m_Hash.end() ) + if ( !m_Hash.erase(filename) ) { wxLogError(_("Trying to remove file '%s' from memory VFS, " "but it is not loaded!"), filename); - return; } - - delete i->second; - m_Hash.erase(i); } #endif // wxUSE_BASE @@ -250,11 +251,11 @@ wxMemoryFSHandler::AddFile(const wxString& filename, wxMemoryOutputStream mems; if ( image.IsOk() && image.SaveFile(mems, type) ) { - m_Hash[filename] = new wxMemoryFSFile - ( + DoAddFile(filename, new wxMemoryFSFile + ( mems, wxImage::FindHandler(type)->GetMimeType() - ); + )); } else { From 070f778dcd471dc30af791d2cda492aff93b968c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:36:21 +0100 Subject: [PATCH 15/37] Use std::unordered_map<> in wxFileSystemWatcher code Use the standard containers directly instead of defining a typedef for it using wx macros. --- include/wx/fswatcher.h | 5 +++-- include/wx/private/fswatcher.h | 8 +++++--- src/osx/fswatcher_fsevents.cpp | 31 ++++++++++++++++--------------- src/unix/fswatcher_inotify.cpp | 8 ++++---- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/include/wx/fswatcher.h b/include/wx/fswatcher.h index b28d2f2d74..b696d74f44 100644 --- a/include/wx/fswatcher.h +++ b/include/wx/fswatcher.h @@ -19,7 +19,8 @@ #include "wx/evtloop.h" #include "wx/filename.h" #include "wx/dir.h" -#include "wx/hashmap.h" + +#include #define wxTRACE_FSWATCHER "fswatcher" @@ -279,7 +280,7 @@ protected: int m_refcount; }; -WX_DECLARE_STRING_HASH_MAP(wxFSWatchInfo, wxFSWatchInfoMap); +using wxFSWatchInfoMap = std::unordered_map; /** * Encapsulation of platform-specific file system event mechanism diff --git a/include/wx/private/fswatcher.h b/include/wx/private/fswatcher.h index d3602f7861..d6de03b9d7 100644 --- a/include/wx/private/fswatcher.h +++ b/include/wx/private/fswatcher.h @@ -12,20 +12,22 @@ #include "wx/sharedptr.h" +#include + #ifdef wxHAS_INOTIFY class wxFSWatchEntryUnix; #define wxFSWatchEntry wxFSWatchEntryUnix - WX_DECLARE_STRING_HASH_MAP(wxSharedPtr,wxFSWatchEntries); + using wxFSWatchEntries = std::unordered_map>; #include "wx/unix/private/fswatcher_inotify.h" #elif defined(wxHAS_KQUEUE) class wxFSWatchEntryKq; #define wxFSWatchEntry wxFSWatchEntryKq - WX_DECLARE_STRING_HASH_MAP(wxSharedPtr,wxFSWatchEntries); + using wxFSWatchEntries = std::unordered_map>; #include "wx/unix/private/fswatcher_kqueue.h" #elif defined(__WINDOWS__) class wxFSWatchEntryMSW; #define wxFSWatchEntry wxFSWatchEntryMSW - WX_DECLARE_STRING_HASH_MAP(wxSharedPtr,wxFSWatchEntries); + using wxFSWatchEntries = std::unordered_map>; #include "wx/msw/private/fswatcher.h" #else #define wxFSWatchEntry wxFSWatchEntryPolling diff --git a/src/osx/fswatcher_fsevents.cpp b/src/osx/fswatcher_fsevents.cpp index cea11ade62..8cde8c6b5b 100644 --- a/src/osx/fswatcher_fsevents.cpp +++ b/src/osx/fswatcher_fsevents.cpp @@ -21,6 +21,8 @@ #include #include +#include + // A small class that we will give the FSEvents // framework, which will be forwarded to the function // that gets called when files change. @@ -275,12 +277,10 @@ static void wxDeleteContext(const void* context) delete watcherContext; } -WX_DECLARE_STRING_HASH_MAP(FSEventStreamRef, FSEventStreamRefMap); - struct wxFsEventsFileSystemWatcher::PrivateData { // map of path => FSEventStreamRef - FSEventStreamRefMap m_streams; + std::unordered_map m_streams; }; wxFsEventsFileSystemWatcher::wxFsEventsFileSystemWatcher() @@ -408,7 +408,7 @@ bool wxFsEventsFileSystemWatcher::RemoveTree(const wxFileName& path) } } - FSEventStreamRefMap::iterator it = m_pImpl->m_streams.find(canonical); + const auto it = m_pImpl->m_streams.find(canonical); bool removed = false; if ( it != m_pImpl->m_streams.end() ) { @@ -425,17 +425,18 @@ bool wxFsEventsFileSystemWatcher::RemoveAll() { // remove all watches created with Add() bool ret = wxKqueueFileSystemWatcher::RemoveAll(); - FSEventStreamRefMap::iterator it = m_pImpl->m_streams.begin(); - while ( it != m_pImpl->m_streams.end() ) + if ( m_pImpl->m_streams.empty() ) + return ret; + + for ( const auto& kv : m_pImpl->m_streams ) { - FSEventStreamStop(it->second); - FSEventStreamInvalidate(it->second); - FSEventStreamRelease(it->second); - ++it; - ret = true; + FSEventStreamRef stream = kv.second; + FSEventStreamStop(stream); + FSEventStreamInvalidate(stream); + FSEventStreamRelease(stream); } m_pImpl->m_streams.clear(); - return ret; + return true; } void wxFsEventsFileSystemWatcher::PostChange(const wxFileName& oldFileName, @@ -510,10 +511,10 @@ int wxFsEventsFileSystemWatcher::GetWatchedPaths(wxArrayString* paths) const return 0; } wxFileSystemWatcherBase::GetWatchedPaths(paths); - FSEventStreamRefMap::const_iterator it = m_pImpl->m_streams.begin(); - for ( ; it != m_pImpl->m_streams.end(); ++it ) + + for ( const auto& kv : m_pImpl->m_streams ) { - paths->push_back(it->first); + paths->push_back(kv.first); } return paths->size(); } diff --git a/src/unix/fswatcher_inotify.cpp b/src/unix/fswatcher_inotify.cpp index a0a381dfea..1e27aec4a0 100644 --- a/src/unix/fswatcher_inotify.cpp +++ b/src/unix/fswatcher_inotify.cpp @@ -21,17 +21,17 @@ #include #include "wx/private/fswatcher.h" +#include + // ============================================================================ // wxFSWatcherImpl implementation & helper wxFSWSourceHandler implementation // ============================================================================ // inotify watch descriptor => wxFSWatchEntry* map -WX_DECLARE_HASH_MAP(int, wxFSWatchEntry*, wxIntegerHash, wxIntegerEqual, - wxFSWatchEntryDescriptors); +using wxFSWatchEntryDescriptors = std::unordered_map; // inotify event cookie => inotify_event* map -WX_DECLARE_HASH_MAP(int, inotify_event*, wxIntegerHash, wxIntegerEqual, - wxInotifyCookies); +using wxInotifyCookies = std::unordered_map; /** * Helper class encapsulating inotify mechanism From 1ac57fbcc40e2ee042800d3c13c74cc67188fe6e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:45:49 +0100 Subject: [PATCH 16/37] Use std::unordered_map<> in wxColourDatabase Stop storing pointers to wxColour in this map when we can just store wxColour objects themselves. Also avoid dependency on in the header by only defining the map in the source file: as wxColourDatabase already used only a pointer to the map, rather than the map object, this was easy to do. --- include/wx/gdicmn.h | 3 +- src/common/gdicmn.cpp | 73 ++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/include/wx/gdicmn.h b/include/wx/gdicmn.h index 2de48183c9..46de754f82 100644 --- a/include/wx/gdicmn.h +++ b/include/wx/gdicmn.h @@ -19,7 +19,6 @@ #include "wx/list.h" #include "wx/string.h" #include "wx/fontenc.h" -#include "wx/hashmap.h" #include "wx/math.h" // --------------------------------------------------------------------------- @@ -904,7 +903,7 @@ protected: wxList list; }; -WX_DECLARE_STRING_HASH_MAP(wxColour*, wxStringToColourHashMap); +class wxStringToColourHashMap; class WXDLLIMPEXP_CORE wxColourDatabase { diff --git a/src/common/gdicmn.cpp b/src/common/gdicmn.cpp index 77a79438f4..657fdc7eae 100644 --- a/src/common/gdicmn.cpp +++ b/src/common/gdicmn.cpp @@ -32,6 +32,7 @@ #include "wx/math.h" #endif +#include wxIMPLEMENT_ABSTRACT_CLASS(wxGDIObject, wxObject); @@ -259,6 +260,27 @@ wxRealPoint::wxRealPoint(const wxPoint& pt) // wxColourDatabase // ============================================================================ +// Due to a bug mentioned in wx/hashmap.h we have to use aggregation here and +// define a simple accessor function below. +// +// FIXME-GCC-4.8: Remove this and just inherit from std::unordered_map<>. +class wxStringToColourHashMap +{ +public: + std::unordered_map m_colours; +}; + +namespace +{ + +inline std::unordered_map& +GetColours(wxStringToColourHashMap* map) +{ + return map->m_colours; +} + +} // anonymous namespace + // ---------------------------------------------------------------------------- // wxColourDatabase ctor/dtor // ---------------------------------------------------------------------------- @@ -271,12 +293,7 @@ wxColourDatabase::wxColourDatabase () wxColourDatabase::~wxColourDatabase () { - if ( m_map ) - { - WX_CLEAR_HASH_MAP(wxStringToColourHashMap, *m_map); - - delete m_map; - } + delete m_map; } // Colour database stuff @@ -375,7 +392,7 @@ void wxColourDatabase::Initialize() for ( n = 0; n < WXSIZEOF(wxColourTable); n++ ) { const wxColourDesc& cc = wxColourTable[n]; - (*m_map)[cc.name] = new wxColour(cc.r, cc.g, cc.b); + GetColours(m_map)[cc.name] = wxColour(cc.r, cc.g, cc.b); } } @@ -400,16 +417,17 @@ void wxColourDatabase::AddColour(const wxString& name, const wxColour& colour) colNameAlt.clear(); } - wxStringToColourHashMap::iterator it = m_map->find(colName); - if ( it == m_map->end() && !colNameAlt.empty() ) - it = m_map->find(colNameAlt); - if ( it != m_map->end() ) + auto& map = GetColours(m_map); + auto it = map.find(colName); + if ( it == map.end() && !colNameAlt.empty() ) + it = map.find(colNameAlt); + if ( it != map.end() ) { - *(it->second) = colour; + it->second = colour; } else // new colour { - (*m_map)[colName] = new wxColour(colour); + map[colName] = wxColour(colour); } } @@ -425,11 +443,12 @@ wxColour wxColourDatabase::Find(const wxString& colour) const if ( !colNameAlt.Replace(wxT("GRAY"), wxT("GREY")) ) colNameAlt.clear(); - wxStringToColourHashMap::iterator it = m_map->find(colName); - if ( it == m_map->end() && !colNameAlt.empty() ) - it = m_map->find(colNameAlt); - if ( it != m_map->end() ) - return *(it->second); + const auto& map = GetColours(m_map); + auto it = map.find(colName); + if ( it == map.end() && !colNameAlt.empty() ) + it = map.find(colNameAlt); + if ( it != map.end() ) + return it->second; // we did not find any result in existing colours: // we won't use wxString -> wxColour conversion because the @@ -444,12 +463,10 @@ wxString wxColourDatabase::FindName(const wxColour& colour) const wxColourDatabase * const self = wxConstCast(this, wxColourDatabase); self->Initialize(); - typedef wxStringToColourHashMap::iterator iterator; - - for ( iterator it = m_map->begin(), en = m_map->end(); it != en; ++it ) + for ( const auto& kv : GetColours(m_map) ) { - if ( *(it->second) == colour ) - return it->first; + if ( kv.second == colour ) + return kv.first; } return wxEmptyString; @@ -460,13 +477,13 @@ wxVector wxColourDatabase::GetAllNames() const wxColourDatabase * const self = wxConstCast(this, wxColourDatabase); self->Initialize(); + const auto& map = GetColours(m_map); + wxVector names; - names.reserve(m_map->size()); + names.reserve(map.size()); - typedef wxStringToColourHashMap::iterator iterator; - - for ( iterator it = m_map->begin(), en = m_map->end(); it != en; ++it ) - names.push_back(it->first); + for ( const auto& kv : map ) + names.push_back(kv.first); return names; } From 93ae99cba518a52af0f6e43c45d9aaeee4c37907 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 20:57:33 +0100 Subject: [PATCH 17/37] Use standard containers in wxHtmlParser Replace wx synonyms for std::unordered_map<> and unordered_set<> defined using macros with the standard classes themselves and also replace a wxVector<> used for a stack with std::stack<>. Also store std::unique_ptr<> rather than raw pointers in the various containers that own the pointers to make the code more clear and robust. --- include/wx/html/htmlpars.h | 22 +++++++++------------- src/html/htmlpars.cpp | 14 ++++++-------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/include/wx/html/htmlpars.h b/include/wx/html/htmlpars.h index bc4be92280..17793e76ff 100644 --- a/include/wx/html/htmlpars.h +++ b/include/wx/html/htmlpars.h @@ -14,11 +14,14 @@ #include "wx/html/htmltag.h" #include "wx/filesys.h" -#include "wx/hashmap.h" -#include "wx/hashset.h" #include "wx/vector.h" #include "wx/fontenc.h" +#include +#include +#include +#include + class WXDLLIMPEXP_FWD_BASE wxMBConv; class WXDLLIMPEXP_FWD_HTML wxHtmlParser; class WXDLLIMPEXP_FWD_HTML wxHtmlTagHandler; @@ -27,13 +30,7 @@ class WXDLLIMPEXP_FWD_HTML wxHtmlEntitiesParser; class wxHtmlTextPieces; class wxHtmlParserState; -WX_DECLARE_HASH_SET_WITH_DECL_PTR(wxHtmlTagHandler*, - wxPointerHash, wxPointerEqual, - wxHtmlTagHandlersSet, - class WXDLLIMPEXP_HTML); -WX_DECLARE_STRING_HASH_MAP_WITH_DECL(wxHtmlTagHandler*, - wxHtmlTagHandlersHash, - class WXDLLIMPEXP_HTML); +using wxHtmlTagHandlersHash = std::unordered_map; enum wxHtmlURLType @@ -185,9 +182,8 @@ protected: // (see wxHtmlWinParser for details about filling it) // m_HandlersHash is for random access based on knowledge of tag name (BR, P, etc.) // it may (and often does) contain more references to one object - // m_HandlersList is list of all handlers and it is guaranteed to contain - // only one reference to each handler instance. - wxHtmlTagHandlersSet m_HandlersSet; + // m_HandlersSet is set of all handlers and owns its elements. + std::unordered_set> m_HandlersSet; wxHtmlTagHandlersHash m_HandlersHash; wxDECLARE_NO_COPY_CLASS(wxHtmlParser); @@ -195,7 +191,7 @@ protected: // class for opening files (file system) wxFileSystem *m_FS; // handlers stack used by PushTagHandler and PopTagHandler - wxVector m_HandlersStack; + std::stack> m_HandlersStack; // entity parse wxHtmlEntitiesParser *m_entitiesParser; diff --git a/src/html/htmlpars.cpp b/src/html/htmlpars.cpp index 9312591b13..2fe5381c49 100644 --- a/src/html/htmlpars.cpp +++ b/src/html/htmlpars.cpp @@ -86,8 +86,6 @@ wxHtmlParser::~wxHtmlParser() while (RestoreState()) {} DestroyDOMTree(); - WX_CLEAR_ARRAY(m_HandlersStack); - WX_CLEAR_HASH_SET(wxHtmlTagHandlersSet, m_HandlersSet); delete m_entitiesParser; delete m_Source; } @@ -331,7 +329,7 @@ void wxHtmlParser::AddTagHandler(wxHtmlTagHandler *handler) while (tokenizer.HasMoreTokens()) m_HandlersHash[tokenizer.GetNextToken()] = handler; - m_HandlersSet.insert(handler); + m_HandlersSet.insert(std::unique_ptr(handler)); handler->SetParser(this); } @@ -341,7 +339,9 @@ void wxHtmlParser::PushTagHandler(wxHtmlTagHandler *handler, const wxString& tag wxStringTokenizer tokenizer(tags, wxT(", ")); wxString key; - m_HandlersStack.push_back(new wxHtmlTagHandlersHash(m_HandlersHash)); + m_HandlersStack.push(std::unique_ptr( + new wxHtmlTagHandlersHash(m_HandlersHash)) + ); while (tokenizer.HasMoreTokens()) { @@ -355,10 +355,8 @@ void wxHtmlParser::PopTagHandler() wxCHECK_RET( !m_HandlersStack.empty(), "attempt to remove HTML tag handler from empty stack" ); - wxHtmlTagHandlersHash *prev = m_HandlersStack.back(); - m_HandlersStack.pop_back(); - m_HandlersHash = *prev; - delete prev; + m_HandlersHash = *m_HandlersStack.top(); + m_HandlersStack.pop(); } void wxHtmlParser::SetSourceAndSaveState(const wxString& src) From 99594f849735b1e40dad3224535878be0aa0f113 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 21:00:19 +0100 Subject: [PATCH 18/37] Use std::unordered_set<> in wxThreadSpecificInfo Replace a macro-based synonym with the standard container itself. --- include/wx/private/threadinfo.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/wx/private/threadinfo.h b/include/wx/private/threadinfo.h index cbdc6df98d..b9b15317a8 100644 --- a/include/wx/private/threadinfo.h +++ b/include/wx/private/threadinfo.h @@ -15,9 +15,11 @@ class WXDLLIMPEXP_FWD_BASE wxLog; #if wxUSE_INTL -#include "wx/hashset.h" -WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual, - wxLocaleUntranslatedStrings); +#include "wx/string.h" + +#include + +using wxLocaleUntranslatedStrings = std::unordered_set; #endif From 8435566dbb8d3145d4e21eeaaa3e7f8939c3f46c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 21:02:12 +0100 Subject: [PATCH 19/37] Use std::unordered_map<> in wxPGProperty Replace a macro-based synonym with the standard container itself. --- include/wx/propgrid/propgriddefs.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/wx/propgrid/propgriddefs.h b/include/wx/propgrid/propgriddefs.h index 0ef842a752..311974099e 100644 --- a/include/wx/propgrid/propgriddefs.h +++ b/include/wx/propgrid/propgriddefs.h @@ -16,13 +16,13 @@ #if wxUSE_PROPGRID #include "wx/colour.h" -#include "wx/hashset.h" class WXDLLIMPEXP_FWD_CORE wxPoint; class WXDLLIMPEXP_FWD_CORE wxSize; class WXDLLIMPEXP_FWD_CORE wxFont; #include +#include // ----------------------------------------------------------------------- @@ -125,9 +125,7 @@ WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(wxPGProperty*, wxArrayPGProperty, wxBaseArrayPtrVoid, class WXDLLIMPEXP_PROPGRID); -WX_DECLARE_STRING_HASH_MAP_WITH_DECL(wxString, - wxPGHashMapS2S, - class WXDLLIMPEXP_PROPGRID); +using wxPGHashMapS2S = std::unordered_map; #if WXWIN_COMPATIBILITY_3_0 WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(wxObject*, wxArrayPGObject, From aef6ce760566679fc504cc22f180bf2e81a2fe0b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 21:05:38 +0100 Subject: [PATCH 20/37] Use std::unordered_map<> in wxAny code Replace a macro-based synonym with the standard container itself and use the correct "const wxAnyValueType*" type for its keys. Also remove the unnecessary synonym for m_anyToVariant. --- src/common/any.cpp | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/common/any.cpp b/src/common/any.cpp index f86c9a2764..40ceb06d10 100644 --- a/src/common/any.cpp +++ b/src/common/any.cpp @@ -23,10 +23,9 @@ #include "wx/vector.h" #include "wx/module.h" -#include "wx/hashmap.h" -#include "wx/hashset.h" #include +#include using namespace wxPrivate; @@ -36,11 +35,13 @@ using namespace wxPrivate; // wxAnyValueTypeGlobals //------------------------------------------------------------------------- -WX_DECLARE_HASH_MAP(wxAnyValueType*, - wxVariantDataFactory, - wxPointerHash, - wxPointerEqual, - wxAnyTypeToVariantDataFactoryMap); +namespace +{ + +using wxAnyTypeToVariantDataFactoryMap = + std::unordered_map; + +} // anonymous namespace // // Helper class to manage global variables related to type conversion @@ -64,16 +65,10 @@ public: // Find wxVariantData factory function for given value type, // (or compatible, if possible) - wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type_) + wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type) { - // Ideally we'd have the hash map of type 'const wxAnyValueType*', - // but WX_DECLARE_HASH_MAP() has some trouble with it. - wxAnyValueType* type = const_cast(type_); - - wxAnyTypeToVariantDataFactoryMap& anyToVariant = m_anyToVariant; - wxAnyTypeToVariantDataFactoryMap::const_iterator it; - it = anyToVariant.find(type); - if ( it != anyToVariant.end() ) + auto it = m_anyToVariant.find(type); + if ( it != m_anyToVariant.end() ) return it->second; // Not found, handle pre-registrations @@ -89,23 +84,23 @@ public: // now been properly initialized, so remove the // pre-registration entry and move data to anyToVarian // map. - anyToVariant[assocType] = reg->GetFactory(); + m_anyToVariant[assocType] = reg->GetFactory(); m_anyToVariantRegs.erase( m_anyToVariantRegs.begin() + i ); } } // Then try again - it = anyToVariant.find(type); - if ( it != anyToVariant.end() ) + it = m_anyToVariant.find(type); + if ( it != m_anyToVariant.end() ) return it->second; // Finally, attempt to find a compatible type - for ( it = anyToVariant.begin(); it != anyToVariant.end(); ++it ) + for ( auto& kv : m_anyToVariant ) { - if ( type->IsSameType(it->first) ) + if ( type->IsSameType(kv.first) ) { - wxVariantDataFactory f = it->second; - anyToVariant[type] = f; + wxVariantDataFactory f = kv.second; + m_anyToVariant[type] = f; return f; } } From 22acc3f67d92eca9ae6ca5f00f96786ad2959d78 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 21:08:28 +0100 Subject: [PATCH 21/37] Use std::unordered_set<> in wxrc code Replace a macro-based synonym with the standard container itself. Also use range for loop for iteration over it. --- utils/wxrc/wxrc.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/utils/wxrc/wxrc.cpp b/utils/wxrc/wxrc.cpp index 137e6978eb..7473d9a206 100644 --- a/utils/wxrc/wxrc.cpp +++ b/utils/wxrc/wxrc.cpp @@ -24,11 +24,10 @@ #include "wx/filename.h" #include "wx/wfstream.h" #include "wx/utils.h" -#include "wx/hashset.h" #include "wx/mimetype.h" #include "wx/vector.h" -WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual, StringSet); +#include class XRCWidgetData { @@ -51,7 +50,7 @@ class XRCWndClassData private: wxString m_className; wxString m_parentClassName; - StringSet m_ancestorClassNames; + std::unordered_set m_ancestorClassNames; ArrayOfXRCWidgetData m_wdata; void BrowseXmlNode(wxXmlNode* node) @@ -184,11 +183,9 @@ public: wxT(" }\n") wxT("};\n")); - for ( StringSet::const_iterator it = m_ancestorClassNames.begin(); - it != m_ancestorClassNames.end(); - ++it ) + for ( const auto& name : m_ancestorClassNames ) { - file.Write(m_className + wxT("(") + *it + wxT(" *parent){\n") + + file.Write(m_className + wxT("(") + name + wxT(" *parent){\n") + wxT(" InitWidgetsFromXRC((wxWindow *)parent);\n") wxT(" }\n") wxT("};\n")); From 73c0998cd9422d52378084331e0f95b52600df89 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 21:21:08 +0100 Subject: [PATCH 22/37] Use std::unordered_map<> in HeightCache private class Replace a wx hash map of raw pointers with a standard container of objects. --- include/wx/generic/private/rowheightcache.h | 11 +++-- src/generic/rowheightcache.cpp | 50 ++++++++------------- 2 files changed, 23 insertions(+), 38 deletions(-) diff --git a/include/wx/generic/private/rowheightcache.h b/include/wx/generic/private/rowheightcache.h index 9136a3863c..b8dea2fdef 100644 --- a/include/wx/generic/private/rowheightcache.h +++ b/include/wx/generic/private/rowheightcache.h @@ -10,8 +10,8 @@ #ifndef _WX_PRIVATE_ROWHEIGHTCACHE_H_ #define _WX_PRIVATE_ROWHEIGHTCACHE_H_ -#include "wx/hashmap.h" -#include "wx/vector.h" +#include +#include // struct describing a range of rows which contains rows .. struct RowRange @@ -66,7 +66,7 @@ public: unsigned int GetSize() const { return m_ranges.size(); } private: - wxVector m_ranges; + std::vector m_ranges; /** If a new row index was inserted, Cleanup() checks if the neighbour @@ -76,9 +76,6 @@ private: void CleanUp(unsigned int idx); }; -WX_DECLARE_HASH_MAP(unsigned int, RowRanges*, wxIntegerHash, wxIntegerEqual, - HeightToRowRangesMap); - /** HeightCache implements a cache mechanism for wxDataViewCtrl. @@ -148,6 +145,8 @@ public: void Clear(); private: + using HeightToRowRangesMap = std::unordered_map; + HeightToRowRangesMap m_heightToRowRange; }; diff --git a/src/generic/rowheightcache.cpp b/src/generic/rowheightcache.cpp index 04a9261220..3514addd6a 100644 --- a/src/generic/rowheightcache.cpp +++ b/src/generic/rowheightcache.cpp @@ -193,17 +193,17 @@ bool HeightCache::GetLineInfo(unsigned int row, int &start, int &height) { int y = 0; bool found = false; - HeightToRowRangesMap::iterator it; - for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + + for ( const auto& kv : m_heightToRowRange ) { - int rowHeight = it->first; - RowRanges* rowRanges = it->second; - if (rowRanges->Has(row)) + int rowHeight = kv.first; + const RowRanges& rowRanges = kv.second; + if (rowRanges.Has(row)) { height = rowHeight; found = true; } - y += rowHeight * (rowRanges->CountTo(row)); + y += rowHeight * (rowRanges.CountTo(row)); } if (found) { @@ -220,12 +220,11 @@ bool HeightCache::GetLineStart(unsigned int row, int &start) bool HeightCache::GetLineHeight(unsigned int row, int &height) { - HeightToRowRangesMap::iterator it; - for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + for ( const auto& kv : m_heightToRowRange ) { - int rowHeight = it->first; - RowRanges* rowRanges = it->second; - if (rowRanges->Has(row)) + int rowHeight = kv.first; + const RowRanges& rowRanges = kv.second; + if (rowRanges.Has(row)) { height = rowHeight; return true; @@ -237,11 +236,11 @@ bool HeightCache::GetLineHeight(unsigned int row, int &height) bool HeightCache::GetLineAt(int y, unsigned int &row) { unsigned int total = 0; - HeightToRowRangesMap::iterator it; - for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + + for ( const auto& kv : m_heightToRowRange ) { - RowRanges* rowRanges = it->second; - total += rowRanges->CountAll(); + const RowRanges& rowRanges = kv.second; + total += rowRanges.CountAll(); } if (total == 0) @@ -292,33 +291,20 @@ bool HeightCache::GetLineAt(int y, unsigned int &row) void HeightCache::Put(unsigned int row, int height) { - RowRanges *rowRanges = m_heightToRowRange[height]; - if (rowRanges == nullptr) - { - rowRanges = new RowRanges(); - m_heightToRowRange[height] = rowRanges; - } - rowRanges->Add(row); + m_heightToRowRange[height].Add(row); } void HeightCache::Remove(unsigned int row) { - HeightToRowRangesMap::iterator it; - for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + for ( auto& kv : m_heightToRowRange ) { - RowRanges* rowRanges = it->second; - rowRanges->Remove(row); + RowRanges& rowRanges = kv.second; + rowRanges.Remove(row); } } void HeightCache::Clear() { - HeightToRowRangesMap::iterator it; - for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) - { - RowRanges* rowRanges = it->second; - delete rowRanges; - } m_heightToRowRange.clear(); } From 86bf35cbc70ceccb1301ad90f1752dd2870c1437 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 21:25:48 +0100 Subject: [PATCH 23/37] Use std::unordered_map<> in wxWebView implementation Replace a wx hash map of handlers with the standard container. --- include/wx/msw/private/webview_edge.h | 5 +++-- include/wx/osx/webview_webkit.h | 4 +++- src/msw/webview_edge.cpp | 11 +++++------ src/osx/webview_webkit.mm | 6 +++--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index c3e5fe0fb6..6e3a35a00c 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -14,7 +14,8 @@ #include "wx/dynlib.h" #endif #include "wx/msw/private/comptr.h" -#include "wx/hashmap.h" + +#include #include @@ -44,7 +45,7 @@ __CRT_UUID_DECL(ICoreWebView2WebResourceRequestedEventHandler, 0xab00b74c, 0x15f __CRT_UUID_DECL(ICoreWebView2WindowCloseRequestedEventHandler, 0x5c19e9e0,0x092f,0x486b, 0xaf,0xfa,0xca,0x82,0x31,0x91,0x30,0x39); #endif -WX_DECLARE_STRING_HASH_MAP(wxSharedPtr, wxStringToWebHandlerMap); +using wxStringToWebHandlerMap = std::unordered_map>; class wxWebViewWindowFeaturesEdge; diff --git a/include/wx/osx/webview_webkit.h b/include/wx/osx/webview_webkit.h index e6a7c84dc2..d254e7e378 100644 --- a/include/wx/osx/webview_webkit.h +++ b/include/wx/osx/webview_webkit.h @@ -21,11 +21,13 @@ #include "wx/osx/core/objcid.h" +#include + // ---------------------------------------------------------------------------- // Web Kit Control // ---------------------------------------------------------------------------- -WX_DECLARE_STRING_HASH_MAP(wxSharedPtr, wxStringToWebHandlerMap); +using wxStringToWebHandlerMap = std::unordered_map>; class wxWebViewConfigurationImplWebKit; diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 1bca4e3bea..1dae4dc9c8 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -852,9 +852,9 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control &m_windowCloseRequestedToken); // Register handlers - for (wxStringToWebHandlerMap::iterator it = m_handlers.begin(); it != m_handlers.end(); it++) + for (const auto& kv : m_handlers) { - wxString filterURI = wxString::Format("*://%s/*", it->first); + wxString filterURI = wxString::Format("*://%s/*", kv.first); m_webView->AddWebResourceRequestedFilter(filterURI.wc_str(), COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL); } @@ -1069,14 +1069,13 @@ void wxWebViewEdge::LoadURL(const wxString& url) if (!m_impl->m_handlers.empty()) { // Emulate custom protocol support for LoadURL() - for (wxStringToWebHandlerMap::iterator it = m_impl->m_handlers.begin(); - it != m_impl->m_handlers.end(); it++) + for (const auto& kv : m_impl->m_handlers) { - wxString scheme = it->second->GetName() + ":"; + wxString scheme = kv.second->GetName() + ":"; if (navURL.StartsWith(scheme)) { navURL.Remove(0, scheme.Length()); - navURL.insert(0, "https://" + it->second->GetVirtualHost() + "/"); + navURL.insert(0, "https://" + kv.second->GetVirtualHost() + "/"); break; } } diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index 1f608cdaed..a58da3ac5f 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -243,10 +243,10 @@ bool wxWebViewWebKit::Create(wxWindow *parent, #if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 if ( WX_IS_MACOS_AVAILABLE(10, 13) ) { - for (wxStringToWebHandlerMap::iterator it = m_handlers.begin(); it != m_handlers.end(); it++) + for (const auto& kv : m_handlers) { - [webViewConfig setURLSchemeHandler:[[WebViewCustomProtocol alloc] initWithHandler:it->second.get()] - forURLScheme:wxCFStringRef(it->first).AsNSString()]; + [webViewConfig setURLSchemeHandler:[[WebViewCustomProtocol alloc] initWithHandler:kv.second.get()] + forURLScheme:wxCFStringRef(kv.first).AsNSString()]; } } else From 7ce71c395b565e812292c7e1ac96f41381ccea1e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:24:14 +0100 Subject: [PATCH 24/37] Refactor wxMSW wxTreeCtrl code to avoid repetition Factor out the common part of SetItemFont(), SetItemTextColour() and SetItemBackgroundColour() into a new helper function. No real changes. --- include/wx/msw/treectrl.h | 4 ++++ src/msw/treectrl.cpp | 47 ++++++++++----------------------------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index dc13d9aed9..dfda459ff5 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -306,6 +306,10 @@ private: bool MSWDeleteItem(const wxTreeItemId& item); + // Return guaranteed non-null non-owning pointer to the attribute for the + // given item. + wxItemAttr* DoGetAttrPtr(const wxTreeItemId& item); + // the hash storing the items attributes (indexed by item ids) wxMapTreeAttr m_attrs; diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 8f9c9d52a4..205137264f 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -1185,11 +1185,8 @@ wxFont wxTreeCtrl::GetItemFont(const wxTreeItemId& item) const return it == m_attrs.end() ? wxNullFont : it->second->GetFont(); } -void wxTreeCtrl::SetItemTextColour(const wxTreeItemId& item, - const wxColour& col) +wxItemAttr* wxTreeCtrl::DoGetAttrPtr(const wxTreeItemId& item) { - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - wxItemAttr *attr; wxMapTreeAttr::iterator it = m_attrs.find(item.m_pItem); if ( it == m_attrs.end() ) @@ -1204,7 +1201,15 @@ void wxTreeCtrl::SetItemTextColour(const wxTreeItemId& item, attr = it->second; } - attr->SetTextColour(col); + return attr; +} + +void wxTreeCtrl::SetItemTextColour(const wxTreeItemId& item, + const wxColour& col) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + DoGetAttrPtr(item)->SetTextColour(col); RefreshItem(item); } @@ -1214,21 +1219,7 @@ void wxTreeCtrl::SetItemBackgroundColour(const wxTreeItemId& item, { wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - wxItemAttr *attr; - wxMapTreeAttr::iterator it = m_attrs.find(item.m_pItem); - if ( it == m_attrs.end() ) - { - m_hasAnyAttr = true; - - m_attrs[item.m_pItem] = - attr = new wxItemAttr; - } - else // already in the hash - { - attr = it->second; - } - - attr->SetBackgroundColour(col); + DoGetAttrPtr(item)->SetBackgroundColour(col); RefreshItem(item); } @@ -1237,23 +1228,9 @@ void wxTreeCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font) { wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - wxItemAttr *attr; - wxMapTreeAttr::iterator it = m_attrs.find(item.m_pItem); - if ( it == m_attrs.end() ) - { - m_hasAnyAttr = true; - - m_attrs[item.m_pItem] = - attr = new wxItemAttr; - } - else // already in the hash - { - attr = it->second; - } - wxFont f = font; f.WXAdjustToPPI(GetDPI()); - attr->SetFont(f); + DoGetAttrPtr(item)->SetFont(f); // Reset the item's text to ensure that the bounding rect will be adjusted // for the new font. From f75929cfa6f0b3c07d96dcb2e2a3476348a0d3ab Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:29:48 +0100 Subject: [PATCH 25/37] Move wxTreeCtrl ctors out of line This is mostly done in preparation for the upcoming change, but already fixes one minor inefficiency: we now call Init() from non-default ctor instead of doing it from Create(), so that it's only called once when the default ctor used instead of twice as before. No real changes otherwise. --- include/wx/msw/treectrl.h | 7 ++----- src/msw/treectrl.cpp | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index dfda459ff5..e28fb6680e 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -46,17 +46,14 @@ class WXDLLIMPEXP_CORE wxTreeCtrl : public wxTreeCtrlBase public: // creation // -------- - wxTreeCtrl() { Init(); } + wxTreeCtrl(); wxTreeCtrl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT, const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxASCII_STR(wxTreeCtrlNameStr)) - { - Create(parent, id, pos, size, style, validator, name); - } + const wxString& name = wxASCII_STR(wxTreeCtrlNameStr)); virtual ~wxTreeCtrl(); diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 205137264f..1e97124235 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -711,6 +711,24 @@ bool wxTreeTraversal::Traverse(const wxTreeItemId& root, bool recursively) // construction and destruction // ---------------------------------------------------------------------------- +wxTreeCtrl::wxTreeCtrl() +{ + Init(); +} + +wxTreeCtrl::wxTreeCtrl(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + Init(); + + Create(parent, id, pos, size, style, validator, name); +} + void wxTreeCtrl::Init() { m_textCtrl = nullptr; @@ -741,8 +759,6 @@ bool wxTreeCtrl::Create(wxWindow *parent, const wxValidator& validator, const wxString& name) { - Init(); - if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT ) style |= wxBORDER_SUNKEN; From ef4f861ed784f840c3d7d6abc1c153ee346133bf Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:31:40 +0100 Subject: [PATCH 26/37] Use std::unordered_map<> for attributes in wxMSW wxTreeCtrl Replace a wx synonym with the direct use of the standard class. Also store std::unique_ptr<> instead of raw pointers in this map. --- include/wx/msw/treectrl.h | 8 ++++---- src/msw/treectrl.cpp | 31 +++++++++++++------------------ 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index e28fb6680e..d30a9f9755 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -20,7 +20,9 @@ #include "wx/textctrl.h" #include "wx/dynarray.h" #include "wx/treebase.h" -#include "wx/hashmap.h" + +#include +#include #ifdef __GNUWIN32__ // Cygwin windows.h defines these identifiers @@ -33,9 +35,7 @@ class WXDLLIMPEXP_FWD_CORE wxImageList; class WXDLLIMPEXP_FWD_CORE wxDragImage; struct WXDLLIMPEXP_FWD_CORE wxTreeViewItem; -// hash storing attributes for our items class wxItemAttr; -WX_DECLARE_EXPORTED_VOIDPTR_HASH_MAP(wxItemAttr *, wxMapTreeAttr); // ---------------------------------------------------------------------------- // wxTreeCtrl @@ -308,7 +308,7 @@ private: wxItemAttr* DoGetAttrPtr(const wxTreeItemId& item); // the hash storing the items attributes (indexed by item ids) - wxMapTreeAttr m_attrs; + std::unordered_map> m_attrs; // true if the hash above is not empty bool m_hasAnyAttr; diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 1e97124235..8bba9f308b 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -856,7 +856,7 @@ wxTreeCtrl::~wxTreeCtrl() // delete any attributes if ( m_hasAnyAttr ) { - WX_CLEAR_HASH_MAP(wxMapTreeAttr, m_attrs); + m_attrs.clear(); // prevent TVN_DELETEITEM handler from deleting the attributes again! m_hasAnyAttr = false; @@ -1181,7 +1181,7 @@ wxColour wxTreeCtrl::GetItemTextColour(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); - wxMapTreeAttr::const_iterator it = m_attrs.find(item.m_pItem); + const auto it = m_attrs.find(item.m_pItem); return it == m_attrs.end() ? wxNullColour : it->second->GetTextColour(); } @@ -1189,7 +1189,7 @@ wxColour wxTreeCtrl::GetItemBackgroundColour(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); - wxMapTreeAttr::const_iterator it = m_attrs.find(item.m_pItem); + const auto it = m_attrs.find(item.m_pItem); return it == m_attrs.end() ? wxNullColour : it->second->GetBackgroundColour(); } @@ -1197,24 +1197,24 @@ wxFont wxTreeCtrl::GetItemFont(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxNullFont, wxT("invalid tree item") ); - wxMapTreeAttr::const_iterator it = m_attrs.find(item.m_pItem); + const auto it = m_attrs.find(item.m_pItem); return it == m_attrs.end() ? wxNullFont : it->second->GetFont(); } wxItemAttr* wxTreeCtrl::DoGetAttrPtr(const wxTreeItemId& item) { wxItemAttr *attr; - wxMapTreeAttr::iterator it = m_attrs.find(item.m_pItem); + const auto it = m_attrs.find(item.m_pItem); if ( it == m_attrs.end() ) { m_hasAnyAttr = true; - m_attrs[item.m_pItem] = attr = new wxItemAttr; + m_attrs[item.m_pItem] = std::unique_ptr(attr); } else { - attr = it->second; + attr = it->second.get(); } return attr; @@ -2258,10 +2258,10 @@ void wxTreeCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI) { wxTreeCtrlBase::MSWUpdateFontOnDPIChange(newDPI); - for ( wxMapTreeAttr::const_iterator it = m_attrs.begin(); it != m_attrs.end(); ++it ) + for ( const auto& kv : m_attrs ) { - if ( it->second->HasFont() ) - SetItemFont(it->first, it->second->GetFont()); + if ( kv.second->HasFont() ) + SetItemFont(kv.first, kv.second->GetFont()); } } @@ -3337,12 +3337,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( m_hasAnyAttr ) { - wxMapTreeAttr::iterator it = m_attrs.find(tv->itemOld.hItem); - if ( it != m_attrs.end() ) - { - delete it->second; - m_attrs.erase(it); - } + m_attrs.erase(tv->itemOld.hItem); } } break; @@ -3583,7 +3578,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) case CDDS_ITEMPREPAINT: { - wxMapTreeAttr::iterator + const auto it = m_attrs.find((void *)nmcd.dwItemSpec); if ( it == m_attrs.end() ) @@ -3593,7 +3588,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; } - wxItemAttr * const attr = it->second; + wxItemAttr * const attr = it->second.get(); wxTreeViewItem tvItem((void *)nmcd.dwItemSpec, TVIF_STATE, TVIS_DROPHILITED); From 97c3d00b1930a66f7664d5680fb9bfbf6a02b2bf Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:33:51 +0100 Subject: [PATCH 27/37] Remove useless wxTreeCtrl::m_hasAnyAttr We can simply check if m_attrs is empty instead. This was added back in 696e1ea0b7cee1394693a0e507bbf49c9863952b (in the last millennium) and apparently there was no simple way to check if wxHashTable used for m_attrs back then was empty, but it's trivial to do it with std::unordered_map<>. --- include/wx/msw/treectrl.h | 3 --- src/msw/treectrl.cpp | 24 +++++++----------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index d30a9f9755..cdc4aebd32 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -310,9 +310,6 @@ private: // the hash storing the items attributes (indexed by item ids) std::unordered_map> m_attrs; - // true if the hash above is not empty - bool m_hasAnyAttr; - #if wxUSE_DRAGIMAGE // used for dragging wxDragImage *m_dragImage; diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 8bba9f308b..ebb174d0fe 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -732,7 +732,6 @@ wxTreeCtrl::wxTreeCtrl(wxWindow *parent, void wxTreeCtrl::Init() { m_textCtrl = nullptr; - m_hasAnyAttr = false; #if wxUSE_DRAGIMAGE m_dragImage = nullptr; #endif @@ -853,14 +852,10 @@ wxTreeCtrl::~wxTreeCtrl() { m_isBeingDeleted = true; - // delete any attributes - if ( m_hasAnyAttr ) - { - m_attrs.clear(); - - // prevent TVN_DELETEITEM handler from deleting the attributes again! - m_hasAnyAttr = false; - } + // delete any attributes: it's important to do it explicitly before calling + // DeleteAllItems() to prevent TVN_DELETEITEM handler from deleting the + // attributes again! + m_attrs.clear(); DeleteTextCtrl(); @@ -1207,8 +1202,6 @@ wxItemAttr* wxTreeCtrl::DoGetAttrPtr(const wxTreeItemId& item) const auto it = m_attrs.find(item.m_pItem); if ( it == m_attrs.end() ) { - m_hasAnyAttr = true; - attr = new wxItemAttr; m_attrs[item.m_pItem] = std::unique_ptr(attr); } @@ -3335,10 +3328,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) event.m_item = tv->itemOld.hItem; - if ( m_hasAnyAttr ) - { - m_attrs.erase(tv->itemOld.hItem); - } + m_attrs.erase(tv->itemOld.hItem); } break; @@ -3530,8 +3520,8 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) case CDDS_PREPAINT: // if we've got any items with non standard attributes, // notify us before painting each item - *result = m_hasAnyAttr ? CDRF_NOTIFYITEMDRAW - : CDRF_DODEFAULT; + *result = m_attrs.empty() ? CDRF_DODEFAULT + : CDRF_NOTIFYITEMDRAW; // windows in TreeCtrl use one-based index for item state images, // 0 indexed image is not being used, we're using zero-based index, From d446286fa63fb7d48351659950ab960c9f331323 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:39:46 +0100 Subject: [PATCH 28/37] Use std::unordered_map<> in wxOSX wxMimeTypesManagerImpl Replace wx hash maps of tags and file type data with the standard containers. Also use auto instead of the explicit iterator type in the code using these maps. --- include/wx/osx/core/mimetype.h | 12 ++++-------- src/osx/core/mimetype.cpp | 18 +++++++++--------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/include/wx/osx/core/mimetype.h b/include/wx/osx/core/mimetype.h index 2a97b3cda6..aac17fafb2 100644 --- a/include/wx/osx/core/mimetype.h +++ b/include/wx/osx/core/mimetype.h @@ -16,9 +16,9 @@ #if wxUSE_MIMETYPE #include "wx/mimetype.h" -#include "wx/hashmap.h" #include "wx/iconloc.h" +#include // This class implements mime type functionality for Mac OS X using UTIs and Launch Services // Currently only the GetFileTypeFromXXXX public functions have been implemented @@ -68,14 +68,10 @@ private: } FileTypeInfo; - // Map types - WX_DECLARE_STRING_HASH_MAP( wxString, TagMap ); - WX_DECLARE_STRING_HASH_MAP( FileTypeData, UtiMap ); - // Data store - TagMap m_extMap; - TagMap m_mimeMap; - UtiMap m_utiMap; + std::unordered_map m_extMap, + m_mimeMap; + std::unordered_map m_utiMap; friend class wxFileTypeImpl; }; diff --git a/src/osx/core/mimetype.cpp b/src/osx/core/mimetype.cpp index 954e7a7db6..bd6cd3dd1b 100644 --- a/src/osx/core/mimetype.cpp +++ b/src/osx/core/mimetype.cpp @@ -322,7 +322,7 @@ wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext { wxString uti; - const TagMap::const_iterator extItr = m_extMap.find( ext ); + const auto extItr = m_extMap.find( ext ); if( extItr == m_extMap.end() ) { @@ -342,7 +342,7 @@ wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mime { wxString uti; - const TagMap::const_iterator mimeItr = m_mimeMap.find( mimeType ); + const auto mimeItr = m_mimeMap.find( mimeType ); if( mimeItr == m_mimeMap.end() ) { @@ -359,7 +359,7 @@ wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mime // If the requested extension is not know the OS is querried and the results saved wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromUti(const wxString& uti) { - UtiMap::const_iterator utiItr = m_utiMap.find( uti ); + const auto utiItr = m_utiMap.find( uti ); if( utiItr == m_utiMap.end() ) { @@ -515,7 +515,7 @@ bool wxMimeTypesManagerImpl::Unassociate(wxFileType *WXUNUSED(ft)) bool wxMimeTypesManagerImpl::GetExtensions(const wxString& uti, wxArrayString& extensions) { - const UtiMap::const_iterator itr = m_utiMap.find( uti ); + const auto itr = m_utiMap.find( uti ); if( itr == m_utiMap.end() || itr->second.extensions.GetCount() < 1 ) { @@ -529,7 +529,7 @@ bool wxMimeTypesManagerImpl::GetExtensions(const wxString& uti, wxArrayString& e bool wxMimeTypesManagerImpl::GetMimeType(const wxString& uti, wxString *mimeType) { - const UtiMap::const_iterator itr = m_utiMap.find( uti ); + const auto itr = m_utiMap.find( uti ); if( itr == m_utiMap.end() || itr->second.mimeTypes.GetCount() < 1 ) { @@ -543,7 +543,7 @@ bool wxMimeTypesManagerImpl::GetMimeType(const wxString& uti, wxString *mimeType bool wxMimeTypesManagerImpl::GetMimeTypes(const wxString& uti, wxArrayString& mimeTypes) { - const UtiMap::const_iterator itr = m_utiMap.find( uti ); + const auto itr = m_utiMap.find( uti ); if( itr == m_utiMap.end() || itr->second.mimeTypes.GetCount() < 1 ) { @@ -557,7 +557,7 @@ bool wxMimeTypesManagerImpl::GetMimeTypes(const wxString& uti, wxArrayString& mi bool wxMimeTypesManagerImpl::GetIcon(const wxString& uti, wxIconLocation *iconLoc) { - const UtiMap::const_iterator itr = m_utiMap.find( uti ); + const auto itr = m_utiMap.find( uti ); if( itr == m_utiMap.end() || !itr->second.iconLoc.IsOk() ) { @@ -571,7 +571,7 @@ bool wxMimeTypesManagerImpl::GetIcon(const wxString& uti, wxIconLocation *iconLo bool wxMimeTypesManagerImpl::GetDescription(const wxString& uti, wxString *desc) { - const UtiMap::const_iterator itr = m_utiMap.find( uti ); + const auto itr = m_utiMap.find( uti ); if( itr == m_utiMap.end() || itr->second.description.empty() ) { @@ -585,7 +585,7 @@ bool wxMimeTypesManagerImpl::GetDescription(const wxString& uti, wxString *desc) bool wxMimeTypesManagerImpl::GetApplication(const wxString& uti, wxString *command) { - const UtiMap::const_iterator itr = m_utiMap.find( uti ); + const auto itr = m_utiMap.find( uti ); if( itr == m_utiMap.end() ) { From f0eed0a1027c5ce12b83213e102abc8ba1fc8784 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:51:52 +0100 Subject: [PATCH 29/37] Use std::unordered_map<> in wxPersistenceManager Replace a wx synonym with the direct use of the standard class. Also store std::unique_ptr<> instead of raw pointers in this map to ensure that they get destroyed: previously we could have memory leaks if some objects were not unregistered before the program exit. --- include/wx/persist.h | 10 ++++++---- src/common/persist.cpp | 25 ++++++++++++------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/include/wx/persist.h b/include/wx/persist.h index 915183f0a7..6caf660d6b 100644 --- a/include/wx/persist.h +++ b/include/wx/persist.h @@ -11,12 +11,12 @@ #define _WX_PERSIST_H_ #include "wx/string.h" -#include "wx/hashmap.h" #include "wx/confbase.h" -class wxPersistentObject; +#include +#include -WX_DECLARE_VOIDPTR_HASH_MAP(wxPersistentObject *, wxPersistentObjectsMap); +class wxPersistentObject; // ---------------------------------------------------------------------------- // global functions @@ -159,9 +159,11 @@ protected: private: + using wxPersistentObjectPtr = std::unique_ptr; + // map with the registered objects as keys and associated // wxPersistentObjects as values - wxPersistentObjectsMap m_persistentObjects; + std::unordered_map m_persistentObjects; // true if we should restore/save the settings (it doesn't make much sense // to use this class when both of them are false but setting one of them to diff --git a/src/common/persist.cpp b/src/common/persist.cpp index efa8a5239b..73a6f46d9e 100644 --- a/src/common/persist.cpp +++ b/src/common/persist.cpp @@ -74,35 +74,34 @@ wxPersistenceManager::GetKey(const wxPersistentObject& who, wxPersistentObject *wxPersistenceManager::Find(void *obj) const { - const wxPersistentObjectsMap::const_iterator - it = m_persistentObjects.find(obj); - return it == m_persistentObjects.end() ? nullptr : it->second; + const auto it = m_persistentObjects.find(obj); + return it == m_persistentObjects.end() ? nullptr : it->second.get(); } wxPersistentObject * wxPersistenceManager::Register(void *obj, wxPersistentObject *po) { + // Avoid memory leaks in any case by ensuring this object gets deleted. + wxPersistentObjectPtr ptr{po}; + if ( wxPersistentObject *old = Find(obj) ) { wxFAIL_MSG( "object is already registered" ); - delete po; // still avoid the memory leaks return old; } - m_persistentObjects[obj] = po; + m_persistentObjects[obj] = std::move(ptr); return po; } void wxPersistenceManager::Unregister(void *obj) { - wxPersistentObjectsMap::iterator it = m_persistentObjects.find(obj); - wxCHECK_RET( it != m_persistentObjects.end(), "not registered" ); - - wxPersistentObject * const po = it->second; - m_persistentObjects.erase(it); - delete po; + if ( !m_persistentObjects.erase(obj) ) + { + wxFAIL_MSG( "unregistering object which is not registered" ); + } } void wxPersistenceManager::Save(void *obj) @@ -110,7 +109,7 @@ void wxPersistenceManager::Save(void *obj) if ( !m_doSave ) return; - wxPersistentObjectsMap::iterator it = m_persistentObjects.find(obj); + const auto it = m_persistentObjects.find(obj); wxCHECK_RET( it != m_persistentObjects.end(), "not registered" ); it->second->Save(); @@ -121,7 +120,7 @@ bool wxPersistenceManager::Restore(void *obj) if ( !m_doRestore ) return false; - wxPersistentObjectsMap::iterator it = m_persistentObjects.find(obj); + const auto it = m_persistentObjects.find(obj); wxCHECK_MSG( it != m_persistentObjects.end(), false, "not registered" ); return it->second->Restore(); From 7b2baeaceee96d040a20cd903f06cbe62b9dd94f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 18 Apr 2023 00:19:46 +0200 Subject: [PATCH 30/37] Use std::unordered_map<> in Unix wxAppConsole Replace a wx synonym with the direct use of the standard class. --- include/wx/unix/app.h | 5 +++-- src/unix/appunix.cpp | 8 +++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/wx/unix/app.h b/include/wx/unix/app.h index 0d27e4a205..bd01944444 100644 --- a/include/wx/unix/app.h +++ b/include/wx/unix/app.h @@ -10,6 +10,8 @@ //Ensure that sigset_t is being defined #include +#include + class wxFDIODispatcher; class wxFDIOHandler; class wxWakeUpPipe; @@ -64,8 +66,7 @@ private: sigset_t m_signalsCaught; // the signal handlers - WX_DECLARE_HASH_MAP(int, SignalHandler, wxIntegerHash, wxIntegerEqual, SignalHandlerHash); - SignalHandlerHash m_signalHandlerHash; + std::unordered_map m_signalHandlerHash; // pipe used for wake up signal handling: if a signal arrives while we're // blocking for input, writing to this pipe triggers a call to our CheckSignal() diff --git a/src/unix/appunix.cpp b/src/unix/appunix.cpp index c5c828c383..cf7a1a6f49 100644 --- a/src/unix/appunix.cpp +++ b/src/unix/appunix.cpp @@ -115,15 +115,13 @@ void wxAppConsole::HandleSignal(int signal) void wxAppConsole::CheckSignal() { - for ( SignalHandlerHash::iterator it = m_signalHandlerHash.begin(); - it != m_signalHandlerHash.end(); - ++it ) + for ( const auto& kv : m_signalHandlerHash ) { - int sig = it->first; + int sig = kv.first; if ( sigismember(&m_signalsCaught, sig) ) { sigdelset(&m_signalsCaught, sig); - (it->second)(sig); + (kv.second)(sig); } } } From 16b748dbc6d27e2282773217032ace3eb95a8f4f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:55:00 +0100 Subject: [PATCH 31/37] Use std::unordered_map<> in wxMappedFDIODispatcher Replace a wx synonym with the direct use of the standard class. --- include/wx/private/fdiodispatcher.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/wx/private/fdiodispatcher.h b/include/wx/private/fdiodispatcher.h index 827dc7038d..14f951a96b 100644 --- a/include/wx/private/fdiodispatcher.h +++ b/include/wx/private/fdiodispatcher.h @@ -10,9 +10,10 @@ #ifndef _WX_PRIVATE_FDIODISPATCHER_H_ #define _WX_PRIVATE_FDIODISPATCHER_H_ -#include "wx/hashmap.h" #include "wx/private/fdiohandler.h" +#include + // those flags describes sets where descriptor should be added enum wxFDIODispatcherEntryFlags { @@ -81,13 +82,7 @@ struct wxFDIOHandlerEntry }; // this hash is used to map file descriptors to their handlers -WX_DECLARE_HASH_MAP( - int, - wxFDIOHandlerEntry, - wxIntegerHash, - wxIntegerEqual, - wxFDIOHandlerMap -); +using wxFDIOHandlerMap = std::unordered_map; // FDIODispatcher that holds map fd <-> FDIOHandler, this should be used if // this map isn't maintained elsewhere already as it is usually needed anyhow From b1530a52e219c2c3240e67021c9a63d0b7f32a99 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 18 Apr 2023 00:37:21 +0200 Subject: [PATCH 32/37] Use std::unordered_map<> in wxWebSession Replace a wx synonym with the direct use of the standard class. Also store std::unique_ptr<> instead of raw pointers in this map, this allows to remove an existing comment saying that the code wasn't always safe -- now it is. --- src/common/webrequest.cpp | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/common/webrequest.cpp b/src/common/webrequest.cpp index 82914c5470..acd76d4f12 100644 --- a/src/common/webrequest.cpp +++ b/src/common/webrequest.cpp @@ -39,6 +39,9 @@ #include "wx/private/webrequest_curl.h" #endif +#include +#include + extern WXDLLIMPEXP_DATA_NET(const char) wxWebSessionBackendWinHTTP[] = "WinHTTP"; extern WXDLLIMPEXP_DATA_NET(const char) wxWebSessionBackendURLSession[] = "URLSession"; extern WXDLLIMPEXP_DATA_NET(const char) wxWebSessionBackendCURL[] = "CURL"; @@ -865,13 +868,11 @@ wxString wxWebResponse::GetDataFile() const // wxWebSessionImpl // -WX_DECLARE_STRING_HASH_MAP(wxWebSessionFactory*, wxStringWebSessionFactoryMap); - namespace { wxWebSession gs_defaultSession; -wxStringWebSessionFactoryMap gs_factoryMap; +std::unordered_map> gs_factoryMap; } // anonymous namespace @@ -949,7 +950,7 @@ wxWebSession wxWebSession::New(const wxString& backendOrig) } } - wxStringWebSessionFactoryMap::iterator factory = gs_factoryMap.find(backend); + const auto factory = gs_factoryMap.find(backend); wxWebSessionImplPtr impl; if ( factory != gs_factoryMap.end() ) @@ -963,18 +964,13 @@ void wxWebSession::RegisterFactory(const wxString& backend, wxWebSessionFactory* factory) { - if ( !factory->Initialize() ) - { - delete factory; - factory = nullptr; - return; - } + // Ensure that the pointer is always freed. + std::unique_ptr ptr{factory}; - // Note that we don't have to check here that there is no registered - // backend with the same name yet because we're only called from - // InitFactoryMap() below. If this function becomes public, we'd need to - // free the previous pointer stored for this backend first here. - gs_factoryMap[backend] = factory; + if ( !factory->Initialize() ) + return; + + gs_factoryMap[backend] = std::move(ptr); } // static @@ -997,7 +993,7 @@ bool wxWebSession::IsBackendAvailable(const wxString& backend) if ( gs_factoryMap.empty() ) InitFactoryMap(); - wxStringWebSessionFactoryMap::iterator factory = gs_factoryMap.find(backend); + const auto factory = gs_factoryMap.find(backend); return factory != gs_factoryMap.end(); } @@ -1070,13 +1066,6 @@ public: virtual void OnExit() override { - for ( wxStringWebSessionFactoryMap::iterator it = gs_factoryMap.begin(); - it != gs_factoryMap.end(); - ++it ) - { - delete it->second; - } - gs_factoryMap.clear(); gs_defaultSession.Close(); } From 97b5d130386bf4f90451b084205070a3ab48a220 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:57:38 +0100 Subject: [PATCH 33/37] Use std::unordered_map<> in private wxWebRequest headers Replace wx synonym with the direct use of the standard class. --- include/wx/private/webrequest.h | 4 ++-- include/wx/private/webrequest_curl.h | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/wx/private/webrequest.h b/include/wx/private/webrequest.h index 235727232b..718953c772 100644 --- a/include/wx/private/webrequest.h +++ b/include/wx/private/webrequest.h @@ -11,13 +11,13 @@ #define _WX_PRIVATE_WEBREQUEST_H_ #include "wx/ffile.h" -#include "wx/hashmap.h" #include "wx/private/refcountermt.h" #include +#include -WX_DECLARE_STRING_HASH_MAP(wxString, wxWebRequestHeaderMap); +using wxWebRequestHeaderMap = std::unordered_map; // Default buffer size when a fixed-size buffer must be used. const int wxWEBREQUEST_BUFFER_SIZE = 64 * 1024; diff --git a/include/wx/private/webrequest_curl.h b/include/wx/private/webrequest_curl.h index 589912e741..9eeea7c087 100644 --- a/include/wx/private/webrequest_curl.h +++ b/include/wx/private/webrequest_curl.h @@ -17,10 +17,11 @@ #include "wx/thread.h" #include "wx/vector.h" #include "wx/timer.h" -#include "wx/hashmap.h" #include "curl/curl.h" +#include + class wxWebRequestCURL; class wxWebResponseCURL; class wxWebSessionCURL; @@ -171,11 +172,8 @@ private: void StopActiveTransfer(CURL*); void RemoveActiveSocket(CURL*); - WX_DECLARE_HASH_MAP(CURL*, wxWebRequestCURL*, wxPointerHash, \ - wxPointerEqual, TransferSet); - - WX_DECLARE_HASH_MAP(CURL*, curl_socket_t, wxPointerHash, \ - wxPointerEqual, CurlSocketMap); + using TransferSet = std::unordered_map; + using CurlSocketMap = std::unordered_map; TransferSet m_activeTransfers; CurlSocketMap m_activeSockets; From 477cd23850c2f8e96b3075ee2ad72cf834a86c2b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 22:59:37 +0100 Subject: [PATCH 34/37] Use std::unordered_map<> in Unix wxExecute() implementation Replace a wx synonym with the direct use of the standard class. --- include/wx/unix/private/execute.h | 6 +++--- src/unix/utilsunx.cpp | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/wx/unix/private/execute.h b/include/wx/unix/private/execute.h index 7605761176..b03cd623fa 100644 --- a/include/wx/unix/private/execute.h +++ b/include/wx/unix/private/execute.h @@ -11,7 +11,6 @@ #define _WX_UNIX_EXECUTE_H #include "wx/app.h" -#include "wx/hashmap.h" #include "wx/process.h" #if wxUSE_STREAMS @@ -19,6 +18,8 @@ #include "wx/private/streamtempinput.h" #endif +#include + class wxEventLoopBase; // Information associated with a running child process. @@ -92,8 +93,7 @@ private: // All currently running child processes indexed by their PID. // // Notice that the container doesn't own its elements. - WX_DECLARE_HASH_MAP(int, wxExecuteData*, wxIntegerHash, wxIntegerEqual, - ChildProcessesData); + using ChildProcessesData = std::unordered_map; static ChildProcessesData ms_childProcesses; wxDECLARE_NO_COPY_CLASS(wxExecuteData); diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index e32c957cab..bb37b66dc9 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -1675,11 +1675,9 @@ void wxExecuteData::OnSomeChildExited(int WXUNUSED(sig)) // Make a copy of the list before iterating over it to avoid problems due // to deleting entries from it in the process. const ChildProcessesData allChildProcesses = ms_childProcesses; - for ( ChildProcessesData::const_iterator it = allChildProcesses.begin(); - it != allChildProcesses.end(); - ++it ) + for ( const auto& kv : allChildProcesses ) { - const int pid = it->first; + const int pid = kv.first; // Check whether this child exited. int exitcode; @@ -1689,7 +1687,7 @@ void wxExecuteData::OnSomeChildExited(int WXUNUSED(sig)) // And handle its termination if it did. // // Notice that this will implicitly remove it from ms_childProcesses. - it->second->OnExit(exitcode); + kv.second->OnExit(exitcode); } } From f13901de58d4de99df9031f33df48b6ec087861c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 23:01:35 +0100 Subject: [PATCH 35/37] Use std::unordered_map<> in wxTarInputStream Replace a wx synonym with the direct use of the standard class. --- include/wx/tarstrm.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/wx/tarstrm.h b/include/wx/tarstrm.h index 8c97475573..9afafe99ab 100644 --- a/include/wx/tarstrm.h +++ b/include/wx/tarstrm.h @@ -14,8 +14,8 @@ #if wxUSE_TARSTREAM #include "wx/archive.h" -#include "wx/hashmap.h" +#include ///////////////////////////////////////////////////////////////////////////// // Constants @@ -149,8 +149,6 @@ private: ///////////////////////////////////////////////////////////////////////////// // wxTarInputStream -WX_DECLARE_STRING_HASH_MAP(wxString, wxTarHeaderRecords); - class WXDLLIMPEXP_BASE wxTarInputStream : public wxArchiveInputStream { public: @@ -174,6 +172,8 @@ protected: wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) override; private: + using wxTarHeaderRecords = std::unordered_map; + void Init(); wxArchiveEntry *DoGetNextEntry() override { return GetNextEntry(); } From b42b82bfb26abc02e24fd4241863b00bf86b2dee Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 23:03:12 +0100 Subject: [PATCH 36/37] Use std::unordered_map<> in XTI wxTypeInfo Replace a wx synonym with the direct use of the standard class. --- include/wx/xtitypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/wx/xtitypes.h b/include/wx/xtitypes.h index 40b48562b5..d83136e5ec 100644 --- a/include/wx/xtitypes.h +++ b/include/wx/xtitypes.h @@ -17,12 +17,12 @@ #if wxUSE_EXTENDED_RTTI #include "wx/string.h" -#include "wx/hashmap.h" #include "wx/arrstr.h" #include "wx/flags.h" #include "wx/intl.h" #include "wx/log.h" #include +#include class WXDLLIMPEXP_BASE wxClassInfo; @@ -299,7 +299,7 @@ enum wxTypeKind class WXDLLIMPEXP_BASE wxAny; class WXDLLIMPEXP_BASE wxTypeInfo; -WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE ); +using wxTypeInfo = std::unordered_map; class WXDLLIMPEXP_BASE wxTypeInfo { From f5920de681f4d38f447e4849929fc7ff91598f67 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 17 Apr 2023 23:14:33 +0100 Subject: [PATCH 37/37] Use standard containers in dataview sample Update the sample to use std::vector<> and std::unordered_map<> for storing the model data, this should be much more useful for the people trying to write their own model. Also use std::unique_ptr<> to avoid manual memory management. --- samples/dataview/mymodels.cpp | 32 ++++++++++++++----------------- samples/dataview/mymodels.h | 36 +++++++++++++---------------------- 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/samples/dataview/mymodels.cpp b/samples/dataview/mymodels.cpp index 30d8f71328..4c719a0785 100644 --- a/samples/dataview/mymodels.cpp +++ b/samples/dataview/mymodels.cpp @@ -135,12 +135,15 @@ void MyMusicTreeModel::Delete( const wxDataViewItem &item ) m_ninth = nullptr; // first remove the node from the parent's array of children; - // NOTE: MyMusicTreeModelNodePtrArray is only an array of _pointers_ - // thus removing the node from it doesn't result in freeing it - node->GetParent()->GetChildren().Remove( node ); - - // free the node - delete node; + auto& siblings = node->GetParent()->GetChildren(); + for ( auto it = siblings.begin(); it != siblings.end(); ++it ) + { + if ( it->get() == node ) + { + siblings.erase(it); + break; + } + } // notify control ItemDeleted( parent, item ); @@ -151,12 +154,7 @@ void MyMusicTreeModel::Clear() m_classical = nullptr; m_ninth = nullptr; - while (!m_root->GetChildren().IsEmpty()) - { - MyMusicTreeModelNode* node = m_root->GetNthChild(0); - m_root->GetChildren().Remove(node); - delete node; - } + m_root->GetChildren().clear(); Cleared(); } @@ -320,14 +318,12 @@ unsigned int MyMusicTreeModel::GetChildren( const wxDataViewItem &parent, return 0; } - unsigned int count = node->GetChildren().GetCount(); - for (unsigned int pos = 0; pos < count; pos++) + for ( const auto& child : node->GetChildren() ) { - MyMusicTreeModelNode *child = node->GetChildren().Item( pos ); - array.Add( wxDataViewItem( (void*) child ) ); + array.Add( wxDataViewItem( child.get() ) ); } - return count; + return array.size(); } @@ -514,7 +510,7 @@ void MyListModel::GetValueByRow( wxVariant &variant, case Col_Custom: { - IntToStringMap::const_iterator it = m_customColValues.find(row); + const auto it = m_customColValues.find(row); if ( it != m_customColValues.end() ) variant = it->second; else diff --git a/samples/dataview/mymodels.h b/samples/dataview/mymodels.h index 7a52e0f03f..ad113d83c2 100644 --- a/samples/dataview/mymodels.h +++ b/samples/dataview/mymodels.h @@ -8,18 +8,17 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#include "wx/hashmap.h" -#include "wx/vector.h" - -WX_DECLARE_HASH_MAP(unsigned, wxString, wxIntegerHash, wxIntegerEqual, - IntToStringMap); +#include +#include +#include // ---------------------------------------------------------------------------- // MyMusicTreeModelNode: a node inside MyMusicTreeModel // ---------------------------------------------------------------------------- class MyMusicTreeModelNode; -WX_DEFINE_ARRAY_PTR( MyMusicTreeModelNode*, MyMusicTreeModelNodePtrArray ); +using MyMusicTreeModelNodePtr = std::unique_ptr; +using MyMusicTreeModelNodePtrArray = std::vector; class MyMusicTreeModelNode { @@ -49,16 +48,7 @@ public: m_container = true; } - ~MyMusicTreeModelNode() - { - // free all our children nodes - size_t count = m_children.GetCount(); - for (size_t i = 0; i < count; i++) - { - MyMusicTreeModelNode *child = m_children[i]; - delete child; - } - } + ~MyMusicTreeModelNode() = default; bool IsContainer() const { return m_container; } @@ -68,13 +58,13 @@ public: MyMusicTreeModelNodePtrArray& GetChildren() { return m_children; } MyMusicTreeModelNode* GetNthChild( unsigned int n ) - { return m_children.Item( n ); } + { return m_children.at( n ).get(); } void Insert( MyMusicTreeModelNode* child, unsigned int n) - { m_children.Insert( child, n); } + { m_children.insert( m_children.begin() + n, MyMusicTreeModelNodePtr(child) ); } void Append( MyMusicTreeModelNode* child ) - { m_children.Add( child ); } + { m_children.push_back( MyMusicTreeModelNodePtr(child) ); } unsigned int GetChildCount() const - { return m_children.GetCount(); } + { return m_children.size(); } public: // public to avoid getters/setters wxString m_title; @@ -87,7 +77,7 @@ public: // public to avoid getters/setters // needs to know in advance if a node is or _will be_ a container. // Thus implementing: // bool IsContainer() const - // { return m_children.GetCount()>0; } + // { return !m_children.empty(); } // doesn't work with wxGTK when MyMusicTreeModel::AddToClassical is called // AND the classical node was removed (a new node temporary without children // would be added to the control) @@ -223,10 +213,10 @@ public: unsigned int row, unsigned int col ) override; private: - wxVector m_toggleColValues; + std::vector m_toggleColValues; wxArrayString m_textColValues; wxArrayString m_iconColValues; - IntToStringMap m_customColValues; + std::unordered_map m_customColValues; wxBitmapBundle m_icon[2]; };