Corrected statements about wxString correctly handling
embedded '\0' characters. Fixed various wxString::*find* methods (patch by Robert Vazan), plus added missing overloaded variants of find_first/last_(not_)of. Added more tests in console sample. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23357 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -6,8 +6,9 @@ Classes: \helpref{wxString}{wxstring}, \helpref{wxArrayString}{wxarraystring}, \
|
||||
|
||||
wxString is a class which represents a character string of arbitrary length (limited by
|
||||
{\it MAX\_INT} which is usually 2147483647 on 32 bit machines) and containing
|
||||
arbitrary characters. The ASCII NUL character is allowed, although care should be
|
||||
taken when passing strings containing it to other functions.
|
||||
arbitrary characters. The ASCII NUL character is allowed, but be aware that
|
||||
in the current string implementation some methods might not work correctly
|
||||
in this case.
|
||||
|
||||
wxString works with both ASCII (traditional, 7 or 8 bit, characters) as well as
|
||||
Unicode (wide characters) strings.
|
||||
|
@@ -6,7 +6,7 @@ there, wxString implements about 90\% of methods of the std::string class (itera
|
||||
are not supported, nor all methods which use them).
|
||||
These standard functions are not documented in this manual so please see the STL documentation.
|
||||
The behaviour of all these functions is identical to the behaviour described
|
||||
there.
|
||||
there (except that wxString is sensitive to null character).
|
||||
|
||||
You may notice that wxString sometimes has many functions which do the same
|
||||
thing like, for example, \helpref{Length()}{wxstringlength},
|
||||
|
@@ -523,6 +523,7 @@ public:
|
||||
{ return find_first_of(str.c_str(), nStart); }
|
||||
// same as above
|
||||
size_t find_first_of(const wxChar* sz, size_t nStart = 0) const;
|
||||
size_t find_first_of(const wxChar* sz, size_t nStart, size_t n) const;
|
||||
// same as find(char, size_t)
|
||||
size_t find_first_of(wxChar c, size_t nStart = 0) const
|
||||
{ return find(c, nStart); }
|
||||
@@ -531,6 +532,7 @@ public:
|
||||
{ return find_last_of(str.c_str(), nStart); }
|
||||
// same as above
|
||||
size_t find_last_of (const wxChar* sz, size_t nStart = npos) const;
|
||||
size_t find_last_of(const wxChar* sz, size_t nStart, size_t n) const;
|
||||
// same as above
|
||||
size_t find_last_of(wxChar c, size_t nStart = npos) const
|
||||
{ return rfind(c, nStart); }
|
||||
@@ -542,13 +544,15 @@ public:
|
||||
{ return find_first_not_of(str.c_str(), nStart); }
|
||||
// same as above
|
||||
size_t find_first_not_of(const wxChar* sz, size_t nStart = 0) const;
|
||||
size_t find_first_not_of(const wxChar* sz, size_t nStart, size_t n) const;
|
||||
// same as above
|
||||
size_t find_first_not_of(wxChar ch, size_t nStart = 0) const;
|
||||
// as strcspn()
|
||||
size_t find_last_not_of(const wxStringBase& str, size_t nStart = npos) const
|
||||
{ return find_first_not_of(str.c_str(), nStart); }
|
||||
{ return find_last_not_of(str.c_str(), nStart); }
|
||||
// same as above
|
||||
size_t find_last_not_of(const wxChar* sz, size_t nStart = npos) const;
|
||||
size_t find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const;
|
||||
// same as above
|
||||
size_t find_last_not_of(wxChar ch, size_t nStart = npos) const;
|
||||
|
||||
|
@@ -97,7 +97,7 @@
|
||||
#undef TEST_ALL
|
||||
static const bool TEST_ALL = true;
|
||||
#else
|
||||
#define TEST_HASHSET
|
||||
#define TEST_STRINGS
|
||||
|
||||
static const bool TEST_ALL = false;
|
||||
#endif
|
||||
@@ -6551,6 +6551,20 @@ void is(int line, const wxString& got, const wxString& expected,
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void is(int line, const wxChar* got, const wxChar* expected,
|
||||
const wxString& msg = wxEmptyString)
|
||||
{
|
||||
bool isOk = wxStrcmp( got, expected ) == 0;
|
||||
ok(line, isOk, msg);
|
||||
if( !isOk )
|
||||
{
|
||||
wxPuts(_T("Got: ") + wxString(got));
|
||||
wxPuts(_T("Expected: ") + wxString(expected));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void is(int line, const wxChar& got, const wxChar& expected,
|
||||
const wxString& msg = wxEmptyString)
|
||||
{
|
||||
@@ -6558,11 +6572,26 @@ void is(int line, const wxChar& got, const wxChar& expected,
|
||||
ok(line, isOk, msg);
|
||||
if( !isOk )
|
||||
{
|
||||
wxPuts("Got: " + got);
|
||||
wxPuts("Expected: " + expected);
|
||||
wxPuts(_T("Got: ") + got);
|
||||
wxPuts(_T("Expected: ") + expected);
|
||||
}
|
||||
}
|
||||
|
||||
void is(int line, size_t got, size_t expected,
|
||||
const wxString& msg = wxEmptyString)
|
||||
{
|
||||
bool isOk = got == expected;
|
||||
ok(line, isOk, msg);
|
||||
if( !isOk )
|
||||
{
|
||||
wxPuts(wxString::Format(_T("Got: %ld"), got));
|
||||
wxPuts(wxString::Format(_T("Expected: %ld"), expected));
|
||||
}
|
||||
}
|
||||
|
||||
#define is_m( got, expected, message ) is( __LINE__, (got), (expected), (message) )
|
||||
#define is_nom( got, expected ) is( __LINE__, (got), (expected), wxEmptyString )
|
||||
|
||||
void TestStdString()
|
||||
{
|
||||
wxPuts(_T("*** Testing std::string operations ***\n"));
|
||||
@@ -6652,6 +6681,77 @@ void TestStdString()
|
||||
is( __LINE__, *it2, _T('g') );
|
||||
ok( __LINE__, it3 == s7.end() );
|
||||
|
||||
// find
|
||||
// 0 1 2
|
||||
// 01234567890123456789012345
|
||||
s1 = _T("abcdefgABCDEFGabcABCabcABC");
|
||||
s2 = _T("gAB");
|
||||
|
||||
is_nom( s1.find(_T('A')), 7u );
|
||||
is_nom( s1.find(_T('A'), 7), 7u );
|
||||
is_nom( s1.find(_T('Z')), wxString::npos );
|
||||
is_nom( s1.find(_T('C'), 22), 25u );
|
||||
|
||||
is_nom( s1.find(_T("gAB")), 6u );
|
||||
is_nom( s1.find(_T("gAB"), 7), wxString::npos );
|
||||
is_nom( s1.find(_T("gAB"), 6), 6u );
|
||||
|
||||
is_nom( s1.find(_T("gABZZZ"), 2, 3), 6u );
|
||||
is_nom( s1.find(_T("gABZZZ"), 7, 3), wxString::npos );
|
||||
|
||||
is_nom( s1.find(s2), 6u );
|
||||
is_nom( s1.find(s2, 7), wxString::npos );
|
||||
is_nom( s1.find(s2, 6), 6u );
|
||||
|
||||
// find_first_not_of
|
||||
// 0 1 2 3
|
||||
// 01234567890123456789012345678901234
|
||||
s1 = _T("aaaaaabcdefghlkjiaaaaaabcdbcdbcdbcd");
|
||||
s2 = _T("aaaaaa");
|
||||
|
||||
is_nom( s1.find_first_not_of(_T('a')), 6u );
|
||||
is_nom( s1.find_first_not_of(_T('a'), 7), 7u );
|
||||
is_nom( s2.find_first_not_of(_T('a')), wxString::npos );
|
||||
|
||||
is_nom( s1.find_first_not_of(_T("abde"), 4), 7u );
|
||||
is_nom( s1.find_first_not_of(_T("abde"), 7), 7u );
|
||||
is_nom( s1.find_first_not_of(_T("abcdefghijkl")), wxString::npos );
|
||||
|
||||
is_nom( s1.find_first_not_of(_T("abcdefghi"), 0, 4), 9u );
|
||||
|
||||
// find_first_of
|
||||
is_nom( s1.find_first_of(_T('c')), 7u );
|
||||
is_nom( s1.find_first_of(_T('v')), wxString::npos );
|
||||
is_nom( s1.find_first_of(_T('c'), 10), 24u );
|
||||
|
||||
is_nom( s1.find_first_of(_T("ijkl")), 13u );
|
||||
is_nom( s1.find_first_of(_T("ddcfg"), 17), 24u );
|
||||
is_nom( s1.find_first_of(_T("ddcfga"), 17, 5), 24u );
|
||||
|
||||
// find_last_not_of
|
||||
// 0 1 2 3
|
||||
// 01234567890123456789012345678901234
|
||||
s1 = _T("aaaaaabcdefghlkjiaaaaaabcdbcdbcdbcd");
|
||||
s2 = _T("aaaaaa");
|
||||
|
||||
is_nom( s2.find_last_not_of(_T('a')), wxString::npos );
|
||||
is_nom( s1.find_last_not_of(_T('d')), 33u );
|
||||
is_nom( s1.find_last_not_of(_T('d'), 25), 24u );
|
||||
|
||||
is_nom( s1.find_last_not_of(_T("bcd")), 22u );
|
||||
is_nom( s1.find_last_not_of(_T("abc"), 24), 16u );
|
||||
|
||||
is_nom( s1.find_last_not_of(_T("abcdefghijklmnopqrstuv"), 24, 3), 16u );
|
||||
|
||||
// find_last_of
|
||||
is_nom( s2.find_last_of(_T('c')), wxString::npos );
|
||||
is_nom( s1.find_last_of(_T('a')), 22u );
|
||||
is_nom( s1.find_last_of(_T('b'), 24), 23u );
|
||||
|
||||
is_nom( s1.find_last_of(_T("ijklm")), 16u );
|
||||
is_nom( s1.find_last_of(_T("ijklma"), 33, 4), 16u );
|
||||
is_nom( s1.find_last_of(_T("a"), 17), 17u );
|
||||
|
||||
// test insert
|
||||
s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("aaaa");
|
||||
s9 = s10 = _T("cdefg");
|
||||
@@ -6702,6 +6802,49 @@ void TestStdString()
|
||||
is( __LINE__, s6, s9);
|
||||
is( __LINE__, s7, _T("QWwertyP") );
|
||||
|
||||
// rfind
|
||||
// 0 1 2
|
||||
// 01234567890123456789012345
|
||||
s1 = _T("abcdefgABCDEFGabcABCabcABC");
|
||||
s2 = _T("gAB");
|
||||
|
||||
is_nom( s1.rfind(_T('A')), 23u );
|
||||
is_nom( s1.rfind(_T('A'), 7), 7u );
|
||||
is_nom( s1.rfind(_T('Z')), wxString::npos );
|
||||
is_nom( s1.rfind(_T('C'), 22), 19u );
|
||||
|
||||
is_nom( s1.rfind(_T("cAB")), 22u );
|
||||
is_nom( s1.rfind(_T("cAB"), 15), wxString::npos );
|
||||
is_nom( s1.rfind(_T("cAB"), 21), 16u );
|
||||
|
||||
is_nom( s1.rfind(_T("gABZZZ"), 7, 3), 6u );
|
||||
is_nom( s1.rfind(_T("gABZZZ"), 5, 3), wxString::npos );
|
||||
|
||||
is_nom( s1.rfind(s2), 6u );
|
||||
is_nom( s1.rfind(s2, 5), wxString::npos );
|
||||
is_nom( s1.rfind(s2, 6), 6u );
|
||||
|
||||
// resize
|
||||
s1 = s2 = s3 = s4 = _T("abcABCdefDEF");
|
||||
|
||||
s1.resize( 12 );
|
||||
s2.resize( 10 );
|
||||
s3.resize( 14, _T(' ') );
|
||||
s4.resize( 14, _T('W') );
|
||||
|
||||
is_nom( s1, _T("abcABCdefDEF") );
|
||||
is_nom( s2, _T("abcABCdefD") );
|
||||
is_nom( s3, _T("abcABCdefDEF ") );
|
||||
is_nom( s4, _T("abcABCdefDEFWW") );
|
||||
|
||||
// substr
|
||||
s1 = _T("abcdefgABCDEFG");
|
||||
|
||||
is_nom( s1.substr( 0, 14 ), s1 );
|
||||
is_nom( s1.substr( 1, 13 ), _T("bcdefgABCDEFG") );
|
||||
is_nom( s1.substr( 1, 20 ), _T("bcdefgABCDEFG") );
|
||||
is_nom( s1.substr( 14, 30 ), _T("") );
|
||||
|
||||
wxPuts(_T("*** Testing std::string operations finished ***\n"));
|
||||
}
|
||||
|
||||
|
@@ -482,12 +482,30 @@ size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
|
||||
wxASSERT( str.GetStringData()->IsValid() );
|
||||
wxASSERT( nStart == npos || nStart <= length() );
|
||||
|
||||
// TODO could be made much quicker than that
|
||||
const wxChar *p = c_str() + (nStart == npos ? length() : nStart);
|
||||
while ( p >= c_str() + str.length() ) {
|
||||
if ( wxStrncmp(p - str.length(), str.c_str(), str.length()) == 0 )
|
||||
return p - str.length() - c_str();
|
||||
p--;
|
||||
if ( length() >= str.length() )
|
||||
{
|
||||
// avoids a corner case later
|
||||
if ( length() == 0 && str.length() == 0 )
|
||||
return 0;
|
||||
|
||||
// "top" is the point where search starts from
|
||||
size_t top = length() - str.length();
|
||||
|
||||
if ( nStart == npos )
|
||||
nStart = length() - 1;
|
||||
if ( nStart < top )
|
||||
top = nStart;
|
||||
|
||||
const wxChar *cursor = c_str() + top;
|
||||
do
|
||||
{
|
||||
if ( memcmp(cursor, str.c_str(),
|
||||
str.length() * sizeof(wxChar)) == 0 )
|
||||
{
|
||||
return cursor - c_str();
|
||||
}
|
||||
--cursor;
|
||||
} while ( cursor > c_str() );
|
||||
}
|
||||
|
||||
return npos;
|
||||
@@ -530,11 +548,17 @@ size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart,
|
||||
size_t n) const
|
||||
{
|
||||
return find_first_of(wxStringBase(sz, n), nStart);
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
|
||||
{
|
||||
if ( nStart == npos )
|
||||
{
|
||||
nStart = length();
|
||||
nStart = length() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -542,7 +566,7 @@ size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
|
||||
_T("invalid index in find_last_of()") );
|
||||
}
|
||||
|
||||
for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
|
||||
for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
|
||||
{
|
||||
if ( wxStrchr(sz, *p) )
|
||||
return p - c_str();
|
||||
@@ -551,6 +575,12 @@ size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart,
|
||||
size_t n) const
|
||||
{
|
||||
return find_last_of(wxStringBase(sz, n), nStart);
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
|
||||
{
|
||||
if ( nStart == npos )
|
||||
@@ -566,7 +596,13 @@ size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
|
||||
if ( nAccept >= length() - nStart )
|
||||
return npos;
|
||||
else
|
||||
return nAccept;
|
||||
return nStart + nAccept;
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
|
||||
size_t n) const
|
||||
{
|
||||
return find_first_not_of(wxStringBase(sz, n), nStart);
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
|
||||
@@ -586,14 +622,14 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
|
||||
{
|
||||
if ( nStart == npos )
|
||||
{
|
||||
nStart = length();
|
||||
nStart = length() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT( nStart <= length() );
|
||||
}
|
||||
|
||||
for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
|
||||
for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
|
||||
{
|
||||
if ( !wxStrchr(sz, *p) )
|
||||
return p - c_str();
|
||||
@@ -602,18 +638,24 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart,
|
||||
size_t n) const
|
||||
{
|
||||
return find_last_not_of(wxStringBase(sz, n), nStart);
|
||||
}
|
||||
|
||||
size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
|
||||
{
|
||||
if ( nStart == npos )
|
||||
{
|
||||
nStart = length();
|
||||
nStart = length() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT( nStart <= length() );
|
||||
}
|
||||
|
||||
for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
|
||||
for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
|
||||
{
|
||||
if ( *p != ch )
|
||||
return p - c_str();
|
||||
@@ -2172,6 +2214,13 @@ void wxArrayString::Remove(const wxChar *sz)
|
||||
RemoveAt(iIndex);
|
||||
}
|
||||
|
||||
void wxArrayString::assign(const_iterator first, const_iterator last)
|
||||
{
|
||||
reserve(last - first);
|
||||
for(; first != last; ++first)
|
||||
push_back(*first);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// sorting
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user