From 069415c2a64f46f68d60a8c45be2f0b773803add Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 20 Oct 2014 15:08:09 +0000 Subject: [PATCH] Fix wxStringTokenizer copy ctor and assignment operator. Implement copying of wxStringTokenizer correctly: compiler-generated versions didn't work as the position of the tokenizer didn't point into the correct string after making the copy. Fix this by adjusting the position iterator to use the copy of the string. Closes #16339. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78050 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/tokenzr.h | 5 +++++ src/common/tokenzr.cpp | 27 ++++++++++++++++++++++ tests/strings/tokenizer.cpp | 45 +++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/docs/changes.txt b/docs/changes.txt index d2ab515a65..78bdab73ce 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -47,6 +47,7 @@ All: - Specialize std::hash<> for wxString when using C++11. - Allow recursive calls to wxYield(). - Add wxART_FULL_SCREEN standard bitmap (Igor Korot). +- Fix wxStringTokenizer copy ctor and assignment operator. Unix: diff --git a/include/wx/tokenzr.h b/include/wx/tokenzr.h index 2eb6519709..45f91a0aef 100644 --- a/include/wx/tokenzr.h +++ b/include/wx/tokenzr.h @@ -47,6 +47,9 @@ public: wxStringTokenizer(const wxString& str, const wxString& delims = wxDEFAULT_DELIMITERS, wxStringTokenizerMode mode = wxTOKEN_DEFAULT); + // copy ctor and assignment operator + wxStringTokenizer(const wxStringTokenizer& src); + wxStringTokenizer& operator=(const wxStringTokenizer& src); // args are same as for the non default ctor above void SetString(const wxString& str, @@ -112,6 +115,8 @@ protected: bool DoHasMoreTokens() const; + void DoCopyFrom(const wxStringTokenizer& src); + enum MoreTokensState { MoreTokens_Unknown, diff --git a/src/common/tokenzr.cpp b/src/common/tokenzr.cpp index 50e08672ac..35fb2c36f6 100644 --- a/src/common/tokenzr.cpp +++ b/src/common/tokenzr.cpp @@ -84,6 +84,21 @@ wxStringTokenizer::wxStringTokenizer(const wxString& str, SetString(str, delims, mode); } +wxStringTokenizer::wxStringTokenizer(const wxStringTokenizer& src) +{ + DoCopyFrom(src); +} + +wxStringTokenizer& wxStringTokenizer::operator=(const wxStringTokenizer& src) +{ + if (this != &src) + { + DoCopyFrom(src); + } + + return *this; +} + void wxStringTokenizer::SetString(const wxString& str, const wxString& delims, wxStringTokenizerMode mode) @@ -136,6 +151,18 @@ void wxStringTokenizer::Reinit(const wxString& str) m_hasMoreTokens = MoreTokens_Unknown; } +void wxStringTokenizer::DoCopyFrom(const wxStringTokenizer& src) +{ + m_string = src.m_string; + m_stringEnd = m_string.end(); + m_pos = m_string.begin() + (src.m_pos - src.m_string.begin()); + m_delims = src.m_delims; + m_delimsLen = src.m_delimsLen; + m_mode = src.m_mode; + m_lastDelim = src.m_lastDelim; + m_hasMoreTokens = src.m_hasMoreTokens; +} + // ---------------------------------------------------------------------------- // access to the tokens // ---------------------------------------------------------------------------- diff --git a/tests/strings/tokenizer.cpp b/tests/strings/tokenizer.cpp index 83007d2427..0b01b680ac 100644 --- a/tests/strings/tokenizer.cpp +++ b/tests/strings/tokenizer.cpp @@ -38,6 +38,8 @@ private: CPPUNIT_TEST( GetString ); CPPUNIT_TEST( LastDelimiter ); CPPUNIT_TEST( StrtokCompat ); + CPPUNIT_TEST( CopyObj ); + CPPUNIT_TEST( AssignObj ); CPPUNIT_TEST_SUITE_END(); void GetCount(); @@ -45,6 +47,8 @@ private: void GetString(); void LastDelimiter(); void StrtokCompat(); + void CopyObj(); + void AssignObj(); DECLARE_NO_COPY_CLASS(TokenizerTestCase) }; @@ -268,4 +272,45 @@ void TokenizerTestCase::StrtokCompat() } } +void TokenizerTestCase::CopyObj() +{ + // Test copy ctor + wxStringTokenizer tkzSrc(wxT("first:second:third:fourth"), wxT(":")); + while ( tkzSrc.HasMoreTokens() ) + { + wxString tokenSrc = tkzSrc.GetNextToken(); + wxStringTokenizer tkz = tkzSrc; + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetPosition(), tkz.GetPosition() ); + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetString(), tkz.GetString() ); + + // Change the state of both objects and compare again... + tokenSrc = tkzSrc.GetNextToken(); + wxString token = tkz.GetNextToken(); + + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetPosition(), tkz.GetPosition() ); + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetString(), tkz.GetString() ); + } +} + +void TokenizerTestCase::AssignObj() +{ + // Test assignment + wxStringTokenizer tkzSrc(wxT("first:second:third:fourth"), wxT(":")); + wxStringTokenizer tkz; + while ( tkzSrc.HasMoreTokens() ) + { + wxString tokenSrc = tkzSrc.GetNextToken(); + tkz = tkzSrc; + + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetPosition(), tkz.GetPosition() ); + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetString(), tkz.GetString() ); + + // Change the state of both objects and compare again... + tokenSrc = tkzSrc.GetNextToken(); + wxString token = tkz.GetNextToken(); + + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetPosition(), tkz.GetPosition() ); + CPPUNIT_ASSERT_EQUAL( tkzSrc.GetString(), tkz.GetString() ); + } +}