diff --git a/docs/changes.txt b/docs/changes.txt index eec38d12d6..9fa8473563 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -64,12 +64,13 @@ All: - Assert messages now show the function in which assert failed - wxApp::OnAssertFailure() should now be used instead the old wxApp::OnAssert() - Fixed several bugs in wxDateTime::ParseDate() -- The WXK*PRIOR and WXK*NEXT constants are now aliases for WXK*PAGEUP +- The WXK*PRIOR and WXK*NEXT constants are now aliases for WXK*PAGEUP and WXK*PAGEDOWN. If you have switch statements that use both - constants from a set then you need to remove the PRIOR/NEXT + constants from a set then you need to remove the PRIOR/NEXT versions in order to eliminate compiler errors. - Fixed bug where wxDateTime::Now() would sometimes return an incorrect value the first time it was called. +- Added wxString::rbegin() and rend() All (GUI): @@ -190,7 +191,7 @@ wxGTK: - Fixed focusing with mnemonic accelerator keys on wxStaticText which is now able to focus on wxComboBox and possibly other controls previously unable to be focused before. -- Enabled mnemonics and the corresponding accelerator keys for +- Enabled mnemonics and the corresponding accelerator keys for wxStaticBox and wxRadioBox. - Fixed problem trying to print from a preview, whereby wrong printer class was used. diff --git a/include/wx/string.h b/include/wx/string.h index 6cf19b5022..ad2ec51b9d 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -299,6 +299,44 @@ public: typedef value_type *iterator; typedef const value_type *const_iterator; +#define wxSTRING_REVERSE_ITERATOR(name, const_or_not) \ + class name \ + { \ + public: \ + typedef wxChar value_type; \ + typedef const_or_not value_type& reference; \ + typedef const_or_not value_type *pointer; \ + typedef const_or_not value_type *iterator_type; \ + \ + name(iterator_type i) : m_cur(i) { } \ + name(const name& ri) : m_cur(ri.m_cur) { } \ + \ + iterator_type base() const { return m_cur; } \ + \ + reference operator*() const { return *(m_cur - 1); } \ + pointer operator->() const { return m_cur - 1; } \ + \ + name& operator++() { --m_cur; return *this; } \ + name operator++(int) { name tmp = *this; --m_cur; return tmp; } \ + name& operator--() { ++m_cur; return *this; } \ + name operator--(int) { name tmp = *this; ++m_cur; return tmp; } \ + \ + bool operator==(name ri) const { return m_cur == ri.m_cur; } \ + bool operator!=(name ri) const { return !(*this == ri); } \ + \ + private: \ + iterator_type m_cur; \ + } + + wxSTRING_REVERSE_ITERATOR(const_reverse_iterator, const); + + #define wxSTRING_CONST + wxSTRING_REVERSE_ITERATOR(reverse_iterator, wxSTRING_CONST); + #undef wxSTRING_CONST + + #undef wxSTRING_REVERSE_ITERATOR + + // constructors and destructor // ctor for an empty string wxStringBase() { Init(); } @@ -431,14 +469,18 @@ public: // first valid index position const_iterator begin() const { return m_pchData; } + iterator begin(); // position one after the last valid one const_iterator end() const { return m_pchData + length(); } - - // first valid index position - iterator begin(); - // position one after the last valid one iterator end(); + // first element of the reversed string + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + // one beyond the end of the reversed string + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + // insert another string wxStringBase& insert(size_t nPos, const wxStringBase& str) { diff --git a/tests/strings/stdstrings.cpp b/tests/strings/stdstrings.cpp index 23e77ef77b..10fdf882c8 100644 --- a/tests/strings/stdstrings.cpp +++ b/tests/strings/stdstrings.cpp @@ -44,6 +44,7 @@ private: CPPUNIT_TEST( StdReplace ); CPPUNIT_TEST( StdRFind ); CPPUNIT_TEST( StdResize ); + CPPUNIT_TEST( StdRiter ); CPPUNIT_TEST( StdSubstr ); CPPUNIT_TEST_SUITE_END(); @@ -59,6 +60,7 @@ private: void StdReplace(); void StdRFind(); void StdResize(); + void StdRiter(); void StdSubstr(); DECLARE_NO_COPY_CLASS(StdStringTestCase) @@ -214,18 +216,18 @@ void StdStringTestCase::StdFind() CPPUNIT_ASSERT( s1.find(s2) == 6u ); CPPUNIT_ASSERT( s1.find(s2, 7) == wxString::npos ); CPPUNIT_ASSERT( s1.find(s2, 6) == 6u ); - + // 0 1 2 // 0123456 78901234567 8901234567 //wxString _s1 = _T("abcdefg\0ABCDEFGabc\0ABCabcABC"); //wxString _s2 = _T("g\0AB"); wxString _s1 = _T("abcdefgABCDEFGabcABCabcABC"); wxString _s2 = _T("gAB"); - + _s1.insert(7, 1, '\0'); _s1.insert(18, 1, '\0'); _s2.insert(1, 1, '\0'); - + CPPUNIT_ASSERT( _s1.find(_T('A')) == 8u ); CPPUNIT_ASSERT( _s1.find(_T('A'), 8) == 8u ); CPPUNIT_ASSERT( _s1.find(_T('Z')) == wxString::npos ); @@ -410,7 +412,7 @@ void StdStringTestCase::StdRFind() // wxString s1 = _T("abcde\0fgABCDE\0FGabcABCabcABC"); // wxString s2 = _T("gAB"); // wxString s3 = _T("ab"); - + s1.insert(5,1,'\0'); s1.insert(13,1,'\0'); @@ -444,6 +446,26 @@ void StdStringTestCase::StdResize() CPPUNIT_ASSERT( s4 == _T("abcABCdefDEFWW") ); } +void StdStringTestCase::StdRiter() +{ + const wxString s(_T("fozbar")); + + wxString::const_reverse_iterator ri(s.rbegin()); + CPPUNIT_ASSERT_EQUAL( _T('r'), *ri ); + CPPUNIT_ASSERT_EQUAL( _T('a'), *++ri ); + CPPUNIT_ASSERT_EQUAL( _T('r'), *--ri ); + + ri = s.rend(); + ri--; + CPPUNIT_ASSERT_EQUAL( _T('f'), *ri ); + + --ri; + CPPUNIT_ASSERT_EQUAL( _T('o'), *ri ); + + wxString::const_iterator i = ri.base(); + CPPUNIT_ASSERT_EQUAL( _T('z'), *i ); +} + void StdStringTestCase::StdSubstr() { wxString s1 = _T("abcdefgABCDEFG"); @@ -453,11 +475,6 @@ void StdStringTestCase::StdSubstr() CPPUNIT_ASSERT( s1.substr( 1, 20 ) == _T("bcdefgABCDEFG") ); CPPUNIT_ASSERT( s1.substr( 14, 30 ) == _T("") ); - -// 1 -// 012 34567 89012 3456 -// wxString s1 = _T("abc\0defg\0ABCD\0EFG"); - s1.insert(3,1,'\0'); s1.insert(8,1,'\0'); s1.insert(13,1,'\0'); @@ -466,7 +483,7 @@ void StdStringTestCase::StdSubstr() s2.insert(2,1,'\0'); s2.insert(7,1,'\0'); s2.insert(12,1,'\0'); - + CPPUNIT_ASSERT( s1.substr( 0, 17 ) == s1 ); CPPUNIT_ASSERT( s1.substr( 1, 17 ) == s2 ); CPPUNIT_ASSERT( s1.substr( 1, 20 ) == s2 );